From 4dd167378d33e3efee4657251655fc2992da2764 Mon Sep 17 00:00:00 2001 From: Jim Fehlig Date: Wed, 15 Aug 2012 09:42:12 -0600 Subject: Collect instance capabilities from compute nodes This change collects a list of supported instances from compute nodes. Each supported instance is a tuple, containing the triple (architecture, hypervisor_type, vm_mode). This list of tuples describes all of the instances supported by the compute node, which can then be used by the ComputeFilter to ensure proper placement of an instance in a heterogeneous compute node cloud. Change-Id: I059ff55c165b372c83e63390b40a2c165df1f717 --- nova/tests/test_libvirt.py | 36 ++++++++++++++++++++++++++++++++++++ nova/virt/libvirt/config.py | 8 ++++++++ nova/virt/libvirt/driver.py | 20 ++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index b45780912..dca370866 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -2244,11 +2244,13 @@ class LibvirtConnTestCase(test.TestCase): guest = config.LibvirtConfigGuest() guest.ostype = vm_mode.HVM guest.arch = "x86_64" + guest.domtype = ["kvm"] caps.guests.append(guest) guest = config.LibvirtConfigGuest() guest.ostype = vm_mode.HVM guest.arch = "i686" + guest.domtype = ["kvm"] caps.guests.append(guest) return caps @@ -2655,6 +2657,36 @@ class LibvirtConnTestCase(test.TestCase): } self.assertEqual(actual, expect) + def test_get_instance_capabilities(self): + conn = libvirt_driver.LibvirtDriver(True) + + def get_host_capabilities_stub(self): + caps = config.LibvirtConfigCaps() + + guest = config.LibvirtConfigGuest() + guest.ostype = 'hvm' + guest.arch = 'x86_64' + guest.domtype = ['kvm', 'qemu'] + caps.guests.append(guest) + + guest = config.LibvirtConfigGuest() + guest.ostype = 'hvm' + guest.arch = 'i686' + guest.domtype = ['kvm'] + caps.guests.append(guest) + + return caps + + self.stubs.Set(libvirt_driver.LibvirtDriver, + 'get_host_capabilities', + get_host_capabilities_stub) + + want = [('x86_64', 'kvm', 'hvm'), + ('x86_64', 'qemu', 'hvm'), + ('i686', 'kvm', 'hvm')] + got = conn.get_instance_capabilities() + self.assertEqual(want, got) + class HostStateTestCase(test.TestCase): @@ -2663,6 +2695,7 @@ class HostStateTestCase(test.TestCase): '"fxsr", "clflush", "pse36", "pat", "cmov", "mca", "pge", ' '"mtrr", "sep", "apic"], ' '"topology": {"cores": "1", "threads": "1", "sockets": "1"}}') + instance_caps = [("x86_64", "kvm", "hvm"), ("i686", "kvm", "hvm")] class FakeConnection(object): """Fake connection object""" @@ -2704,6 +2737,9 @@ class HostStateTestCase(test.TestCase): def get_disk_available_least(self): return 13091 + def get_instance_capabilities(self): + return HostStateTestCase.instance_caps + def test_update_status(self): self.mox.StubOutWithMock(libvirt_driver, 'LibvirtDriver') libvirt_driver.LibvirtDriver(True).AndReturn(self.FakeConnection()) diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index a53ed640f..8a924df56 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -133,6 +133,7 @@ class LibvirtConfigCapsGuest(LibvirtConfigObject): self.arch = None self.ostype = None + self.domtype = list() def parse_dom(self, xmldoc): super(LibvirtConfigCapsGuest, self).parse_dom(xmldoc) @@ -142,6 +143,9 @@ 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")) def format_dom(self): caps = super(LibvirtConfigCapsGuest, self).format_dom() @@ -150,6 +154,10 @@ class LibvirtConfigCapsGuest(LibvirtConfigObject): caps.append(self._text_node("os_type", self.ostype)) if self.arch: arch = etree.Element("arch", name=self.arch) + for dt in self.domtype: + dte = etree.Element("domain") + dte.set("type", dt) + arch.append(dte) caps.append(arch) return caps diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index bf3cec403..6abce222d 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -2055,6 +2055,24 @@ class LibvirtDriver(driver.ComputeDriver): """Returns the hostname of the hypervisor.""" return self._conn.getHostname() + def get_instance_capabilities(self): + """Get hypervisor instance capabilities + + Returns a list of tuples that describe instances the + hypervisor is capable of hosting. Each tuple consists + of the triplet (arch, hypervisor_type, vm_mode). + + :returns: List of tuples describing instance capabilities + """ + caps = self.get_host_capabilities() + instance_caps = list() + for g in caps.guests: + for dt in g.domtype: + instance_cap = (g.arch, dt, g.ostype) + instance_caps.append(instance_cap) + + return instance_caps + def get_cpu_info(self): """Get cpuinfo information. @@ -2991,6 +3009,8 @@ class HostState(object): data["hypervisor_type"] = self.connection.get_hypervisor_type() data["hypervisor_version"] = self.connection.get_hypervisor_version() data["hypervisor_hostname"] = self.connection.get_hypervisor_hostname() + data["supported_instances"] = \ + self.connection.get_instance_capabilities() self._stats = data -- cgit