diff options
-rw-r--r-- | tests/data/xmlparse/change-minimal-guest-out.xml | 2 | ||||
-rw-r--r-- | tests/test_capabilities.py | 6 | ||||
-rw-r--r-- | tests/test_xmlconfig.py | 20 | ||||
-rw-r--r-- | tests/test_xmlparse.py | 10 | ||||
-rw-r--r-- | virtManager/details/details.py | 10 | ||||
-rw-r--r-- | virtManager/object/domain.py | 9 | ||||
-rw-r--r-- | virtinst/cli.py | 12 | ||||
-rw-r--r-- | virtinst/domain/cpu.py | 62 |
8 files changed, 72 insertions, 59 deletions
diff --git a/tests/data/xmlparse/change-minimal-guest-out.xml b/tests/data/xmlparse/change-minimal-guest-out.xml index d347eec0..e07c8e69 100644 --- a/tests/data/xmlparse/change-minimal-guest-out.xml +++ b/tests/data/xmlparse/change-minimal-guest-out.xml @@ -20,8 +20,8 @@ </features> <clock offset="utc"/> <cpu mode="custom" match="exact"> + <topology cores="4" sockets="1" threads="1"/> <model fallback="allow">foobar</model> - <topology sockets="1" cores="4" threads="1"/> <feature policy="forbid" name="x2apic"/> </cpu> <seclabel type="static" model="testSecurity"> diff --git a/tests/test_capabilities.py b/tests/test_capabilities.py index 566c4516..46476182 100644 --- a/tests/test_capabilities.py +++ b/tests/test_capabilities.py @@ -33,9 +33,9 @@ class TestCapabilities(unittest.TestCase): self.assertEqual(caps.host.cpu.model, "core2duo") self.assertEqual(caps.host.cpu.vendor, "Intel") - self.assertEqual(caps.host.cpu.threads, 3) - self.assertEqual(caps.host.cpu.cores, 5) - self.assertEqual(caps.host.cpu.sockets, 7) + self.assertEqual(caps.host.cpu.topology.threads, 3) + self.assertEqual(caps.host.cpu.topology.cores, 5) + self.assertEqual(caps.host.cpu.topology.sockets, 7) def testCapsUtilFuncs(self): caps_with_kvm = self._buildCaps("test-qemu-with-kvm.xml") diff --git a/tests/test_xmlconfig.py b/tests/test_xmlconfig.py index a066a151..2312da20 100644 --- a/tests/test_xmlconfig.py +++ b/tests/test_xmlconfig.py @@ -145,25 +145,27 @@ class TestXMLMisc(unittest.TestCase): # Test CPU topology determining cpu = virtinst.DomainCpu(self.conn) cpu.set_topology_defaults(6) - assert cpu.sockets is None + assert cpu.topology.sockets is None - cpu.sockets = "2" + cpu.topology.sockets = "2" cpu.set_topology_defaults(6) - self.assertEqual([cpu.sockets, cpu.cores, cpu.threads], [2, 3, 1]) + def get_top(_c): + return [_c.topology.sockets, _c.topology.cores, _c.topology.threads] + self.assertEqual(get_top(cpu), [2, 3, 1]) cpu = virtinst.DomainCpu(self.conn) - cpu.cores = "4" + cpu.topology.cores = "4" cpu.set_topology_defaults(9) - self.assertEqual([cpu.sockets, cpu.cores, cpu.threads], [2, 4, 1]) + self.assertEqual(get_top(cpu), [2, 4, 1]) cpu = virtinst.DomainCpu(self.conn) - cpu.threads = "3" + cpu.topology.threads = "3" cpu.set_topology_defaults(14) - self.assertEqual([cpu.sockets, cpu.cores, cpu.threads], [4, 1, 3]) + self.assertEqual(get_top(cpu), [4, 1, 3]) cpu = virtinst.DomainCpu(self.conn) - cpu.sockets = 5 - cpu.cores = 2 + cpu.topology.sockets = 5 + cpu.topology.cores = 2 self.assertEqual(cpu.vcpus_from_topology(), 10) cpu = virtinst.DomainCpu(self.conn) diff --git a/tests/test_xmlparse.py b/tests/test_xmlparse.py index b6f14e64..2eb1142b 100644 --- a/tests/test_xmlparse.py +++ b/tests/test_xmlparse.py @@ -195,10 +195,10 @@ class XMLParseTest(unittest.TestCase): guest.cpu.set_model(guest, "qemu64") check("model", "qemu64") check("vendor", "Intel", "qemuvendor") - check("threads", 2, 1) - check("cores", 5, 3) - guest.cpu.sockets = 4.0 - check("sockets", 4) + check("topology.threads", 2, 1) + check("topology.cores", 5, 3) + guest.cpu.topology.sockets = 4.0 + check("topology.sockets", 4) check = self._make_checker(guest.cpu.features[0]) check("name", "x2apic") @@ -292,7 +292,7 @@ class XMLParseTest(unittest.TestCase): guest.cpu.set_model(guest, "foobar") check("model", "foobar") check("model_fallback", None, "allow") - check("cores", None, 4) + check("topology.cores", None, 4) guest.cpu.add_feature("x2apic", "forbid") guest.cpu.set_topology_defaults(guest.vcpus) self.assertTrue(guest.cpu.get_xml().startswith("<cpu")) diff --git a/virtManager/details/details.py b/virtManager/details/details.py index 831fc57b..351dd227 100644 --- a/virtManager/details/details.py +++ b/virtManager/details/details.py @@ -1939,13 +1939,13 @@ class vmmDetails(vmmGObjectUI): def _refresh_config_cpu(self): # Set topology first, because it impacts vcpus values - cpu = self.vm.get_cpu_config() - show_top = bool(cpu.sockets or cpu.cores or cpu.threads) + cpu = self.vm.xmlobj.cpu + show_top = cpu.has_topology() self.widget("cpu-topology-enable").set_active(show_top) - sockets = cpu.sockets or 1 - cores = cpu.cores or 1 - threads = cpu.threads or 1 + sockets = cpu.topology.sockets or 1 + cores = cpu.topology.cores or 1 + threads = cpu.topology.threads or 1 self.widget("cpu-sockets").set_value(sockets) self.widget("cpu-cores").set_value(cores) diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py index f47185be..62410bfc 100644 --- a/virtManager/object/domain.py +++ b/virtManager/object/domain.py @@ -559,9 +559,9 @@ class vmmDomain(vmmLibvirtObject): guest.vcpu_current = int(vcpus) if sockets != _SENTINEL: - guest.cpu.sockets = sockets - guest.cpu.cores = cores - guest.cpu.threads = threads + guest.cpu.topology.sockets = sockets + guest.cpu.topology.cores = cores + guest.cpu.topology.threads = threads if secure != _SENTINEL or model != _SENTINEL: guest.cpu.secure = secure @@ -1205,9 +1205,6 @@ class vmmDomain(vmmLibvirtObject): def get_description(self): return self.get_xmlobj().description - def get_cpu_config(self): - return self.get_xmlobj().cpu - def get_boot_order(self): legacy = not self.can_use_device_boot_order() return self.xmlobj.get_boot_order(legacy=legacy) diff --git a/virtinst/cli.py b/virtinst/cli.py index 4f0c8256..eac73ab9 100644 --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -2222,9 +2222,9 @@ class ParserCPU(VirtCLIParser): cls.add_arg("disable", None, lookup_cb=None, cb=cls.set_feature_cb) cls.add_arg("forbid", None, lookup_cb=None, cb=cls.set_feature_cb) - cls.add_arg("topology.sockets", "sockets") - cls.add_arg("topology.cores", "cores") - cls.add_arg("topology.threads", "threads") + cls.add_arg("topology.sockets", "topology.sockets") + cls.add_arg("topology.cores", "topology.cores") + cls.add_arg("topology.threads", "topology.threads") # Options for CPU.cells config cls.add_arg("numa.cell[0-9]*.id", "id", @@ -2407,9 +2407,9 @@ class ParserVCPU(VirtCLIParser): cls.add_arg("vcpus", "vcpus", cb=cls.noset_cb) # Further CPU options should be added to --cpu - cls.add_arg("sockets", "cpu.sockets") - cls.add_arg("cores", "cpu.cores") - cls.add_arg("threads", "cpu.threads") + cls.add_arg("sockets", "cpu.topology.sockets") + cls.add_arg("cores", "cpu.topology.cores") + cls.add_arg("threads", "cpu.topology.threads") # <domain><vcpu> options cls.add_arg("vcpu", "vcpus") diff --git a/virtinst/domain/cpu.py b/virtinst/domain/cpu.py index 0e6f4f1e..670a9dd3 100644 --- a/virtinst/domain/cpu.py +++ b/virtinst/domain/cpu.py @@ -57,13 +57,43 @@ class _CPUFeature(XMLBuilder): policy = XMLProperty("./@policy") +class _CPUTopology(XMLBuilder): + """ + Class for generating <cpu> <topology> XML + """ + XML_NAME = "topology" + _XML_PROP_ORDER = ["sockets", "cores", "threads"] + + sockets = XMLProperty("./@sockets", is_int=True) + cores = XMLProperty("./@cores", is_int=True) + threads = XMLProperty("./@threads", is_int=True) + + def set_defaults_from_vcpus(self, vcpus): + if not self.sockets: + if not self.cores: + self.sockets = vcpus // self.threads + else: + self.sockets = vcpus // self.cores + + if not self.cores: + if not self.threads: + self.cores = vcpus // self.sockets + else: + self.cores = vcpus // (self.sockets * self.threads) + + if not self.threads: + self.threads = vcpus // (self.sockets * self.cores) + + return + + class DomainCpu(XMLBuilder): """ Class for generating <cpu> XML """ XML_NAME = "cpu" _XML_PROP_ORDER = ["mode", "match", "model", "vendor", - "sockets", "cores", "threads", "features"] + "topology", "features"] secure = True @@ -207,13 +237,15 @@ class DomainCpu(XMLBuilder): Determine the CPU count represented by topology, or 1 if no topology is set """ - return (self.sockets or 1) * (self.cores or 1) * (self.threads or 1) + return ((self.topology.sockets or 1) * + (self.topology.cores or 1) * + (self.topology.threads or 1)) def has_topology(self): """ Return True if any topology info is set """ - return bool(self.sockets or self.cores or self.threads) + return bool(self.topology.get_xml()) def set_topology_defaults(self, vcpus): """ @@ -223,29 +255,15 @@ class DomainCpu(XMLBuilder): """ if not self.has_topology(): return - - if not self.sockets: - if not self.cores: - self.sockets = vcpus // self.threads - else: - self.sockets = vcpus // self.cores - - if not self.cores: - if not self.threads: - self.cores = vcpus // self.sockets - else: - self.cores = vcpus // (self.sockets * self.threads) - - if not self.threads: - self.threads = vcpus // (self.sockets * self.cores) - - return + self.topology.set_defaults_from_vcpus(vcpus) ################## # XML properties # ################## + topology = XMLChildProperty(_CPUTopology, is_single=True) + model = XMLProperty("./model") model_fallback = XMLProperty("./model/@fallback") @@ -253,10 +271,6 @@ class DomainCpu(XMLBuilder): vendor = XMLProperty("./vendor") mode = XMLProperty("./@mode") - sockets = XMLProperty("./topology/@sockets", is_int=True) - cores = XMLProperty("./topology/@cores", is_int=True) - threads = XMLProperty("./topology/@threads", is_int=True) - ################## # Default config # |