storage/callback: async Volume.export() & added Volume.export_end()
Fixes QubesOS/qubes-issues#5935
This commit is contained in:
parent
42d62bb47e
commit
56c8d9d039
@ -21,6 +21,8 @@
|
|||||||
"pre_volume_import": "Called before importing a volume from elsewhere. Same as above otherwise.",
|
"pre_volume_import": "Called before importing a volume from elsewhere. Same as above otherwise.",
|
||||||
"pre_volume_import_data": "Called before importing a volume from elsewhere. Same as above otherwise.",
|
"pre_volume_import_data": "Called before importing a volume from elsewhere. Same as above otherwise.",
|
||||||
"post_volume_import_data_end": "Called after finishing an `import_data` action. Same as above otherwise.",
|
"post_volume_import_data_end": "Called after finishing an `import_data` action. Same as above otherwise.",
|
||||||
|
"pre_volume_export": "Called before exporting a volume. Same as above otherwise.",
|
||||||
|
"post_volume_export_end": "Called after a volume export completed. Same as above otherwise.",
|
||||||
"description": "Optional description for your personal reference."
|
"description": "Optional description for your personal reference."
|
||||||
},
|
},
|
||||||
"testing-fail-missing-all":
|
"testing-fail-missing-all":
|
||||||
|
@ -23,7 +23,6 @@ import logging
|
|||||||
import subprocess
|
import subprocess
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
import threading
|
|
||||||
from shlex import quote
|
from shlex import quote
|
||||||
from qubes.utils import coro_maybe
|
from qubes.utils import coro_maybe
|
||||||
|
|
||||||
@ -234,7 +233,7 @@ class CallbackPool(qubes.storage.Pool):
|
|||||||
raise qubes.storage.StoragePoolException('The class %s must be a subclass of qubes.storage.Pool.' % cls)
|
raise qubes.storage.StoragePoolException('The class %s must be a subclass of qubes.storage.Pool.' % cls)
|
||||||
|
|
||||||
self._cb_requires_init = self._check_init() #: Boolean indicating whether late storage initialization yet has to be done or not.
|
self._cb_requires_init = self._check_init() #: Boolean indicating whether late storage initialization yet has to be done or not.
|
||||||
self._cb_init_lock = threading.Lock() #: Lock ensuring that late storage initialization is only run exactly once. Currently a `threading.Lock()` to make it accessible from synchronous code as well.
|
self._cb_init_lock = asyncio.Lock() #: Lock ensuring that late storage initialization is only run exactly once.
|
||||||
bdriver_args = self._cb_conf.get('bdriver_args', {})
|
bdriver_args = self._cb_conf.get('bdriver_args', {})
|
||||||
self._cb_impl = cls(name=name, **bdriver_args) #: Instance of the backend pool driver.
|
self._cb_impl = cls(name=name, **bdriver_args) #: Instance of the backend pool driver.
|
||||||
|
|
||||||
@ -254,20 +253,12 @@ class CallbackPool(qubes.storage.Pool):
|
|||||||
''' Late storage initialization on first use for e.g. decryption on first usage request.
|
''' Late storage initialization on first use for e.g. decryption on first usage request.
|
||||||
:param callback: Whether to trigger the `pre_sinit` callback or not.
|
:param callback: Whether to trigger the `pre_sinit` callback or not.
|
||||||
'''
|
'''
|
||||||
with self._cb_init_lock:
|
with (yield from self._cb_init_lock):
|
||||||
if self._cb_requires_init:
|
if self._cb_requires_init:
|
||||||
if callback:
|
if callback:
|
||||||
yield from self._callback('pre_sinit')
|
yield from self._callback('pre_sinit')
|
||||||
self._cb_requires_init = False
|
self._cb_requires_init = False
|
||||||
|
|
||||||
def _init_nocoro(self, callback=True):
|
|
||||||
''' `_init()` in synchronous code. '''
|
|
||||||
with self._cb_init_lock:
|
|
||||||
if self._cb_requires_init:
|
|
||||||
if callback:
|
|
||||||
self._callback_nocoro('pre_sinit')
|
|
||||||
self._cb_requires_init = False
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _assert_initialized(self, **kwargs):
|
def _assert_initialized(self, **kwargs):
|
||||||
if self._cb_requires_init:
|
if self._cb_requires_init:
|
||||||
@ -571,12 +562,18 @@ class CallbackVolume(qubes.storage.Volume):
|
|||||||
return None
|
return None
|
||||||
return self._cb_impl.block_device()
|
return self._cb_impl.block_device()
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
def export(self):
|
def export(self):
|
||||||
# pylint: disable=protected-access
|
yield from self._assert_initialized()
|
||||||
#TODO: once this becomes a coroutine in the Volume class, avoid the below blocking & potentially exception-throwing code; maybe also add a callback
|
yield from self._callback('pre_volume_export')
|
||||||
if self._cb_pool._cb_requires_init:
|
return (yield from coro_maybe(self._cb_impl.export()))
|
||||||
self._cb_pool._init_nocoro()
|
|
||||||
return self._cb_impl.export()
|
@asyncio.coroutine
|
||||||
|
def export_end(self, path):
|
||||||
|
yield from self._assert_initialized()
|
||||||
|
ret = yield from coro_maybe(self._cb_impl.export_end(path))
|
||||||
|
yield from self._callback('post_volume_export_end', cb_args=[path])
|
||||||
|
return ret
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def verify(self):
|
def verify(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user