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
(cherry picked from commit eeeca4ceff)
(cherry picked from commit 45a4110d20)
This commit is contained in:
Andrew Bonney 2020-10-06 14:42:38 +01:00 committed by Marc Gariépy (mgariepy)
parent 29425d6fb6
commit b6c473159e
2 changed files with 47 additions and 2 deletions

View File

@ -338,6 +338,26 @@ class LibvirtConfigCPUFeatureTest(LibvirtConfigBaseTest):
<feature name="mtrr"/>
""")
def test_config_parse_require(self):
xml = """
<feature name="mtrr" policy="require"/>
"""
xmldoc = etree.fromstring(xml)
obj = config.LibvirtConfigCPUFeature()
obj.parse_dom(xmldoc)
self.assertEqual(obj.policy, "require")
def test_config_parse_disable(self):
xml = """
<feature name="mtrr" policy="disable"/>
"""
xmldoc = etree.fromstring(xml)
obj = config.LibvirtConfigCPUFeature()
obj.parse_dom(xmldoc)
self.assertEqual(obj.policy, "disable")
class LibvirtConfigGuestCPUFeatureTest(LibvirtConfigBaseTest):
@ -436,6 +456,27 @@ class LibvirtConfigCPUTest(LibvirtConfigBaseTest):
</cpu>
""")
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, """
<cpu>
<arch>x86_64</arch>
<model>Penryn</model>
<vendor>Intel</vendor>
<feature name="apic"/>
</cpu>
""")
def test_only_uniq_cpu_featues(self):
obj = config.LibvirtConfigCPU()
obj.model = "Penryn"

View File

@ -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