diff options
| -rw-r--r-- | nova/tests/test_libvirt.py | 73 | ||||
| -rw-r--r-- | nova/virt/libvirt/driver.py | 43 |
2 files changed, 113 insertions, 3 deletions
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 55163b4c4..982d08554 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -684,6 +684,79 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(conf.cpu.mode, "custom") self.assertEquals(conf.cpu.model, "Penryn") + @test.skip_if(missing_libvirt(), "Test requires libvirt") + def test_get_guest_cpu_config_host_passthrough_old(self): + def get_lib_version_stub(self): + return (0 * 1000 * 1000) + (9 * 1000) + 7 + + self.stubs.Set(libvirt.virConnect, "getLibVersion", + get_lib_version_stub) + conn = libvirt_driver.LibvirtDriver(True) + instance_ref = db.instance_create(self.context, self.test_instance) + + self.flags(libvirt_cpu_mode="host-passthrough") + self.assertRaises(exception.NovaException, + conn.get_guest_config, + instance_ref, + _fake_network_info(self.stubs, 1), + None, None) + + @test.skip_if(missing_libvirt(), "Test requires libvirt") + def test_get_guest_cpu_config_host_model_old(self): + def get_lib_version_stub(self): + return (0 * 1000 * 1000) + (9 * 1000) + 7 + + # Ensure we have a predictable host CPU + def get_host_capabilities_stub(self): + cpu = config.LibvirtConfigGuestCPU() + cpu.model = "Opteron_G4" + cpu.vendor = "AMD" + + caps = config.LibvirtConfigCaps() + caps.host = config.LibvirtConfigCapsHost() + caps.host.cpu = cpu + return caps + + self.stubs.Set(libvirt.virConnect, + "getLibVersion", + get_lib_version_stub) + self.stubs.Set(libvirt_driver.LibvirtDriver, + "get_host_capabilities", + get_host_capabilities_stub) + conn = libvirt_driver.LibvirtDriver(True) + instance_ref = db.instance_create(self.context, self.test_instance) + + self.flags(libvirt_cpu_mode="host-model") + conf = conn.get_guest_config(instance_ref, + _fake_network_info(self.stubs, 1), + None, None) + self.assertEquals(type(conf.cpu), + config.LibvirtConfigGuestCPU) + self.assertEquals(conf.cpu.mode, None) + self.assertEquals(conf.cpu.model, "Opteron_G4") + self.assertEquals(conf.cpu.vendor, "AMD") + + @test.skip_if(missing_libvirt(), "Test requires libvirt") + def test_get_guest_cpu_config_custom_old(self): + def get_lib_version_stub(self): + return (0 * 1000 * 1000) + (9 * 1000) + 7 + + self.stubs.Set(libvirt.virConnect, + "getLibVersion", + get_lib_version_stub) + conn = libvirt_driver.LibvirtDriver(True) + instance_ref = db.instance_create(self.context, self.test_instance) + + self.flags(libvirt_cpu_mode="custom") + self.flags(libvirt_cpu_model="Penryn") + conf = conn.get_guest_config(instance_ref, + _fake_network_info(self.stubs, 1), + None, None) + self.assertEquals(type(conf.cpu), + config.LibvirtConfigGuestCPU) + self.assertEquals(conf.cpu.mode, None) + self.assertEquals(conf.cpu.model, "Penryn") + def test_xml_and_uri_no_ramdisk_no_kernel(self): instance_data = dict(self.test_instance) self._check_xml_and_uri(instance_data, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 950494d97..f41cdba8a 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -231,6 +231,9 @@ LIBVIRT_POWER_STATE = { } MIN_LIBVIRT_VERSION = (0, 9, 6) +# When the above version matches/exceeds this version +# delete it & corresponding code using it +MIN_LIBVIRT_HOST_CPU_VERSION = (0, 9, 10) def _late_load_cheetah(): @@ -1469,6 +1472,27 @@ class LibvirtDriver(driver.ComputeDriver): caps.parse_str(xmlstr) return caps + def get_host_cpu_for_guest(self): + """Returns an instance of config.LibvirtConfigGuestCPU + representing the host's CPU model & topology with + policy for configuring a guest to match""" + + caps = self.get_host_capabilities() + hostcpu = caps.host.cpu + guestcpu = config.LibvirtConfigGuestCPU() + + guestcpu.model = hostcpu.model + guestcpu.vendor = hostcpu.vendor + guestcpu.arch = hostcpu.arch + + guestcpu.match = "exact" + + for hostfeat in hostcpu.features: + guestfeat = config.LibvirtConfigGuestCPUFeature(hostfeat.name) + guestfeat.policy = "require" + + return guestcpu + def get_guest_cpu_config(self): mode = FLAGS.libvirt_cpu_mode model = FLAGS.libvirt_cpu_model @@ -1494,9 +1518,22 @@ class LibvirtDriver(driver.ComputeDriver): LOG.debug(_("CPU mode '%(mode)s' model '%(model)s' was chosen") % {'mode': mode, 'model': (model or "")}) - cpu = config.LibvirtConfigGuestCPU() - cpu.mode = mode - cpu.model = model + # TODO(berrange): in the future, when MIN_LIBVIRT_VERSION is + # updated to be at least this new, we can kill off the elif + # blocks here + if self.has_min_version(MIN_LIBVIRT_HOST_CPU_VERSION): + cpu = config.LibvirtConfigGuestCPU() + cpu.mode = mode + cpu.model = model + elif mode == "custom": + cpu = config.LibvirtConfigGuestCPU() + cpu.model = model + elif mode == "host-model": + cpu = self.get_host_cpu_for_guest() + elif mode == "host-passthrough": + msg = _("Passthrough of the host CPU was requested but " + "this libvirt version does not support this feature") + raise exception.NovaException(msg) return cpu |
