From 691ffcfe93c56efba44230c65884118dbd9f89af Mon Sep 17 00:00:00 2001 From: Kashyap Chamarthy Date: Sat, 28 Apr 2018 18:55:25 +0200 Subject: [PATCH] libvirt: Make `cpu_model_extra_flags` case-insensitive for real MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we introduced `cpu_model_extra_flags` config attribute (in commit: 6b601b7 -- "libvirt: Allow to specify granular CPU feature flags"), we said it was case-insensitive; but unfortunately I missed to _really_ make it so (despite proposing code for it in one of the revisions). Address that mistake by making `cpu_model_extra_flags` case-insensitive for real, from Nova's point of view. NB: Internally, this patch is normalizing 'extra_flags' to _lower_ casing -- because CPU flags _must_ be lower case from libvirt's point of view. Nova must honour that; otherwise, launching instances with an upper case CPU flag, 'FOO', will fail with: "libvirtError: internal error: Unknown CPU feature FOO". Related-Bug: #1750829 Change-Id: Ia7ff0566a5109c76c009f3a0c6199c4ba419cfb1 Reported-by: Daniel P. Berrangé Signed-off-by: Kashyap Chamarthy (cherry picked from commit 8e438eda9bb16cdd3b627b93da2435572275b921) (cherry picked from commit f9ab466c6d9bb657409356f29139a9edfbb98747) (cherry picked from commit efa26e8dc24b5e828447fb78d0f54004054ae8b9) --- nova/tests/unit/virt/libvirt/test_driver.py | 29 +++++++++++++++++++++ nova/virt/libvirt/driver.py | 3 ++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 703e1ae41b02..a3257ca048c3 100755 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -5884,6 +5884,35 @@ class LibvirtConnTestCase(test.NoDBTestCase): self.assertEqual(conf.cpu.threads, 1) self.assertFalse(mock_warn.called) + @mock.patch.object(libvirt_driver.LOG, 'warning') + def test_get_guest_cpu_config_custom_with_extra_flags_upper_case(self, + mock_warn): + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + instance_ref = objects.Instance(**self.test_instance) + image_meta = objects.ImageMeta.from_dict(self.test_image_meta) + + self.flags(cpu_mode="custom", + cpu_model="IvyBridge", + cpu_model_extra_flags="PCID", + group='libvirt') + disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type, + instance_ref, + image_meta) + conf = drvr._get_guest_config(instance_ref, + _fake_network_info(self, 1), + image_meta, disk_info) + self.assertIsInstance(conf.cpu, + vconfig.LibvirtConfigGuestCPU) + self.assertEqual("custom", conf.cpu.mode) + self.assertEqual("IvyBridge", conf.cpu.model) + # At this point the upper case CPU flag is normalized to lower + # case, so assert for that + self.assertEqual("pcid", conf.cpu.features.pop().name) + self.assertEqual(instance_ref.flavor.vcpus, conf.cpu.sockets) + self.assertEqual(1, conf.cpu.cores) + self.assertEqual(1, conf.cpu.threads) + mock_warn.assert_not_called() + @mock.patch.object(libvirt_driver.LOG, 'warning') def test_get_guest_cpu_config_host_model_with_extra_flags(self, mock_warn): diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 058280a6029e..7416bc363998 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -3563,7 +3563,8 @@ class LibvirtDriver(driver.ComputeDriver): def _get_guest_cpu_model_config(self): mode = CONF.libvirt.cpu_mode model = CONF.libvirt.cpu_model - extra_flags = CONF.libvirt.cpu_model_extra_flags + extra_flags = set([flag.lower() for flag in + CONF.libvirt.cpu_model_extra_flags]) if (CONF.libvirt.virt_type == "kvm" or CONF.libvirt.virt_type == "qemu"):