storage: factor out _wait_and_reraise(); fix clone/create
_wait_and_reraise() is similar to asyncio.gather(), but it preserves the current behavior of waiting for all futures and only _then_ reraising the first exception (if there is any) in line. Also switch Storage.create() and Storage.clone() to _wait_and_reraise(). Previously, they called asyncio.wait() and implicitly swallowed all exceptions.
This commit is contained in:
parent
d33bd3f2b6
commit
d181bf1aa4
@ -509,8 +509,7 @@ class Storage:
|
|||||||
ret = volume.create()
|
ret = volume.create()
|
||||||
if asyncio.iscoroutine(ret):
|
if asyncio.iscoroutine(ret):
|
||||||
coros.append(ret)
|
coros.append(ret)
|
||||||
if coros:
|
yield from _wait_and_reraise(coros)
|
||||||
yield from asyncio.wait(coros)
|
|
||||||
|
|
||||||
os.umask(old_umask)
|
os.umask(old_umask)
|
||||||
|
|
||||||
@ -552,7 +551,7 @@ class Storage:
|
|||||||
|
|
||||||
self.vm.volumes = {}
|
self.vm.volumes = {}
|
||||||
with VmCreationManager(self.vm):
|
with VmCreationManager(self.vm):
|
||||||
yield from asyncio.wait([self.clone_volume(src_vm, vol_name)
|
yield from _wait_and_reraise([self.clone_volume(src_vm, vol_name)
|
||||||
for vol_name in self.vm.volume_config.keys()])
|
for vol_name in self.vm.volume_config.keys()])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -584,11 +583,7 @@ class Storage:
|
|||||||
ret = volume.verify()
|
ret = volume.verify()
|
||||||
if asyncio.iscoroutine(ret):
|
if asyncio.iscoroutine(ret):
|
||||||
futures.append(ret)
|
futures.append(ret)
|
||||||
if futures:
|
yield from _wait_and_reraise(futures)
|
||||||
done, _ = yield from asyncio.wait(futures)
|
|
||||||
for task in done:
|
|
||||||
# re-raise any exception from async task
|
|
||||||
task.result()
|
|
||||||
self.vm.fire_event('domain-verify-files')
|
self.vm.fire_event('domain-verify-files')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -608,14 +603,10 @@ class Storage:
|
|||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
self.vm.log.exception("Failed to remove volume %s", name, e)
|
self.vm.log.exception("Failed to remove volume %s", name, e)
|
||||||
|
|
||||||
if futures:
|
try:
|
||||||
try:
|
yield from _wait_and_reraise(futures)
|
||||||
done, _ = yield from asyncio.wait(futures)
|
except (IOError, OSError) as e:
|
||||||
for task in done:
|
self.vm.log.exception("Failed to remove some volume", e)
|
||||||
# re-raise any exception from async task
|
|
||||||
task.result()
|
|
||||||
except (IOError, OSError) as e:
|
|
||||||
self.vm.log.exception("Failed to remove some volume", e)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def start(self):
|
def start(self):
|
||||||
@ -626,11 +617,7 @@ class Storage:
|
|||||||
if asyncio.iscoroutine(ret):
|
if asyncio.iscoroutine(ret):
|
||||||
futures.append(ret)
|
futures.append(ret)
|
||||||
|
|
||||||
if futures:
|
yield from _wait_and_reraise(futures)
|
||||||
done, _ = yield from asyncio.wait(futures)
|
|
||||||
for task in done:
|
|
||||||
# re-raise any exception from async task
|
|
||||||
task.result()
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@ -641,11 +628,7 @@ class Storage:
|
|||||||
if asyncio.iscoroutine(ret):
|
if asyncio.iscoroutine(ret):
|
||||||
futures.append(ret)
|
futures.append(ret)
|
||||||
|
|
||||||
if futures:
|
yield from _wait_and_reraise(futures)
|
||||||
done, _ = yield from asyncio.wait(futures)
|
|
||||||
for task in done:
|
|
||||||
# re-raise any exception from async task
|
|
||||||
task.result()
|
|
||||||
|
|
||||||
def unused_frontend(self):
|
def unused_frontend(self):
|
||||||
''' Find an unused device name '''
|
''' Find an unused device name '''
|
||||||
@ -845,6 +828,14 @@ class Pool:
|
|||||||
return NotImplementedError(msg)
|
return NotImplementedError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _wait_and_reraise(futures):
|
||||||
|
if futures:
|
||||||
|
done, _ = yield from asyncio.wait(futures)
|
||||||
|
for task in done: # (re-)raise first exception in line
|
||||||
|
task.result()
|
||||||
|
|
||||||
|
|
||||||
def _sanitize_config(config):
|
def _sanitize_config(config):
|
||||||
''' Helper function to convert types to appropriate strings
|
''' Helper function to convert types to appropriate strings
|
||||||
''' # FIXME: find another solution for serializing basic types
|
''' # FIXME: find another solution for serializing basic types
|
||||||
|
Loading…
Reference in New Issue
Block a user