commit eeeca4ceff576beaa8558360c8a6a165d716f996 Author: Andrew Bonney Date: Tue Oct 6 14:42:38 2020 +0100 Handle disabled CPU features to fix live migration failures When performing a live migration between hypervisors running libvirt, where one or more CPU features are disabled, nova does not take account of these. This results in migration failures as none of the available hypervisor targets appear compatible. This patch ensures that the libvirt 'disable' poicy is taken account of, at least in a basic sense, by explicitly ignoring items flagged in this way when enumerating CPU features. Closes-Bug: #1898715 Change-Id: Iaf14ca97cfac99dd280d1114123f2d4bb6292b63 diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py index f0c2fa3..9a9342e 100644 --- a/nova/tests/unit/virt/libvirt/test_config.py +++ b/nova/tests/unit/virt/libvirt/test_config.py @@ -339,6 +339,26 @@ class LibvirtConfigCPUFeatureTest(LibvirtConfigBaseTest): """) + def test_config_parse_require(self): + xml = """ + + """ + xmldoc = etree.fromstring(xml) + obj = config.LibvirtConfigCPUFeature() + obj.parse_dom(xmldoc) + + self.assertEqual(obj.policy, "require") + + def test_config_parse_disable(self): + xml = """ + + """ + xmldoc = etree.fromstring(xml) + obj = config.LibvirtConfigCPUFeature() + obj.parse_dom(xmldoc) + + self.assertEqual(obj.policy, "disable") + class LibvirtConfigGuestCPUFeatureTest(LibvirtConfigBaseTest): @@ -437,6 +457,27 @@ class LibvirtConfigCPUTest(LibvirtConfigBaseTest): """) + def test_config_disabled_features(self): + obj = config.LibvirtConfigCPU() + obj.model = "Penryn" + obj.vendor = "Intel" + obj.arch = obj_fields.Architecture.X86_64 + + disabled_feature = config.LibvirtConfigCPUFeature("mtrr") + disabled_feature.policy = "disable" + obj.add_feature(disabled_feature) + obj.add_feature(config.LibvirtConfigCPUFeature("apic")) + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + x86_64 + Penryn + Intel + + + """) + def test_only_uniq_cpu_featues(self): obj = config.LibvirtConfigCPU() obj.model = "Penryn" diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index 7cfdb42..ea52564 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -674,11 +674,13 @@ class LibvirtConfigCPUFeature(LibvirtConfigObject): **kwargs) self.name = name + self.policy = "require" def parse_dom(self, xmldoc): super(LibvirtConfigCPUFeature, self).parse_dom(xmldoc) self.name = xmldoc.get("name") + self.policy = xmldoc.get("policy", "require") def format_dom(self): ft = super(LibvirtConfigCPUFeature, self).format_dom() @@ -730,7 +732,8 @@ class LibvirtConfigCPU(LibvirtConfigObject): elif c.tag == "feature": f = LibvirtConfigCPUFeature() f.parse_dom(c) - self.add_feature(f) + if f.policy != "disable": + self.add_feature(f) def format_dom(self): cpu = super(LibvirtConfigCPU, self).format_dom() @@ -753,7 +756,8 @@ class LibvirtConfigCPU(LibvirtConfigObject): # sorting the features to allow more predictable tests for f in sorted(self.features, key=lambda x: x.name): - cpu.append(f.format_dom()) + if f.policy != "disable": + cpu.append(f.format_dom()) return cpu