libvirt: properly decode error message from qemu guest agent

Some of error messages from qemu-guest-agent is
localized encoding.
We may get GB2312(Chinese charactors) from qga's error message
from a Chinese version of Windows.

nova didn't cover this senario, we may get errors like:
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6
    in position 138: ordinal not in range(128)

This patch will fix this issue by exception_to_unicode

Closes-bug: #1727643

Change-Id: I3b8bfaec8af0e9b4859dcfe7e35fc5bb26c208dc
Signed-off-by: Chen Hanxiao <chenhx@certusnet.com.cn>
(cherry picked from commit 13418faa17)
This commit is contained in:
Chen Hanxiao 2017-10-12 18:52:42 +08:00 committed by Matt Riedemann
parent 191faf3124
commit 7687dadccf
2 changed files with 25 additions and 2 deletions

View File

@ -1393,6 +1393,26 @@ 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_error_with_unicode(
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)
mock_guest.set_user_password.side_effect = (
fakelibvirt.libvirtError(
b"failed: \xe9\x94\x99\xe8\xaf\xaf\xe3\x80\x82"))
mock_get_guest.return_value = mock_guest
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
self.assertRaises(exception.NovaException,
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

@ -51,6 +51,7 @@ from oslo_concurrency import processutils
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_service import loopingcall
from oslo_utils import encodeutils
from oslo_utils import excutils
from oslo_utils import fileutils
from oslo_utils import importutils
@ -1816,9 +1817,10 @@ class LibvirtDriver(driver.ComputeDriver):
guest.set_user_password(user, new_pass)
except libvirt.libvirtError as ex:
error_code = ex.get_error_code()
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')
% {'user': user, 'error_code': error_code, 'ex': ex})
% {'user': user, 'error_code': error_code, 'ex': err_msg})
raise exception.InternalError(msg)
def _can_quiesce(self, instance, image_meta):
@ -1842,10 +1844,11 @@ class LibvirtDriver(driver.ComputeDriver):
guest.thaw_filesystems()
except libvirt.libvirtError as ex:
error_code = ex.get_error_code()
err_msg = encodeutils.exception_to_unicode(ex)
msg = (_('Error from libvirt while quiescing %(instance_name)s: '
'[Error Code %(error_code)s] %(ex)s')
% {'instance_name': instance.name,
'error_code': error_code, 'ex': ex})
'error_code': error_code, 'ex': err_msg})
raise exception.InternalError(msg)
def quiesce(self, context, instance, image_meta):