The issue is when the host has been updated with microcode for Spectre but qemu has _not_ been updated. In this scenario (as an example), 'virsh capabilities' shows the host cpu model as IvyBridge-IBRS, which is correct. However, 'virsh domcapabilities' shows IvyBridge as the host-model and does not show any of the '-IBRS' flavors available under the custom model, which is also correct since the qemu does not have Spectre patches. Be default, virt-manager uses 'custom' for the cpu mode XML. For example, <cpu mode="custom" match="exact"> <model>IvyBridge-IBRS</model> </cpu> Starting an installation in the above scenario will fail because qemu doesn't understand '-IBRS' until it has been updated to do so. The patch below validates that the capabilities cpu is present in domcapabilities, and if they differ, log a message and set the CPU model to None. Signed-off-by: Charles Arnold <carnold@xxxxxxxx> diff --git a/virtinst/domain/cpu.py b/virtinst/domain/cpu.py index 3c1089c0..f3055dc7 100644 --- a/virtinst/domain/cpu.py +++ b/virtinst/domain/cpu.py @@ -6,6 +6,8 @@ # See the COPYING file in the top-level directory. from ..xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty +from .domcapabilities import DomainCapabilities +import logging class _CPUCellSibling(XMLBuilder): @@ -79,7 +81,7 @@ class DomainCpu(XMLBuilder): SPECIAL_MODES = [SPECIAL_MODE_HOST_MODEL_ONLY, SPECIAL_MODE_HV_DEFAULT, SPECIAL_MODE_HOST_COPY, SPECIAL_MODE_HOST_MODEL, SPECIAL_MODE_HOST_PASSTHROUGH, SPECIAL_MODE_CLEAR] - def set_special_mode(self, val): + def set_special_mode(self, val, guest=None): if (val == self.SPECIAL_MODE_HOST_MODEL or val == self.SPECIAL_MODE_HOST_PASSTHROUGH): self.model = None @@ -97,6 +99,15 @@ class DomainCpu(XMLBuilder): if self.conn.caps.host.cpu.model: self.clear() self.model = self.conn.caps.host.cpu.model + if guest: + domcaps = DomainCapabilities.build_from_guest(guest) + domcaps_model = domcaps.cpu.get_mode("host-model").get_models() + if (isinstance(domcaps_model, list) and len(domcaps_model) and + domcaps_model[0] != self.conn.caps.host.cpu.model): + logging.debug("Host capabilities CPU '%s' does not match " + "domain capabilities CPU '%s'. Leaving CPU model unset.", + self.conn.caps.host.cpu.model, domcaps_model[0]) + self.model = None else: raise RuntimeError("programming error: unknown " "special cpu mode '%s'" % val) diff --git a/virtinst/domcapabilities.py b/virtinst/domcapabilities.py index f98c807b..8387838c 100644 --- a/virtinst/domcapabilities.py +++ b/virtinst/domcapabilities.py @@ -29,9 +29,27 @@ class _Enum(_HasValues): name = XMLProperty("./@name") +class _Model(XMLBuilder): + _XML_ROOT_NAME = "model" + model = XMLProperty(".") + + +class _HasModels(XMLBuilder): + models = XMLChildProperty(_Model) + + def get_models(self): + return [m.model for m in self.models] + + +class _CPUMode(_HasModels): + _XML_ROOT_NAME = "mode" + name = XMLProperty("./@name") + + class _CapsBlock(_HasValues): supported = XMLProperty("./@supported", is_yesno=True) enums = XMLChildProperty(_Enum) + modes = XMLChildProperty(_CPUMode) def enum_names(self): return [e.name for e in self.enums] @@ -40,6 +58,12 @@ class _CapsBlock(_HasValues): d = dict((e.name, e) for e in self.enums) return d[name] + def mode_names(self): + return [m.name for m in self.modes] + + def get_mode(self, name): + d = dict((m.name, m) for m in self.modes) + return d[name] def _make_capsblock(xml_root_name): class TmpClass(_CapsBlock): @@ -53,6 +77,11 @@ class _OS(_CapsBlock): loader = XMLChildProperty(_make_capsblock("loader"), is_single=True) +class _CPU(_CapsBlock): + _XML_ROOT_NAME = "cpu" + mode = XMLChildProperty(_make_capsblock("mode"), is_single=True) + + class _Devices(_CapsBlock): XML_NAME = "devices" hostdev = XMLChildProperty(_make_capsblock("hostdev"), is_single=True) @@ -151,6 +180,7 @@ class DomainCapabilities(XMLBuilder): XML_NAME = "domainCapabilities" os = XMLChildProperty(_OS, is_single=True) + cpu = XMLChildProperty(_CPU, is_single=True) devices = XMLChildProperty(_Devices, is_single=True) arch = XMLProperty("./arch") diff --git a/virtinst/guest.py b/virtinst/guest.py index 5e7d8077..35d162c5 100644 --- a/virtinst/guest.py +++ b/virtinst/guest.py @@ -868,7 +868,7 @@ class Guest(XMLBuilder): if self.os.arch != self.conn.caps.host.cpu.arch: return - self.cpu.set_special_mode(self.x86_cpu_default) + self.cpu.set_special_mode(self.x86_cpu_default, self) if self._os_object.broken_x2apic(): self.cpu.add_feature("x2apic", policy="disable") _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list