Encode libvirt domain XML in UTF-8

Creating a VM with a non-ASCII name results in an error. Resolve
this by encoding the libvirt domain XML in utf-8.

Co-Authored-By: Yikun Jiang <yikunkero@gmail.com>

Closes-Bug: #1730756
Change-Id: I7afce618deca3baaa96605a6b48c1c2ef4a5f2a5
This commit is contained in:
JiangPF 2018-01-31 18:36:33 +08:00 committed by Matt Riedemann
parent b7de3eca6d
commit 784c0ecdc3
3 changed files with 40 additions and 5 deletions

View File

@ -14764,7 +14764,12 @@ class LibvirtConnTestCase(test.NoDBTestCase,
fake_xml = "<test>this is a test</test>"
def fake_defineXML(xml):
self.assertEqual(fake_xml, xml)
# In py2 env, xml is encoded in write_instance_config use
# encodeutils.safe_encode, it will be decode text before encoding
if six.PY2:
self.assertEqual(fake_safe_decode(fake_xml), xml)
else:
self.assertEqual(fake_xml, xml)
raise fakelibvirt.libvirtError('virDomainDefineXML() failed')
def fake_safe_decode(text, *args, **kwargs):
@ -15599,20 +15604,22 @@ class LibvirtConnTestCase(test.NoDBTestCase,
create=True) as mock_define:
srcfile = "/first/path"
dstfile = "/second/path"
orig_xml = six.text_type(mock.sentinel.orig_xml)
new_xml = six.text_type(mock.sentinel.new_xml)
mock_dom.XMLDesc.return_value = mock.sentinel.orig_xml
mock_dom.XMLDesc.return_value = orig_xml
mock_dom.isPersistent.return_value = True
def fake_rebase_success(*args, **kwargs):
# Make sure the XML is set after the rebase so we know
# get_xml_desc was called after the update.
mock_dom.XMLDesc.return_value = mock.sentinel.new_xml
mock_dom.XMLDesc.return_value = new_xml
if not fail:
mock_dom.blockRebase.side_effect = fake_rebase_success
# If the swap succeeds, make sure we use the new XML to
# redefine the domain.
expected_xml = mock.sentinel.new_xml
expected_xml = new_xml
else:
if resize:
mock_dom.blockResize.side_effect = test.TestingException()
@ -15622,7 +15629,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
expected_exception = exception.VolumeRebaseFailed
# If the swap fails, make sure we use the original domain XML
# to redefine the domain.
expected_xml = mock.sentinel.orig_xml
expected_xml = orig_xml
# Run the swap volume code.
mock_conf = mock.MagicMock(source_type=source_type,

View File

@ -775,6 +775,31 @@ Active: 8381604 kB
mock_defineXML.assert_called_once_with(fake_dom_xml)
self.assertIsInstance(guest, libvirt_guest.Guest)
def test_write_instance_config_unicode(self):
fake_dom_xml = u"""
<domain type='kvm'>
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
<devices>
<disk type='file'>
<source file='\u4e2d\u6587'/>
</disk>
</devices>
</domain>
"""
def emulate_defineXML(xml):
conn = self.host.get_connection()
# Emulate the decoding behavior of defineXML in Python2
if six.PY2:
xml = xml.decode("utf-8")
dom = fakelibvirt.Domain(conn, xml, False)
return dom
with mock.patch.object(fakelibvirt.virConnect, "defineXML"
) as mock_defineXML:
mock_defineXML.side_effect = emulate_defineXML
guest = self.host.write_instance_config(fake_dom_xml)
self.assertIsInstance(guest, libvirt_guest.Guest)
@mock.patch.object(fakelibvirt.virConnect, "nodeDeviceLookupByName")
def test_device_lookup_by_name(self, mock_nodeDeviceLookupByName):
self.host.device_lookup_by_name("foo")

View File

@ -38,6 +38,7 @@ from eventlet import greenthread
from eventlet import patcher
from eventlet import tpool
from oslo_log import log as logging
from oslo_utils import encodeutils
from oslo_utils import excutils
from oslo_utils import importutils
from oslo_utils import units
@ -823,6 +824,8 @@ class Host(object):
:returns: an instance of Guest
"""
if six.PY2:
xml = encodeutils.safe_encode(xml)
domain = self.get_connection().defineXML(xml)
return libvirt_guest.Guest(domain)