virtinst: cpu: Move topology elements to their own class

This is a no-op but will help with a future bug fix

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2020-08-27 18:02:10 -04:00
parent ade6c34a96
commit 34c6d1c7ea
8 changed files with 72 additions and 59 deletions

View File

@ -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">

View File

@ -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")

View File

@ -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)

View File

@ -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"))

View File

@ -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)

View File

@ -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)

View File

@ -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")

View File

@ -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 #