Parse <emulator> elements from virConnectGetCapabilities()
Extend the associated LibvirtConfigCapsGuest class so that it can parse and store <emulator> elements in a way which can be reused in subsequent commits by callers of virConnectGetDomainCapabilities(). Ongoing / future work such as SEV[0] and the move of the default machine type to q35[1] will need to invoke virConnectGetDomainCapabilities() in order to check whether SEV or q35 respectively are supported. However this API requires 5 parameters[2]: 1) the path to the emulator binary (e.g. qemu-system-x86_64) 2) the domain architecture 3) the machine type 4) the virtualization type 5) flags (not used yet) 4) is determined by CONF.libvirt.virt_type. The caller of virConnectGetDomainCapabilities() can decide which combinations of 2) and 3) type to pass[3], but still needs to know 1). Once 2) and 3) are known, this can be determined from the <emulator> elements returned by libvirt's virConnectGetCapabilities() API[4]. nova already calls this and parses the response into a LibvirtConfigCaps object. However currently the parser ignores the <emulator> elements. This patch fixes that. [0] https://specs.openstack.org/openstack/nova-specs/specs/stein/approved/amd-sev-libvirt-support.html [1] https://blueprints.launchpad.net/nova/+spec/handle-default-machine-type-as-q35 [2] https://libvirt.org/html/libvirt-libvirt-domain.html#virConnectGetDomainCapabilities [3] Calling virConnectGetDomainCapabilities for every machine type is most likely overkill: https://bugzilla.redhat.com/show_bug.cgi?id=1683471#c7 [4] https://libvirt.org/formatcaps.html#elementGuest blueprint: amd-sev-libvirt-support blueprint: handle-default-machine-type-as-q35 Change-Id: Ibdc88bc5e0a214bff36a8351a1b76980f7015d16
This commit is contained in:
parent
ffd81eb107
commit
48d6753d37
|
@ -115,11 +115,19 @@ class LibvirtConfigCapsTest(LibvirtConfigBaseTest):
|
|||
</host>
|
||||
<guest>
|
||||
<os_type>hvm</os_type>
|
||||
<arch name='x86_64'/>
|
||||
<arch name='x86_64'>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
<domain type="qemu" />
|
||||
<domain type="kvm">
|
||||
<emulator>/usr/bin/qemu-kvm</emulator>
|
||||
</domain>
|
||||
</arch>
|
||||
</guest>
|
||||
<guest>
|
||||
<os_type>hvm</os_type>
|
||||
<arch name='i686'/>
|
||||
<arch name='i686'>
|
||||
<emulator>/usr/bin/qemu-system-i386</emulator>
|
||||
</arch>
|
||||
</guest>
|
||||
</capabilities>"""
|
||||
|
||||
|
@ -128,6 +136,17 @@ class LibvirtConfigCapsTest(LibvirtConfigBaseTest):
|
|||
|
||||
self.assertIsInstance(obj.host, config.LibvirtConfigCapsHost)
|
||||
self.assertEqual(obj.host.uuid, "c7a5fdbd-edaf-9455-926a-d65c16db1809")
|
||||
self.assertEqual(2, len(obj.guests))
|
||||
for guest in obj.guests:
|
||||
self.assertIsInstance(guest, config.LibvirtConfigCapsGuest)
|
||||
self.assertEqual('hvm', guest.ostype)
|
||||
|
||||
self.assertEqual('x86_64', obj.guests[0].arch)
|
||||
self.assertEqual('i686', obj.guests[1].arch)
|
||||
self.assertEqual('/usr/bin/qemu-system-x86_64', obj.guests[0].emulator)
|
||||
self.assertNotIn('qemu', obj.guests[0].domemulator)
|
||||
self.assertEqual('/usr/bin/qemu-kvm', obj.guests[0].domemulator['kvm'])
|
||||
self.assertEqual('/usr/bin/qemu-system-i386', obj.guests[1].emulator)
|
||||
|
||||
xmlout = obj.to_xml()
|
||||
|
||||
|
|
|
@ -304,6 +304,21 @@ class LibvirtConfigCapsGuest(LibvirtConfigObject):
|
|||
self.ostype = None
|
||||
self.domtype = list()
|
||||
|
||||
# Track <emulator> values, which we need in order to be able
|
||||
# to call virConnectGetDomainCapabilities() - typically
|
||||
# something like '/usr/bin/qemu-system-i386'.
|
||||
#
|
||||
# Firstly we track the default for any <domain> child without
|
||||
# its own <emulator> sub-child:
|
||||
self.emulator = None
|
||||
#
|
||||
# Also per-<domain> overrides for the default in self.emulator.
|
||||
# The dict maps domain types such as 'kvm' to the emulator
|
||||
# path for that domain type. Note that these overrides come
|
||||
# from <emulator> elements under each <domain>; there is no
|
||||
# <domemulator> element.
|
||||
self.domemulator = dict()
|
||||
|
||||
def parse_dom(self, xmldoc):
|
||||
super(LibvirtConfigCapsGuest, self).parse_dom(xmldoc)
|
||||
|
||||
|
@ -312,9 +327,18 @@ class LibvirtConfigCapsGuest(LibvirtConfigObject):
|
|||
self.ostype = c.text
|
||||
elif c.tag == "arch":
|
||||
self.arch = c.get("name")
|
||||
for sc in c.getchildren():
|
||||
if sc.tag == "domain":
|
||||
self.domtype.append(sc.get("type"))
|
||||
for ac in c.getchildren():
|
||||
if ac.tag == "domain":
|
||||
self.parse_domain(ac)
|
||||
elif ac.tag == "emulator":
|
||||
self.emulator = ac.text
|
||||
|
||||
def parse_domain(self, domxml):
|
||||
domtype = domxml.get("type")
|
||||
self.domtype.append(domtype)
|
||||
for dc in domxml.getchildren():
|
||||
if dc.tag == "emulator":
|
||||
self.domemulator[domtype] = dc.text
|
||||
|
||||
def format_dom(self):
|
||||
caps = super(LibvirtConfigCapsGuest, self).format_dom()
|
||||
|
@ -323,9 +347,14 @@ class LibvirtConfigCapsGuest(LibvirtConfigObject):
|
|||
caps.append(self._text_node("os_type", self.ostype))
|
||||
if self.arch:
|
||||
arch = etree.Element("arch", name=self.arch)
|
||||
if self.emulator is not None:
|
||||
arch.append(self._text_node("emulator", self.emulator))
|
||||
for dt in self.domtype:
|
||||
dte = etree.Element("domain")
|
||||
dte.set("type", dt)
|
||||
if dt in self.domemulator:
|
||||
dte.append(self._text_node("emulator",
|
||||
self.domemulator[dt]))
|
||||
arch.append(dte)
|
||||
caps.append(arch)
|
||||
|
||||
|
|
Loading…
Reference in New Issue