storage: allow import_data and import_data_end be coroutines

On some storage pools this operation can also be time consuming - for
example require creating temporary volume, and volume.create() already
can be a coroutine.
This is also requirement for making common code used by start()/create()
etc be a coroutine, otherwise neither of them can be and will block
other operations.

Related to QubesOS/qubes-issues#4283
This commit is contained in:
Marek Marczykowski-Górecki 2018-10-19 01:29:03 +02:00
父節點 295705a708
當前提交 6170edb291
沒有發現已知的金鑰在資料庫的簽署中
GPG 金鑰 ID: 063938BA42CFA724
共有 3 個檔案被更改,包括 21 行新增6 行删除

查看文件

@ -479,7 +479,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
if not self.dest.is_halted(): if not self.dest.is_halted():
raise qubes.exc.QubesVMNotHaltedError(self.dest) raise qubes.exc.QubesVMNotHaltedError(self.dest)
path = self.dest.storage.import_data(self.arg) path = yield from self.dest.storage.import_data(self.arg)
assert ' ' not in path assert ' ' not in path
size = self.dest.volumes[self.arg].size size = self.dest.volumes[self.arg].size

查看文件

@ -68,7 +68,8 @@ class QubesInternalAPI(qubes.api.AbstractQubesAPI):
success = untrusted_payload == b'ok' success = untrusted_payload == b'ok'
try: try:
self.dest.storage.import_data_end(self.arg, success=success) yield from self.dest.storage.import_data_end(self.arg,
success=success)
except: except:
self.dest.fire_event('domain-volume-import-end', volume=self.arg, self.dest.fire_event('domain-volume-import-end', volume=self.arg,
success=False) success=False)

查看文件

@ -198,6 +198,8 @@ class Volume:
volume data require something more than just writing to a file ( volume data require something more than just writing to a file (
for example connecting to some other domain, or converting data for example connecting to some other domain, or converting data
on the fly), the returned path may be a pipe. on the fly), the returned path may be a pipe.
This can be implemented as a coroutine.
''' '''
raise self._not_implemented("import") raise self._not_implemented("import")
@ -207,6 +209,8 @@ class Volume:
This method is called regardless the operation was successful or not. This method is called regardless the operation was successful or not.
This can be implemented as a coroutine.
:param success: True if data import was successful, otherwise False :param success: True if data import was successful, otherwise False
''' '''
# by default do nothing # by default do nothing
@ -654,24 +658,34 @@ class Storage:
return self.vm.volumes[volume].export() return self.vm.volumes[volume].export()
@asyncio.coroutine
def import_data(self, volume): def import_data(self, volume):
''' Helper function to import volume data (pool.import_data(volume))''' ''' Helper function to import volume data (pool.import_data(volume))'''
assert isinstance(volume, (Volume, str)), \ assert isinstance(volume, (Volume, str)), \
"You need to pass a Volume or pool name as str" "You need to pass a Volume or pool name as str"
if isinstance(volume, Volume): if isinstance(volume, Volume):
return volume.import_data() ret = volume.import_data()
else:
ret = self.vm.volumes[volume].import_data()
return self.vm.volumes[volume].import_data() if asyncio.iscoroutine(ret):
ret = yield from ret
return ret
@asyncio.coroutine
def import_data_end(self, volume, success): def import_data_end(self, volume, success):
''' Helper function to finish/cleanup data import ''' Helper function to finish/cleanup data import
(pool.import_data_end( volume))''' (pool.import_data_end( volume))'''
assert isinstance(volume, (Volume, str)), \ assert isinstance(volume, (Volume, str)), \
"You need to pass a Volume or pool name as str" "You need to pass a Volume or pool name as str"
if isinstance(volume, Volume): if isinstance(volume, Volume):
return volume.import_data_end(success=success) ret = volume.import_data_end(success=success)
else:
ret = self.vm.volumes[volume].import_data_end(success=success)
return self.vm.volumes[volume].import_data_end(success=success) if asyncio.iscoroutine(ret):
ret = yield from ret
return ret
class VolumesCollection: class VolumesCollection: