summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2012-06-19 14:42:59 +0100
committerDaniel P. Berrange <berrange@redhat.com>2012-07-02 19:59:33 +0100
commit2a236d24a84875ee17df427ed90457414aaa9149 (patch)
tree656419955e70b5189668f56e76805f7a597ef9ff
parent7504c13711da5e372918b60393f497349e523994 (diff)
downloadnova-2a236d24a84875ee17df427ed90457414aaa9149.tar.gz
nova-2a236d24a84875ee17df427ed90457414aaa9149.tar.xz
nova-2a236d24a84875ee17df427ed90457414aaa9149.zip
Add compatibility for CPU model config with libvirt < 0.9.10
Libvirt versions prior to 0.9.10 do not support the simpler 'mode' attribute for choosing CPU model. So with such libvirt releases we must explicitly construct the guest CPU model from the host capabilities info when mode=host-model. We can not support mode=host-passthrough at all with these earlier libvirt versions This change can be reverted in the future, if the value of the MIN_LIBVIRT_VERSION constant is increased to 0.9.10 or later Fixes: bug #1003373 Implements: blueprint libvirt-xml-cpu-model Change-Id: I3e55ffccf38be18454f810efeb5c201aab94ddb0 Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
-rw-r--r--nova/tests/test_libvirt.py73
-rw-r--r--nova/virt/libvirt/driver.py43
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