Subject: virtinst: read CPU model from domain capabilities
From: Charles Arnold carnold@suse.com Wed Mar 28 13:45:29 2018 -0600
Date: Tue Apr 3 10:57:15 2018 -0400:
Git: d15b78ab0d7b9e73261a19fafc841a4ee206d413

Add functionality to acquire the CPU model from the
libvirt domain capabilities. This is used to compare
with the host CPU model.

(crobinso: add test coverage, rework domcaps layout a bit)

Index: virt-manager-1.4.1/tests/capabilities-xml/kvm-x86_64-domcaps.xml
===================================================================
--- virt-manager-1.4.1.orig/tests/capabilities-xml/kvm-x86_64-domcaps.xml
+++ virt-manager-1.4.1/tests/capabilities-xml/kvm-x86_64-domcaps.xml
@@ -18,6 +18,68 @@
       </enum>
     </loader>
   </os>
+  <cpu>
+    <mode name='host-passthrough' supported='yes'/>
+    <mode name='host-model' supported='yes'>
+      <model fallback='forbid'>Broadwell</model>
+      <vendor>Intel</vendor>
+      <feature policy='require' name='vme'/>
+      <feature policy='require' name='ss'/>
+      <feature policy='require' name='f16c'/>
+      <feature policy='require' name='rdrand'/>
+      <feature policy='require' name='hypervisor'/>
+      <feature policy='require' name='arat'/>
+      <feature policy='require' name='tsc_adjust'/>
+      <feature policy='require' name='xsaveopt'/>
+      <feature policy='require' name='pdpe1gb'/>
+      <feature policy='require' name='abm'/>
+      <feature policy='require' name='invtsc'/>
+    </mode>
+    <mode name='custom' supported='yes'>
+      <model usable='yes'>qemu64</model>
+      <model usable='yes'>qemu32</model>
+      <model usable='no'>phenom</model>
+      <model usable='yes'>pentium3</model>
+      <model usable='yes'>pentium2</model>
+      <model usable='yes'>pentium</model>
+      <model usable='yes'>n270</model>
+      <model usable='yes'>kvm64</model>
+      <model usable='yes'>kvm32</model>
+      <model usable='yes'>coreduo</model>
+      <model usable='yes'>core2duo</model>
+      <model usable='no'>athlon</model>
+      <model usable='yes'>Westmere</model>
+      <model usable='no'>Westmere-IBRS</model>
+      <model usable='no'>Skylake-Server</model>
+      <model usable='no'>Skylake-Server-IBRS</model>
+      <model usable='no'>Skylake-Client</model>
+      <model usable='no'>Skylake-Client-IBRS</model>
+      <model usable='yes'>SandyBridge</model>
+      <model usable='no'>SandyBridge-IBRS</model>
+      <model usable='yes'>Penryn</model>
+      <model usable='no'>Opteron_G5</model>
+      <model usable='yes'>Opteron_G4</model>
+      <model usable='no'>Opteron_G3</model>
+      <model usable='yes'>Opteron_G2</model>
+      <model usable='yes'>Opteron_G1</model>
+      <model usable='yes'>Nehalem</model>
+      <model usable='no'>Nehalem-IBRS</model>
+      <model usable='yes'>IvyBridge</model>
+      <model usable='no'>IvyBridge-IBRS</model>
+      <model usable='yes'>Haswell</model>
+      <model usable='yes'>Haswell-noTSX</model>
+      <model usable='no'>Haswell-noTSX-IBRS</model>
+      <model usable='no'>Haswell-IBRS</model>
+      <model usable='no'>EPYC</model>
+      <model usable='no'>EPYC-IBPB</model>
+      <model usable='yes'>Conroe</model>
+      <model usable='yes'>Broadwell</model>
+      <model usable='yes'>Broadwell-noTSX</model>
+      <model usable='no'>Broadwell-noTSX-IBRS</model>
+      <model usable='no'>Broadwell-IBRS</model>
+      <model usable='yes'>486</model>
+    </mode>
+  </cpu>
   <devices>
     <disk supported='yes'>
       <enum name='diskDevice'>
@@ -32,8 +94,25 @@
         <value>scsi</value>
         <value>virtio</value>
         <value>usb</value>
+        <value>sata</value>
       </enum>
     </disk>
+    <graphics supported='yes'>
+      <enum name='type'>
+        <value>sdl</value>
+        <value>vnc</value>
+        <value>spice</value>
+      </enum>
+    </graphics>
+    <video supported='yes'>
+      <enum name='modelType'>
+        <value>vga</value>
+        <value>cirrus</value>
+        <value>vmvga</value>
+        <value>qxl</value>
+        <value>virtio</value>
+      </enum>
+    </video>
     <hostdev supported='yes'>
       <enum name='mode'>
         <value>subsystem</value>
@@ -50,11 +129,10 @@
         <value>scsi</value>
       </enum>
       <enum name='capsType'/>
-      <enum name='pciBackend'>
-        <value>default</value>
-        <value>kvm</value>
-        <value>vfio</value>
-      </enum>
+      <enum name='pciBackend'/>
     </hostdev>
   </devices>
+  <features>
+    <gic supported='no'/>
+  </features>
 </domainCapabilities>
Index: virt-manager-1.4.1/tests/capabilities.py
===================================================================
--- virt-manager-1.4.1.orig/tests/capabilities.py
+++ virt-manager-1.4.1/tests/capabilities.py
@@ -142,6 +142,16 @@ class TestCapabilities(unittest.TestCase
         self.assertEquals(caps.os.loader.get_enum("type").get_values(),
             ["rom", "pflash"])
 
+    def testDomainCapabilitiesx86(self):
+        xml = open("tests/capabilities-xml/kvm-x86_64-domcaps.xml").read()
+        caps = DomainCapabilities(utils.URIs.open_testdriver_cached(), xml)
+
+        custom_mode = caps.cpu.get_mode("custom")
+        self.assertTrue(bool(custom_mode))
+        cpu_model = custom_mode.get_model("Opteron_G4")
+        self.assertTrue(bool(cpu_model))
+        self.assertTrue(cpu_model.usable)
+
 
 if __name__ == "__main__":
     unittest.main()
Index: virt-manager-1.4.1/virtinst/domcapabilities.py
===================================================================
--- virt-manager-1.4.1.orig/virtinst/domcapabilities.py
+++ virt-manager-1.4.1/virtinst/domcapabilities.py
@@ -76,6 +76,33 @@ class _Features(_CapsBlock):
     gic = XMLChildProperty(_make_capsblock("gic"), is_single=True)
 
 
+
+class _CPUModel(XMLBuilder):
+    _XML_ROOT_NAME = "model"
+    model = XMLProperty(".")
+    usable = XMLProperty("./@usable", is_yesno=True)
+
+
+class _CPUMode(XMLBuilder):
+    _XML_ROOT_NAME = "mode"
+    name = XMLProperty("./@name")
+    models = XMLChildProperty(_CPUModel)
+
+    def get_model(self, name):
+        for model in self.models:
+            if model.model == name:
+                return model
+
+class _CPU(XMLBuilder):
+    _XML_ROOT_NAME = "cpu"
+    modes = XMLChildProperty(_CPUMode)
+
+    def get_mode(self, name):
+        for mode in self.modes:
+            if mode.name == name:
+                return mode
+
+
 class DomainCapabilities(XMLBuilder):
     @staticmethod
     def build_from_params(conn, emulator, arch, machine, hvtype):
@@ -163,6 +190,7 @@ class DomainCapabilities(XMLBuilder):
 
     _XML_ROOT_NAME = "domainCapabilities"
     os = XMLChildProperty(_OS, is_single=True)
+    cpu = XMLChildProperty(_CPU, is_single=True)
     devices = XMLChildProperty(_Devices, is_single=True)
 
     arch = XMLProperty("./arch")
