Handle not found error on taking snapshot

If there is a request to create a snapshot of an instance and
another request to delete the instance at the same time, the
snapshot task might fail with libvirt error and this error
is not handled correctly by compute manager. As a result,
tracestack was printed in the compute log.

This patch fixes it by handling libvirt exception during live
snapshot and raise instance not found exception if the libvirt
exception is raised due to domain not found.

Change-Id: I585b7b03753ed1d28a313ce443e6918687d76a8b
Closes-Bug: #1722571
This commit is contained in:
Hongbin Lu 2017-10-10 23:05:14 +00:00 committed by Hongbin Lu
parent 81f0ca1352
commit 9ef56fa866
2 changed files with 32 additions and 0 deletions

View File

@ -19911,6 +19911,24 @@ class LibvirtSnapshotTests(_BaseSnapshotTests):
self._test_snapshot(disk_format='qcow2',
extra_properties=extra_properties)
@mock.patch.object(host.Host, 'get_guest')
@mock.patch.object(host.Host, 'write_instance_config')
def test_failing_domain_not_found(self, mock_write_config, mock_get_guest):
self.flags(disable_libvirt_livesnapshot=False, group='workarounds')
mock_dev = mock.Mock(spec=libvirt_guest.BlockDevice)
mock_guest = mock.Mock(spec=libvirt_guest.Guest)
mock_guest.get_power_state.return_value = power_state.RUNNING
mock_guest.get_block_device.return_value = mock_dev
mock_guest._domain = mock.Mock()
mock_get_guest.return_value = mock_guest
ex = fakelibvirt.make_libvirtError(
fakelibvirt.libvirtError,
"No such domain",
error_code=fakelibvirt.VIR_ERR_NO_DOMAIN)
mock_dev.rebase.side_effect = ex
self.assertRaises(exception.InstanceNotFound, self._test_snapshot,
disk_format='qcow2')
@mock.patch.object(rbd_utils, 'RBDDriver')
@mock.patch.object(rbd_utils, 'rbd')
def test_raw_with_rbd_clone(self, mock_rbd, mock_driver):

View File

@ -1837,6 +1837,20 @@ class LibvirtDriver(driver.ComputeDriver):
root_disk.snapshot_extract(out_path, image_format)
LOG.info("Snapshot extracted, beginning image upload",
instance=instance)
except libvirt.libvirtError as ex:
error_code = ex.get_error_code()
if error_code == libvirt.VIR_ERR_NO_DOMAIN:
LOG.info('Instance %(instance_name)s disappeared '
'while taking snapshot of it: [Error Code '
'%(error_code)s] %(ex)s',
{'instance_name': instance.name,
'error_code': error_code,
'ex': ex},
instance=instance)
raise exception.InstanceNotFound(
instance_id=instance.uuid)
else:
raise
finally:
self._snapshot_domain(context, live_snapshot, virt_dom,
state, instance)