libvirt: throw NotImplementedError if qga is not responsive when setting password

If qemu guest agent is not reponsive when setting admin password,
an InternalError will be thrown by nova,
then the VM state will be set to ERROR.

Actually we did nothing to VMs as qga did not answer our request,
such as qga is crashed/halt, etc.
In this kind of senario, libvirt will throw VIR_ERR_AGENT_UNRESPONSIVE
to us by an error code.
We should check the error code return by libvirt and
throw a NotImplementedError, which we've already expected
in compute.manager.
Other cases like qga got our request
but failed to do its work should follow what we used to.

This patch checks the return code from libvirt.
If got VIR_ERR_AGENT_UNRESPONSIVE,
then throws NotImplementedError.

Change-Id: I4603711c435e15593e4a979906a12b560737bd77
Signed-off-by: Chen Hanxiao <chenhx@certusnet.com.cn>
This commit is contained in:
Chen Hanxiao 2017-11-29 17:45:29 +08:00
parent 3cec0cb584
commit c32c6eb2cd
2 changed files with 27 additions and 0 deletions

View File

@ -1421,6 +1421,28 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertRaises(exception.NovaException,
drvr.set_admin_password, instance, "123")
@mock.patch('nova.utils.get_image_from_system_metadata')
@mock.patch.object(host.Host,
'has_min_version', return_value=True)
@mock.patch('nova.virt.libvirt.host.Host.get_guest')
def test_set_admin_password_not_implemented(
self, mock_get_guest, ver, mock_image):
self.flags(virt_type='kvm', group='libvirt')
instance = objects.Instance(**self.test_instance)
mock_image.return_value = {"properties": {
"hw_qemu_guest_agent": "yes"}}
mock_guest = mock.Mock(spec=libvirt_guest.Guest)
not_implemented = fakelibvirt.make_libvirtError(
fakelibvirt.libvirtError,
"Guest agent disappeared while executing command",
error_code=fakelibvirt.VIR_ERR_AGENT_UNRESPONSIVE)
mock_guest.set_user_password.side_effect = not_implemented
mock_get_guest.return_value = mock_guest
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
self.assertRaises(NotImplementedError,
drvr.set_admin_password, instance, "123")
@mock.patch.object(objects.Service, 'save')
@mock.patch.object(objects.Service, 'get_by_compute_host')
def test_set_host_enabled_with_disable(self, mock_svc, mock_save):

View File

@ -1832,6 +1832,11 @@ class LibvirtDriver(driver.ComputeDriver):
guest.set_user_password(user, new_pass)
except libvirt.libvirtError as ex:
error_code = ex.get_error_code()
if error_code == libvirt.VIR_ERR_AGENT_UNRESPONSIVE:
LOG.debug('Failed to set password: QEMU agent unresponsive',
instance_uuid=instance.uuid)
raise NotImplementedError()
err_msg = encodeutils.exception_to_unicode(ex)
msg = (_('Error from libvirt while set password for username '
'"%(user)s": [Error Code %(error_code)s] %(ex)s')