Blob Blame History Raw
From 8bf52a94315a3fa219875a009a5d9661c46c47fe Mon Sep 17 00:00:00 2001
Message-Id: <8bf52a94315a3fa219875a009a5d9661c46c47fe@dist-git>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Thu, 4 Oct 2018 12:22:22 -0400
Subject: [PATCH] guest: Add DomainCapabilities caching

From: Cole Robinson <crobinso@redhat.com>

(cherry picked from commit 76334bfabdfd32498d78f390182d9621036e02d3)

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1525337

Conflicts:
    - virtinst/guest.py: different code-base as upstream have a lot of
      cleanup patches that moved a lot of code around

Reviewed-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
 tests/capabilities.py       |  5 +++++
 virtinst/cpu.py             | 26 ++++++++++++++------------
 virtinst/domcapabilities.py |  7 +++++--
 virtinst/guest.py           | 21 ++++++++++++++++++++-
 4 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/tests/capabilities.py b/tests/capabilities.py
index ef1d961b..f1416925 100644
--- a/tests/capabilities.py
+++ b/tests/capabilities.py
@@ -135,6 +135,11 @@ class TestCapabilities(unittest.TestCase):
         xml = open("tests/capabilities-xml/kvm-x86_64-domcaps.xml").read()
         caps = DomainCapabilities(utils.open_testdriver(), 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/cpu.py b/virtinst/cpu.py
index 1b8f4a96..1f1ad7ec 100644
--- a/virtinst/cpu.py
+++ b/virtinst/cpu.py
@@ -19,7 +19,6 @@
 
 import logging
 
-from .domcapabilities import DomainCapabilities
 from .xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty
 
 
@@ -237,20 +236,14 @@ class CPU(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
         # <capabilities> is not actually supported by qemu/kvm
         # combo which will be reported in <domainCapabilities>
-        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
@@ -264,6 +257,15 @@ class CPU(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 78ac7a3e..1a84ab95 100644
--- a/virtinst/domcapabilities.py
+++ b/virtinst/domcapabilities.py
@@ -192,6 +192,9 @@ class DomainCapabilities(XMLBuilder):
     os = XMLChildProperty(_OS, is_single=True)
     cpu = XMLChildProperty(_CPU, is_single=True)
     devices = XMLChildProperty(_Devices, is_single=True)
-
-    arch = XMLProperty("./arch")
     features = XMLChildProperty(_Features, is_single=True)
+
+    arch = XMLProperty("./arch")
+    domain = XMLProperty("./domain")
+    machine = XMLProperty("./machine")
+    path = XMLProperty("./path")
diff --git a/virtinst/guest.py b/virtinst/guest.py
index 6bf1b59a..9c45b1b8 100644
--- a/virtinst/guest.py
+++ b/virtinst/guest.py
@@ -140,6 +140,7 @@ class Guest(XMLBuilder):
 
         # This is set via Capabilities.build_virtinst_guest
         self.capsinfo = None
+        self._domcaps = None
 
         self.installer = DistroInstaller(self.conn)
 
@@ -534,6 +535,24 @@ class Guest(XMLBuilder):
                 logging.error("Failed to remove disk '%s': %s", name, e)
 
 
+    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
+
+
     ###########################
     # XML convenience helpers #
     ###########################
@@ -543,7 +562,7 @@ class Guest(XMLBuilder):
         Configure UEFI for the VM, but only if libvirt is advertising
         a known UEFI binary path.
         """
-        domcaps = DomainCapabilities.build_from_guest(self)
+        domcaps = self.lookup_domcaps()
 
         if not domcaps.supports_uefi_xml():
             raise RuntimeError(_("Libvirt version does not support UEFI."))
-- 
2.20.1