diff --git a/tests/capabilities.py b/tests/capabilities.py index d80c2898..11401d0b 100644 --- a/tests/capabilities.py +++ b/tests/capabilities.py @@ -106,6 +106,11 @@ class TestCapabilities(unittest.TestCase): xml = open("tests/capabilities-xml/kvm-x86_64-domcaps.xml").read() caps = DomainCapabilities(utils.URIs.open_testdriver_cached(), xml) + self.assertEqual(caps.machine, "pc-i440fx-2.1") + self.assertEqual(caps.arch, "x86_64") + self.assertEqual(caps.domain, "kvm") + self.assertEqual(caps.path, "/bin/qemu-system-x86_64") + custom_mode = caps.cpu.get_mode("custom") self.assertTrue(bool(custom_mode)) cpu_model = custom_mode.get_model("Opteron_G4") diff --git a/virtinst/domain/cpu.py b/virtinst/domain/cpu.py index cb71f4f5..799485f8 100644 --- a/virtinst/domain/cpu.py +++ b/virtinst/domain/cpu.py @@ -7,7 +7,6 @@ import logging -from ..domcapabilities import DomainCapabilities from ..xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty @@ -206,20 +205,14 @@ class DomainCpu(XMLBuilder): # Default config # ################## - def _set_cpu_x86_kvm_default(self, guest): - if guest.os.arch != self.conn.caps.host.cpu.arch: - return - - self.set_special_mode(guest.x86_cpu_default) - if guest.x86_cpu_default != self.SPECIAL_MODE_HOST_MODEL_ONLY: - return - if not self.model: - return - + def _validate_default_host_model_only(self, guest): # It's possible that the value HOST_MODEL_ONLY gets from # is not actually supported by qemu/kvm # combo which will be reported in - domcaps = DomainCapabilities.build_from_guest(guest) + if not self.model: + return + + domcaps = guest.lookup_domcaps() domcaps_mode = domcaps.cpu.get_mode("custom") if not domcaps_mode: return @@ -233,6 +226,15 @@ class DomainCpu(XMLBuilder): self.model) self.model = None + def _set_cpu_x86_kvm_default(self, guest): + if guest.os.arch != self.conn.caps.host.cpu.arch: + return + + mode = guest.x86_cpu_default + self.set_special_mode(mode) + if mode == self.SPECIAL_MODE_HOST_MODEL_ONLY: + self._validate_default_host_model_only(guest) + def set_defaults(self, guest): self.set_topology_defaults(guest.vcpus) diff --git a/virtinst/domcapabilities.py b/virtinst/domcapabilities.py index d8e2e444..9ef3853e 100644 --- a/virtinst/domcapabilities.py +++ b/virtinst/domcapabilities.py @@ -217,6 +217,9 @@ class DomainCapabilities(XMLBuilder): os = XMLChildProperty(_OS, is_single=True) cpu = XMLChildProperty(_CPU, is_single=True) devices = XMLChildProperty(_Devices, is_single=True) + features = XMLChildProperty(_Features, is_single=True) arch = XMLProperty("./arch") - features = XMLChildProperty(_Features, is_single=True) + domain = XMLProperty("./domain") + machine = XMLProperty("./machine") + path = XMLProperty("./path") diff --git a/virtinst/guest.py b/virtinst/guest.py index c35be334..21a44030 100644 --- a/virtinst/guest.py +++ b/virtinst/guest.py @@ -165,6 +165,7 @@ class Guest(XMLBuilder): self.__osinfo = None self._capsinfo = None + self._domcaps = None ###################### @@ -326,7 +327,7 @@ class Guest(XMLBuilder): """ if not self.os.arch: self.set_capabilities_defaults() - domcaps = DomainCapabilities.build_from_guest(self) + domcaps = self.lookup_domcaps() if not domcaps.supports_uefi_xml(): raise RuntimeError(_("Libvirt version does not support UEFI.")) @@ -408,10 +409,26 @@ class Guest(XMLBuilder): return False return True - def lookup_capsinfo(self): - def _compare_to_capsinfo(capsinfo): - if not capsinfo: + def lookup_domcaps(self): + # We need to regenerate domcaps cache if any of these values change + def _compare(domcaps): + if self.os.machine and self.os.machine != domcaps.machine: return False + if self.type and self.type != domcaps.domain: + return False + if self.os.arch and self.os.arch != domcaps.arch: + return False + if self.emulator and self.emulator != domcaps.path: + return False + return True + + if not self._domcaps or not _compare(self._domcaps): + self._domcaps = DomainCapabilities.build_from_guest(self) + return self._domcaps + + def lookup_capsinfo(self): + # We need to regenerate capsinfo cache if any of these values change + def _compare(capsinfo): if self.type and self.type != capsinfo.hypervisor_type: return False if self.os.os_type and self.os.os_type != capsinfo.os_type: @@ -422,7 +439,7 @@ class Guest(XMLBuilder): return False return True - if not _compare_to_capsinfo(self._capsinfo): + if not self._capsinfo or not _compare(self._capsinfo): self._capsinfo = self.conn.caps.guest_lookup( os_type=self.os.os_type, arch=self.os.arch,