diff options
author | Cole Robinson <crobinso@redhat.com> | 2015-04-03 12:40:16 -0400 |
---|---|---|
committer | Cole Robinson <crobinso@redhat.com> | 2015-04-03 16:45:42 -0400 |
commit | cac4ac1401203e2b851f111bf81136ae0723bcbe (patch) | |
tree | 56ac50058d92a32b694cc74a059920ea0c7c72a8 | |
parent | 0492dbc1b12db1057cd8ac9132d6786d32703376 (diff) | |
download | virt-manager-cac4ac1401203e2b851f111bf81136ae0723bcbe.tar.gz |
capabilities: Switch to use XMLBuilder
Just a cleanup to finally unify all the XML objects around the same
API, and drop a bunch of old cruft.
-rw-r--r-- | tests/capabilities.py | 77 | ||||
-rw-r--r-- | virtManager/connection.py | 2 | ||||
-rw-r--r-- | virtinst/__init__.py | 2 | ||||
-rw-r--r-- | virtinst/capabilities.py | 529 | ||||
-rw-r--r-- | virtinst/connection.py | 6 | ||||
-rw-r--r-- | virtinst/devicedisk.py | 11 | ||||
-rw-r--r-- | virtinst/guest.py | 2 |
7 files changed, 240 insertions, 389 deletions
diff --git a/tests/capabilities.py b/tests/capabilities.py index 8f6eaae6..c1da0630 100644 --- a/tests/capabilities.py +++ b/tests/capabilities.py @@ -19,20 +19,19 @@ import os import unittest from tests import utils -from virtinst import CapabilitiesParser as capabilities -from virtinst.capabilities import _CPUMapFileValues -from virtinst import DomainCapabilities +from virtinst import Capabilities +from virtinst import DomainCapabilities +from virtinst.capabilities import _CPUMapFileValues -def build_host_feature_dict(feature_list): - fdict = {} - for f in feature_list: - fdict[f] = capabilities.FEATURE_ON - return fdict +conn = utils.open_testdriver() class TestCapabilities(unittest.TestCase): + def _buildCaps(self, filename): + path = os.path.join("tests/capabilities-xml", filename) + return Capabilities(conn, file(path).read()) def _compareGuest(self, (arch, os_type, domains, features), guest): self.assertEqual(arch, guest.arch) @@ -44,13 +43,7 @@ class TestCapabilities(unittest.TestCase): self.assertEqual(domains[n][2], guest.domains[n].machines) for n in features: - self.assertEqual(features[n], guest.features[n]) - - def _buildCaps(self, filename): - path = os.path.join("tests/capabilities-xml", filename) - xml = file(path).read() - - return capabilities.Capabilities(xml) + self.assertEqual(features[n], getattr(guest.features, n)) def _testCapabilities(self, path, (host_arch, host_features), guests, secmodel=None): @@ -59,28 +52,31 @@ class TestCapabilities(unittest.TestCase): if host_arch: self.assertEqual(host_arch, caps.host.cpu.arch) for n in host_features: - self.assertEqual(host_features[n], caps.host.cpu.features[n]) + self.assertEqual(host_features[n], caps.host.cpu.has_feature(n)) if secmodel: - self.assertEqual(secmodel[0], caps.host.secmodel.model) - self.assertEqual(secmodel[1], caps.host.secmodel.doi) - if secmodel[2]: - for k, v in secmodel[2].items(): - self.assertEqual(v, caps.host.secmodel.baselabels[k]) + self.assertEqual(secmodel[0], caps.host.secmodels[0].model) + if secmodel[1]: + for idx, (t, v) in enumerate(secmodel[1].items()): + self.assertEqual(t, + caps.host.secmodels[0].baselabels[idx].type) + self.assertEqual(v, + caps.host.secmodels[0].baselabels[idx].content) for idx in range(len(guests)): self._compareGuest(guests[idx], caps.guests[idx]) def testCapabilities1(self): - host = ('x86_64', {'vmx': capabilities.FEATURE_ON}) + host = ('x86_64', {'vmx': True}) guests = [ ('x86_64', 'xen', [['xen', None, []]], {}), ('i686', 'xen', - [['xen', None, []]], {'pae': capabilities.FEATURE_ON}), + [['xen', None, []]], {'pae': True, 'nonpae': False}), ('i686', 'hvm', - [['xen', "/usr/lib64/xen/bin/qemu-dm", ['pc', 'isapc']]], {'pae': capabilities.FEATURE_ON | capabilities.FEATURE_OFF}), + [['xen', "/usr/lib64/xen/bin/qemu-dm", ['pc', 'isapc']]], + {'pae': True, 'nonpae': True}), ('x86_64', 'hvm', [['xen', "/usr/lib64/xen/bin/qemu-dm", ['pc', 'isapc']]], {}) ] @@ -89,7 +85,7 @@ class TestCapabilities(unittest.TestCase): def testCapabilities2(self): host = ('x86_64', {}) - secmodel = ('selinux', '0', None) + secmodel = ('selinux', None) guests = [ ('x86_64', 'hvm', @@ -129,18 +125,17 @@ class TestCapabilities(unittest.TestCase): ['g3bw', 'mac99', 'prep']]], {}), ] - secmodel = ('dac', '0', {"kvm" : "+0:+0", "qemu" : "+0:+0"}) + secmodel = ('dac', {"kvm" : "+0:+0", "qemu" : "+0:+0"}) self._testCapabilities("capabilities-kvm.xml", host, guests, secmodel) def testCapabilities4(self): - host = ('i686', - {'pae': capabilities.FEATURE_ON | capabilities.FEATURE_OFF}) + host = ('i686', {'pae': True, 'nonpae': True}) guests = [ ('i686', 'linux', [['test', None, []]], - {'pae': capabilities.FEATURE_ON | capabilities.FEATURE_OFF}), + {'pae': True, 'nonpae': True}), ] self._testCapabilities("capabilities-test.xml", host, guests) @@ -166,36 +161,33 @@ class TestCapabilities(unittest.TestCase): def testCapsCPUFeaturesOldSyntax(self): filename = "rhel5.4-xen-caps-virt-enabled.xml" host_feature_list = ["vmx"] - feature_dict = build_host_feature_dict(host_feature_list) caps = self._buildCaps(filename) - for f in feature_dict.keys(): - self.assertEquals(caps.host.cpu.features[f], feature_dict[f]) + for f in host_feature_list: + self.assertEquals(caps.host.cpu.has_feature(f), True) def testCapsCPUFeaturesOldSyntaxSVM(self): filename = "rhel5.4-xen-caps.xml" host_feature_list = ["svm"] - feature_dict = build_host_feature_dict(host_feature_list) caps = self._buildCaps(filename) - for f in feature_dict.keys(): - self.assertEquals(caps.host.cpu.features[f], feature_dict[f]) + for f in host_feature_list: + self.assertEquals(caps.host.cpu.has_feature(f), True) def testCapsCPUFeaturesNewSyntax(self): filename = "libvirt-0.7.6-qemu-caps.xml" host_feature_list = ['lahf_lm', 'xtpr', 'cx16', 'tm2', 'est', 'vmx', - 'ds_cpl', 'pbe', 'tm', 'ht', 'ss', 'acpi', 'ds'] - feature_dict = build_host_feature_dict(host_feature_list) + 'ds_cpl', 'pbe', 'tm', 'ht', 'ss', 'acpi', 'ds'] caps = self._buildCaps(filename) - for f in feature_dict.keys(): - self.assertEquals(caps.host.cpu.features[f], feature_dict[f]) + for f in host_feature_list: + self.assertEquals(caps.host.cpu.has_feature(f), True) self.assertEquals(caps.host.cpu.model, "core2duo") self.assertEquals(caps.host.cpu.vendor, "Intel") - self.assertEquals(caps.host.cpu.threads, "3") - self.assertEquals(caps.host.cpu.cores, "5") - self.assertEquals(caps.host.cpu.sockets, "7") + self.assertEquals(caps.host.cpu.threads, 3) + self.assertEquals(caps.host.cpu.cores, 5) + self.assertEquals(caps.host.cpu.sockets, 7) def testCapsUtilFuncs(self): new_caps = self._buildCaps("libvirt-0.7.6-qemu-caps.xml") @@ -246,7 +238,6 @@ class TestCapabilities(unittest.TestCase): test_cpu_map(cpu_64, x86_cpunames) test_cpu_map(cpu_random, []) - conn = utils.open_testdriver() cpu_64 = caps.get_cpu_values(conn, "x86_64") self.assertTrue(len(cpu_64) > 0) diff --git a/virtManager/connection.py b/virtManager/connection.py index 3bfd118f..d3f3a3a4 100644 --- a/virtManager/connection.py +++ b/virtManager/connection.py @@ -972,7 +972,7 @@ class vmmConnection(vmmGObject): self._backend.daemon_version()) logging.debug("conn version=%s", self._backend.conn_version()) logging.debug("%s capabilities:\n%s", - self.get_uri(), self.caps.xml) + self.get_uri(), self.caps.get_xml_config()) self._add_conn_events() # Prime CPU cache diff --git a/virtinst/__init__.py b/virtinst/__init__.py index aaf6eeea..0801cbfc 100644 --- a/virtinst/__init__.py +++ b/virtinst/__init__.py @@ -51,7 +51,7 @@ from virtinst.seclabel import Seclabel from virtinst.pm import PM from virtinst.idmap import IdMap -from virtinst import capabilities as CapabilitiesParser +from virtinst.capabilities import Capabilities from virtinst.domcapabilities import DomainCapabilities from virtinst.interface import Interface, InterfaceProtocol from virtinst.network import Network diff --git a/virtinst/capabilities.py b/virtinst/capabilities.py index 729fa73f..ed329dd7 100644 --- a/virtinst/capabilities.py +++ b/virtinst/capabilities.py @@ -22,17 +22,14 @@ import re from . import util +from .cpu import CPU as DomainCPU +from .xmlbuilder import XMLBuilder, XMLChildProperty +from .xmlbuilder import XMLProperty as _XMLProperty -# Whether a guest can be created with a certain feature on resp. off -FEATURE_ON = 0x01 -FEATURE_OFF = 0x02 - -def xpathString(node, path, default=None): - result = node.xpathEval("string(%s)" % path) - if len(result) == 0: - result = default - return result +# Disable test suite property tracking +class XMLProperty(_XMLProperty): + _track = False class CPUValuesModel(object): @@ -141,252 +138,109 @@ class _CPUMapFileValues(_CPUAPIValues): return cpumap.cpus -class Features(object): - """Represent a set of features. For each feature, store a bit mask of - FEATURE_ON and FEATURE_OFF to indicate whether the feature can - be turned on or off. For features for which toggling doesn't make sense - (e.g., 'vmx') store FEATURE_ON when the feature is present.""" - - def __init__(self, node=None): - self.features = {} - if node is not None: - self.parseXML(node) - - def __getitem__(self, feature): - if feature in self.features: - return self.features[feature] - return 0 - - def names(self): - return self.features.keys() - - def parseXML(self, node): - d = self.features - - feature_list = [] - if node.name == "features": - node_list = node.xpathEval("*") - for n in node_list: - feature_list.append(n.name) - else: - # New style features - node_list = node.xpathEval("feature/@name") - for n in node_list: - feature_list.append(n.content) - - for feature in feature_list: - if feature not in d: - d[feature] = 0 - - self._extractFeature(feature, d, n) - - def _extractFeature(self, feature, d, node): - """Extract the value of FEATURE from NODE and set DICT[FEATURE] to - its value. Abstract method, must be overridden""" - raise NotImplementedError("Abstract base class") - - -class CapabilityFeatures(Features): - def __init__(self, node=None): - Features.__init__(self, node) - - def _extractFeature(self, feature, d, n): - default = xpathString(n, "@default") - toggle = xpathString(n, "@toggle") - - if default is not None: - # Format for guest features - if default == "on": - d[feature] = FEATURE_ON - elif default == "off": - d[feature] = FEATURE_OFF - else: - raise RuntimeError("Feature %s: value of default must " - "be 'on' or 'off', but is '%s'" % - (feature, default)) - if toggle == "yes": - d[feature] |= d[feature] ^ (FEATURE_ON | FEATURE_OFF) - else: - # Format for old HOST features, on OLD old guest features - # back compat is just <$featurename>, like <svm/> - if feature == "nonpae": - d["pae"] |= FEATURE_OFF - else: - d[feature] |= FEATURE_ON - - -class CPU(object): - def __init__(self, node=None): - # e.g. "i686" or "x86_64" - self.arch = None - self.model = None - self.vendor = None - self.sockets = 1 - self.cores = 1 - self.threads = 1 - self.features = CapabilityFeatures() - - if node is not None: - self.parseXML(node) - - def parseXML(self, node): - newstyle_features = False - - child = node.children - while child: - # Do a first pass to try and detect new style features - if child.name == "feature": - newstyle_features = True - break - child = child.next +class _CapsCPU(DomainCPU): + arch = XMLProperty("./arch") - if newstyle_features: - self.features = CapabilityFeatures(node) + # capabilities used to just expose these properties as bools + _svm_bool = XMLProperty("./features/svm", is_bool=True) + _vmx_bool = XMLProperty("./features/vmx", is_bool=True) + _pae_bool = XMLProperty("./features/pae", is_bool=True) + _nonpae_bool = XMLProperty("./features/nonpae", is_bool=True) - child = node.children - while child: - if child.name == "arch": - self.arch = child.content - elif child.name == "model": - self.model = child.content - elif child.name == "vendor": - self.vendor = child.content - elif child.name == "topology": - self.sockets = xpathString(child, "@sockets") or 1 - self.cores = xpathString(child, "@cores") or 1 - self.threads = xpathString(child, "@threads") or 1 - - elif child.name == "features" and not newstyle_features: - self.features = CapabilityFeatures(child) + has_feature_block = XMLProperty("./features", is_bool=True) - child = child.next + ############## + # Public API # + ############## -class Host(object): - def __init__(self, node=None): - self.cpu = CPU() - self.topology = None - self.secmodels = [] + def has_feature(self, name): + if name == "svm" and self._svm_bool: + return True + if name == "vmx" and self._vmx_bool: + return True + if name == "pae" and self._pae_bool: + return True + if name == "nonpae" and self._nonpae_bool: + return True - if node is not None: - self.parseXML(node) + return name in [f.name for f in self.features] - def get_secmodel(self): - return self.secmodels and self.secmodels[0] or None - secmodel = property(get_secmodel) - def parseXML(self, node): - child = node.children - while child: - if child.name == "topology": - self.topology = Topology(child) +########################### +# Caps <topology> parsers # +########################### - if child.name == "secmodel": - self.secmodels.append(SecurityModel(child)) +class _CapsTopologyCPU(XMLBuilder): + _XML_ROOT_NAME = "cpu" + id = XMLProperty("./@id") - if child.name == "cpu": - self.cpu = CPU(child) - child = child.next +class _TopologyCell(XMLBuilder): + _XML_ROOT_NAME = "cell" + id = XMLProperty("./@id") + cpus = XMLChildProperty(_CapsTopologyCPU, relative_xpath="./cpus") -class Guest(object): - def __init__(self, node=None): - # e.g. "xen" or "hvm" - self.os_type = None - # e.g. "i686" or "x86_64" - self.arch = None +class _CapsTopology(XMLBuilder): + _XML_ROOT_NAME = "topology" + cells = XMLChildProperty(_TopologyCell, relative_xpath="./cells") - self.domains = [] - self.features = CapabilityFeatures() +###################################### +# Caps <host> and <secmodel> parsers # +###################################### - if node is not None: - self.parseXML(node) +class _CapsSecmodelBaselabel(XMLBuilder): + _XML_ROOT_NAME = "baselabel" + type = XMLProperty("./@type") + content = XMLProperty(".") - def parseXML(self, node): - child = node.children - while child: - if child.name == "os_type": - self.os_type = child.content - elif child.name == "features": - self.features = CapabilityFeatures(child) - elif child.name == "arch": - self.arch = child.prop("name") - machines = [] - emulator = None - loader = None - n = child.children - while n: - if n.name == "machine": - machines.append(n.content) - - canon = n.prop("canonical") - if canon: - machines.append(canon) - elif n.name == "emulator": - emulator = n.content - elif n.name == "loader": - loader = n.content - n = n.next - - n = child.children - while n: - if n.name == "domain": - self.domains.append(Domain(n.prop("type"), - emulator, loader, machines, n)) - n = n.next - child = child.next +class _CapsSecmodel(XMLBuilder): + _XML_ROOT_NAME = "secmodel" + model = XMLProperty("./model") + baselabels = XMLChildProperty(_CapsSecmodelBaselabel) - def _favoredDomain(self, domains): - """ - Return the recommended domain for use if the user does not explicitly - request one. - """ - if not domains: - return None - priority = ["kvm", "xen", "kqemu", "qemu"] +class _CapsHost(XMLBuilder): + _XML_ROOT_NAME = "host" + secmodels = XMLChildProperty(_CapsSecmodel) + cpu = XMLChildProperty(_CapsCPU, is_single=True) + topology = XMLChildProperty(_CapsTopology, is_single=True) - for t in priority: - for d in domains: - if d.hypervisor_type == t: - return d - # Fallback, just return last item in list - return domains[-1] +################################ +# <guest> and <domain> parsers # +################################ - def bestDomainType(self, dtype=None, machine=None): - domains = [] - for d in self.domains: - d.set_recommended_machine(None) +class _CapsMachine(XMLBuilder): + _XML_ROOT_NAME = "machine" + name = XMLProperty(".") + canonical = XMLProperty("./@canonical") - if dtype and d.hypervisor_type != dtype.lower(): - continue - if machine and machine not in d.machines: - continue - if machine: - d.set_recommended_machine(machine) - domains.append(d) +class _CapsDomain(XMLBuilder): + def __init__(self, *args, **kwargs): + XMLBuilder.__init__(self, *args, **kwargs) - return self._favoredDomain(domains) + self.machines = [] + for m in self._machines: + self.machines.append(m.name) + if m.canonical: + self.machines.append(m.canonical) + self._recommended_machine = None -class Domain(object): - def __init__(self, hypervisor_type, - emulator=None, loader=None, - machines=None, node=None): - self.hypervisor_type = hypervisor_type - self.emulator = emulator - self.loader = loader - self.machines = machines + _XML_ROOT_NAME = "domain" + hypervisor_type = XMLProperty("./@type") + emulator = XMLProperty("./emulator") + _machines = XMLChildProperty(_CapsMachine) - self._recommended_machine = None - if node is not None: - self.parseXML(node) + ############### + # Public APIs # + ############### def get_recommended_machine(self, conn, capsguest): if self._recommended_machine: @@ -408,102 +262,102 @@ class Domain(object): def set_recommended_machine(self, machine): self._recommended_machine = machine - def parseXML(self, node): - child = node.children - machines = [] - while child: - if child.name == "emulator": - self.emulator = child.content - elif child.name == "machine": - machines.append(child.content) - - canon = child.prop("canonical") - if canon: - machines.append(canon) - machines.append(child.content) - child = child.next - - if len(machines) > 0: - self.machines = machines - def is_accelerated(self): return self.hypervisor_type in ["kvm", "kqemu"] -class Topology(object): - def __init__(self, node=None): - self.cells = [] +class _CapsGuestFeatures(XMLBuilder): + _XML_ROOT_NAME = "features" - if node is not None: - self.parseXML(node) + pae = XMLProperty("./pae", is_bool=True) + nonpae = XMLProperty("./nonpae", is_bool=True) + acpi = XMLProperty("./acpi", is_bool=True) + apic = XMLProperty("./apci", is_bool=True) - def parseXML(self, node): - child = node.children - if child.name == "cells": - for cell in child.children: - if cell.name == "cell": - self.cells.append(TopologyCell(cell)) +class _CapsGuest(XMLBuilder): + def __init__(self, *args, **kwargs): + XMLBuilder.__init__(self, *args, **kwargs) -class TopologyCell(object): - def __init__(self, node=None): - self.id = None - self.cpus = [] + self.machines = [] + for m in self._machines: + self.machines.append(m.name) + if m.canonical: + self.machines.append(m.canonical) - if node is not None: - self.parseXML(node) + for d in self.domains: + if not d.emulator: + d.emulator = self.emulator + if not d.machines: + d.machines = self.machines - def parseXML(self, node): - self.id = int(node.prop("id")) - for child in node.children: - if child.name == "cpus": - for cpu in child.children: - if cpu.name == "cpu": - self.cpus.append(TopologyCPU(cpu)) + _XML_ROOT_NAME = "guest" -class TopologyCPU(object): - def __init__(self, node=None): - self.id = None + os_type = XMLProperty("./os_type") + arch = XMLProperty("./arch/@name") + loader = XMLProperty("./arch/loader") + emulator = XMLProperty("./arch/emulator") - if node is not None: - self.parseXML(node) + domains = XMLChildProperty(_CapsDomain, relative_xpath="./arch") + features = XMLChildProperty(_CapsGuestFeatures, is_single=True) + _machines = XMLChildProperty(_CapsMachine, relative_xpath="./arch") - def parseXML(self, node): - self.id = int(node.prop("id")) + ############### + # Public APIs # + ############### -class SecurityModel(object): - def __init__(self, node=None): - self.model = None - self.doi = None - self.baselabels = {} + def bestDomainType(self, dtype=None, machine=None): + """ + Return the recommended domain for use if the user does not explicitly + request one. + """ + domains = [] + for d in self.domains: + d.set_recommended_machine(None) - if node is not None: - self.parseXML(node) + if dtype and d.hypervisor_type != dtype.lower(): + continue + if machine and machine not in d.machines: + continue - def parseXML(self, node): - for child in node.children or []: - if child.name == "model": - self.model = child.content - elif child.name == "doi": - self.doi = child.content - elif child.name == "baselabel": - typ = child.prop("type") - self.baselabels[typ] = child.content - - -class Capabilities(object): - def __init__(self, xml): - self.host = None - self.guests = [] - self.xml = xml - self._topology = None + if machine: + d.set_recommended_machine(machine) + domains.append(d) + + if not domains: + return None + + priority = ["kvm", "xen", "kqemu", "qemu"] + + for t in priority: + for d in domains: + if d.hypervisor_type == t: + return d + + # Fallback, just return last item in list + return domains[-1] + + +############################ +# Main capabilities object # +############################ + +class Capabilities(XMLBuilder): + def __init__(self, *args, **kwargs): + XMLBuilder.__init__(self, *args, **kwargs) self._cpu_values = None - util.parse_node_helper(self.xml, "capabilities", - self.parseXML, - RuntimeError) + _XML_ROOT_NAME = "capabilities" + + host = XMLChildProperty(_CapsHost, is_single=True) + guests = XMLChildProperty(_CapsGuest) + + + ################### + # Private helpers # + ################### def _is_xen(self): for g in self.guests: @@ -516,6 +370,11 @@ class Capabilities(object): return False + + ############## + # Public API # + ############## + def no_install_options(self): """ Return True if there are no install options available @@ -534,17 +393,17 @@ class Capabilities(object): sufficiently provided, so we will return True in cases that we aren't sure. """ + # Obvious case of feature being specified + if (self.host.cpu.has_feature("vmx") or + self.host.cpu.has_feature("svm")): + return True + has_hvm_guests = False for g in self.guests: if g.os_type == "hvm": has_hvm_guests = True break - # Obvious case of feature being specified - if (self.host.cpu.features["vmx"] == FEATURE_ON or - self.host.cpu.features["svm"] == FEATURE_ON): - return True - # Xen seems to block the vmx/svm feature bits from cpuinfo? # so make sure no hvm guests are listed if self._is_xen() and has_hvm_guests: @@ -552,7 +411,7 @@ class Capabilities(object): # If there is other features, but no virt bit, then HW virt # isn't supported - if len(self.host.cpu.features.names()): + if self.host.cpu.has_feature_block: return False # Xen caps have always shown this info, so if we didn't find any @@ -617,36 +476,15 @@ class Capabilities(object): return True - def support_pae(self): + def supports_pae(self): + """ + Return True if capabilities report support for PAE + """ for g in self.guests: - if "pae" in g.features.names(): + if g.features.pae: return True return False - def _guestForOSType(self, typ=None, arch=None): - if self.host is None: - return None - - if arch is None: - archs = [self.host.cpu.arch, None] - else: - archs = [arch] - - for a in archs: - for g in self.guests: - if (typ is None or g.os_type == typ) and \ - (a is None or g.arch == a): - return g - - def parseXML(self, node): - child = node.children - while child: - if child.name == "host": - self.host = Host(child) - elif child.name == "guest": - self.guests.append(Guest(child)) - child = child.next - def get_cpu_values(self, conn, arch): if not arch: return [] @@ -663,6 +501,25 @@ class Capabilities(object): return [] + + ############################ + # Public XML building APIs # + ############################ + + def _guestForOSType(self, typ=None, arch=None): + if self.host is None: + return None + + archs = [arch] + if arch is None: + archs = [self.host.cpu.arch, None] + + for a in archs: + for g in self.guests: + if ((typ is None or g.os_type == typ) and + (a is None or g.arch == a)): + return g + def guest_lookup(self, os_type=None, arch=None, typ=None, machine=None): """ Simple virtualization availability lookup @@ -714,12 +571,12 @@ class Capabilities(object): return (guest, domain) def build_virtinst_guest(self, conn, guest, domain): - from .guest import Guest as VMGuest - gobj = VMGuest(conn) + from .guest import Guest + gobj = Guest(conn) gobj.type = domain.hypervisor_type gobj.os.os_type = guest.os_type gobj.os.arch = guest.arch - gobj.os.loader = domain.loader + gobj.os.loader = guest.loader gobj.emulator = domain.emulator gobj.os.machine = domain.get_recommended_machine(conn, guest) diff --git a/virtinst/connection.py b/virtinst/connection.py index bd4f973f..8fc162a7 100644 --- a/virtinst/connection.py +++ b/virtinst/connection.py @@ -25,8 +25,8 @@ import libvirt from . import pollhelpers from . import support from . import util -from . import capabilities as CapabilitiesParser from . import URISplit +from . import Capabilities from .cli import VirtOptionString from .guest import Guest from .nodedev import NodeDevice @@ -121,8 +121,8 @@ class VirtualConnection(object): def _get_caps(self): if not self._caps: - self._caps = CapabilitiesParser.Capabilities( - self._libvirtconn.getCapabilities()) + self._caps = Capabilities(self, + self._libvirtconn.getCapabilities()) return self._caps caps = property(_get_caps) diff --git a/virtinst/devicedisk.py b/virtinst/devicedisk.py index d40b6a95..76c4a928 100644 --- a/virtinst/devicedisk.py +++ b/virtinst/devicedisk.py @@ -252,12 +252,15 @@ class VirtualDisk(VirtualDevice): from virtcli import cliconfig user = cliconfig.default_qemu_user try: - for i in conn.caps.host.secmodels: - if i.model != "dac": + for secmodel in conn.caps.host.secmodels: + if secmodel.model != "dac": continue - label = (i.baselabels.get("kvm") or - i.baselabels.get("qemu")) + label = None + for baselabel in secmodel.baselabels: + if baselabel.type in ["qemu", "kvm"]: + label = baselabel.content + break if not label: continue diff --git a/virtinst/guest.py b/virtinst/guest.py index 678f6756..b17215a3 100644 --- a/virtinst/guest.py +++ b/virtinst/guest.py @@ -833,7 +833,7 @@ class Guest(XMLBuilder): if self.features.apic == "default": self.features.apic = self._lookup_osdict_key("apic", default) if self.features.pae == "default": - self.features.pae = self.conn.caps.support_pae() + self.features.pae = self.conn.caps.supports_pae() if (self._lookup_osdict_key("hyperv_features", False) and self._hv_supported() and |