From 272407be59a9de094fa73a557d0823adf03b506b Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 19 Jun 2012 14:27:49 +0100 Subject: [PATCH] Add libvirt config classes for handling capabilities XML doc Libvirt exposes the host/hypervisor features using an XML schema known as "capabilities". Currently the libvirt driver code just parses this in an adhoc manner using xpath queries. This change provides a handful of classes LibvirtConfigCaps, LibvirtConfigCapsHost and LibvirtConfigCapsGuest for maintaining an object based representation of the capabilities. The LibvirtConfigCapsHost class also uses the existing LibvirtConfigCPU class Fixes: bug #1003373 Implements: blueprint libvirt-xml-cpu-model Change-Id: Ie962c6378b0da09eddc75983d4824a226ed1c25e Signed-off-by: Daniel P. Berrange --- nova/tests/test_libvirt_config.py | 35 ++++++++++ nova/virt/libvirt/config.py | 112 ++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/nova/tests/test_libvirt_config.py b/nova/tests/test_libvirt_config.py index 59ed88e1ce01..55f5528c759b 100644 --- a/nova/tests/test_libvirt_config.py +++ b/nova/tests/test_libvirt_config.py @@ -59,6 +59,41 @@ class LibvirtConfigTest(LibvirtConfigBaseTest): obj.parse_str(inxml) +class LibvirtConfigCapsTest(LibvirtConfigBaseTest): + + def test_config_host(self): + xmlin = """ + + + + x86_64 + Opteron_G3 + AMD + + + + + + + hvm + + + + hvm + + + """ + + obj = config.LibvirtConfigCaps() + obj.parse_str(xmlin) + + self.assertEqual(type(obj.host), config.LibvirtConfigCapsHost) + + xmlout = obj.to_xml() + + self.assertXmlEqual(xmlin, xmlout) + + class LibvirtConfigGuestTimerTest(LibvirtConfigBaseTest): def test_config_platform(self): obj = config.LibvirtConfigGuestTimer() diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index b432b860fd48..edde66d7c4a0 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -67,6 +67,94 @@ class LibvirtConfigObject(object): return xml_str +class LibvirtConfigCaps(LibvirtConfigObject): + + def __init__(self, **kwargs): + super(LibvirtConfigCaps, self).__init__(root_name="capabilities", + **kwargs) + self.host = None + self.guests = [] + + def parse_dom(self, xmldoc): + super(LibvirtConfigCaps, self).parse_dom(xmldoc) + + for c in xmldoc.getchildren(): + if c.tag == "host": + host = LibvirtConfigCapsHost() + host.parse_dom(c) + self.host = host + elif c.tag == "guest": + guest = LibvirtConfigCapsGuest() + guest.parse_dom(c) + self.guests.append(guest) + + def format_dom(self): + caps = super(LibvirtConfigCaps, self).format_dom() + + if self.host: + caps.append(self.host.format_dom()) + for g in self.guests: + caps.append(g.format_dom()) + + return caps + + +class LibvirtConfigCapsHost(LibvirtConfigObject): + + def __init__(self, **kwargs): + super(LibvirtConfigCapsHost, self).__init__(root_name="host", + **kwargs) + + self.cpu = None + + def parse_dom(self, xmldoc): + super(LibvirtConfigCapsHost, self).parse_dom(xmldoc) + + for c in xmldoc.getchildren(): + if c.tag == "cpu": + cpu = LibvirtConfigCPU() + cpu.parse_dom(c) + self.cpu = cpu + + def format_dom(self): + caps = super(LibvirtConfigCapsHost, self).format_dom() + + if self.cpu: + caps.append(self.cpu.format_dom()) + + return caps + + +class LibvirtConfigCapsGuest(LibvirtConfigObject): + + def __init__(self, **kwargs): + super(LibvirtConfigCapsGuest, self).__init__(root_name="guest", + **kwargs) + + self.arch = None + self.ostype = None + + def parse_dom(self, xmldoc): + super(LibvirtConfigCapsGuest, self).parse_dom(xmldoc) + + for c in xmldoc.getchildren(): + if c.tag == "os_type": + self.ostype = c.text + elif c.tag == "arch": + self.arch = c.get("name") + + def format_dom(self): + caps = super(LibvirtConfigCapsGuest, self).format_dom() + + if self.ostype is not None: + caps.append(self._text_node("os_type", self.ostype)) + if self.arch: + arch = etree.Element("arch", name=self.arch) + caps.append(arch) + + return caps + + class LibvirtConfigGuestTimer(LibvirtConfigObject): def __init__(self, **kwargs): @@ -132,6 +220,11 @@ class LibvirtConfigCPUFeature(LibvirtConfigObject): self.name = name + def parse_dom(self, xmldoc): + super(LibvirtConfigCPUFeature, self).parse_dom(xmldoc) + + self.name = xmldoc.get("name") + def format_dom(self): ft = super(LibvirtConfigCPUFeature, self).format_dom() @@ -156,6 +249,25 @@ class LibvirtConfigCPU(LibvirtConfigObject): self.features = [] + def parse_dom(self, xmldoc): + super(LibvirtConfigCPU, self).parse_dom(xmldoc) + + for c in xmldoc.getchildren(): + if c.tag == "arch": + self.arch = c.text + elif c.tag == "model": + self.model = c.text + elif c.tag == "vendor": + self.vendor = c.text + elif c.tag == "topology": + self.sockets = int(c.get("sockets")) + self.cores = int(c.get("cores")) + self.threads = int(c.get("threads")) + elif c.tag == "feature": + f = LibvirtConfigCPUFeature() + f.parse_dom(c) + self.add_feature(f) + def format_dom(self): cpu = super(LibvirtConfigCPU, self).format_dom()