VirtualConnection: cache capabilities XML
This means we can drop passing around the pre-parsed caps info everywhere.
This commit is contained in:
parent
f5ef1edeea
commit
94f8d4cfa9
|
@ -45,7 +45,7 @@ class TestCapabilities(unittest.TestCase):
|
|||
path = os.path.join("tests/capabilities-xml", filename)
|
||||
xml = file(path).read()
|
||||
|
||||
return capabilities.parse(xml)
|
||||
return capabilities.Capabilities(xml)
|
||||
|
||||
def _testCapabilities(self, path, (host_arch, host_features), guests,
|
||||
secmodel=None):
|
||||
|
|
|
@ -40,7 +40,7 @@ import os
|
|||
# We install several storage pools on the connection to ensure
|
||||
# we aren't bumping up against errors in that department.
|
||||
testconn = utils.open_testdriver()
|
||||
testcaps = virtinst.CapabilitiesParser.parse(testconn.getCapabilities())
|
||||
testcaps = testconn.caps
|
||||
|
||||
virtimage = virtinst.ImageParser.parse_file("tests/image-xml/image.xml")
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import urlgrabber.progress as progress
|
|||
|
||||
import virtinst
|
||||
import virtinst.ImageParser
|
||||
import virtinst.CapabilitiesParser
|
||||
import virtinst.cli as cli
|
||||
from virtinst.cli import fail, print_stdout, print_stderr
|
||||
|
||||
|
@ -140,7 +139,7 @@ def main(conn=None):
|
|||
|
||||
try:
|
||||
image = virtinst.ImageParser.parse_file(options.image)
|
||||
except virtinst.ImageParser.ParserException, msg:
|
||||
except RuntimeError, msg:
|
||||
fail("%s '%s': %s" % (_("Cannot parse"), options.image, msg))
|
||||
|
||||
if options.boot is not None:
|
||||
|
|
10
virt-install
10
virt-install
|
@ -31,7 +31,6 @@ import optparse
|
|||
import urlgrabber.progress as progress
|
||||
|
||||
import virtinst
|
||||
import virtinst.CapabilitiesParser
|
||||
import virtinst.cli as cli
|
||||
import virtinst.util as util
|
||||
from virtinst import VirtualCharDevice
|
||||
|
@ -258,15 +257,12 @@ def prompt_virt(caps, arch, req_virt_type, req_accel):
|
|||
|
||||
|
||||
def get_virt_type(conn, options):
|
||||
|
||||
# Set up all virt/hypervisor parameters
|
||||
if sum([bool(f) for f in [options.fullvirt,
|
||||
options.paravirt,
|
||||
options.container]]) > 1:
|
||||
fail(_("Can't do more than one of --hvm, --paravirt, or --container"))
|
||||
|
||||
capabilities = virtinst.CapabilitiesParser.parse(conn.getCapabilities())
|
||||
|
||||
req_accel = True
|
||||
req_hv_type = options.hv_type and options.hv_type.lower() or None
|
||||
if options.fullvirt:
|
||||
|
@ -282,7 +278,7 @@ def get_virt_type(conn, options):
|
|||
if cli.is_prompt():
|
||||
# User requested prompting but passed no virt type flag, ask for
|
||||
# needed info
|
||||
req_virt_type, req_accel = prompt_virt(capabilities, options.arch,
|
||||
req_virt_type, req_accel = prompt_virt(conn.caps, options.arch,
|
||||
req_virt_type, req_accel)
|
||||
|
||||
logging.debug("Requesting virt method '%s', hv type '%s'.",
|
||||
|
@ -295,9 +291,7 @@ def get_virt_type(conn, options):
|
|||
|
||||
try:
|
||||
(capsguest,
|
||||
capsdomain) = virtinst.CapabilitiesParser.guest_lookup(
|
||||
conn=conn,
|
||||
caps=capabilities,
|
||||
capsdomain) = conn.caps.guest_lookup(
|
||||
os_type=req_virt_type,
|
||||
arch=arch,
|
||||
typ=req_hv_type,
|
||||
|
|
|
@ -187,23 +187,8 @@ class vmmConnection(vmmGObject):
|
|||
return self._backend
|
||||
|
||||
def invalidate_caps(self):
|
||||
self._caps_xml = None
|
||||
self._caps = None
|
||||
|
||||
def _check_caps(self):
|
||||
if not (self._caps_xml or self._caps):
|
||||
self._caps_xml = self._backend.getCapabilities()
|
||||
self._caps = virtinst.CapabilitiesParser.parse(self._caps_xml)
|
||||
|
||||
def get_capabilities_xml(self):
|
||||
if not self._caps_xml:
|
||||
self._check_caps()
|
||||
return self._caps_xml
|
||||
|
||||
def get_capabilities(self):
|
||||
if not self._caps:
|
||||
self._check_caps()
|
||||
return self._caps
|
||||
return self._backend.invalidate_caps()
|
||||
caps = property(lambda self: getattr(self, "_backend").caps)
|
||||
|
||||
def get_host_info(self):
|
||||
return self.hostinfo
|
||||
|
@ -305,26 +290,16 @@ class vmmConnection(vmmGObject):
|
|||
return self.config.rhel6_defaults
|
||||
|
||||
def rhel6_defaults_caps(self):
|
||||
caps = self.get_capabilities()
|
||||
for guest in caps.guests:
|
||||
for guest in self.caps.guests:
|
||||
for dom in guest.domains:
|
||||
if dom.emulator.startswith("/usr/libexec"):
|
||||
return self.config.rhel6_defaults
|
||||
return True
|
||||
|
||||
def is_kvm_supported(self):
|
||||
return self.get_capabilities().is_kvm_available()
|
||||
|
||||
def no_install_options(self):
|
||||
return self.get_capabilities().no_install_options()
|
||||
|
||||
def hw_virt_supported(self):
|
||||
return self.get_capabilities().hw_virt_supported()
|
||||
|
||||
def is_bios_virt_disabled(self):
|
||||
return self.get_capabilities().is_bios_virt_disabled()
|
||||
|
||||
# Connection pretty print routines
|
||||
####################################
|
||||
# Connection pretty print routines #
|
||||
####################################
|
||||
|
||||
def _get_pretty_desc(self, active, shorthost, show_trans):
|
||||
def match_whole_string(orig, reg):
|
||||
|
@ -380,7 +355,7 @@ class vmmConnection(vmmGObject):
|
|||
if scheme in pretty_map:
|
||||
hv = pretty_map[scheme]
|
||||
|
||||
if hv == "QEMU" and active and self.is_kvm_supported():
|
||||
if hv == "QEMU" and active and self.caps.is_kvm_available():
|
||||
hv += "/KVM"
|
||||
|
||||
if show_trans:
|
||||
|
@ -968,10 +943,8 @@ class vmmConnection(vmmGObject):
|
|||
self.idle_emit("state-changed")
|
||||
|
||||
if self.state == self.STATE_ACTIVE:
|
||||
caps = self.get_capabilities_xml()
|
||||
logging.debug("%s capabilities:\n%s",
|
||||
self.get_uri(), caps)
|
||||
|
||||
self.get_uri(), self.caps.xml)
|
||||
self.tick()
|
||||
|
||||
if self.state == self.STATE_DISCONNECTED:
|
||||
|
|
|
@ -417,7 +417,7 @@ class vmmCreate(vmmGObjectUI):
|
|||
# Update all state that has some dependency on the current connection
|
||||
self.widget("create-forward").set_sensitive(True)
|
||||
|
||||
if self.conn.no_install_options():
|
||||
if self.conn.caps.no_install_options():
|
||||
error = _("No hypervisor options were found for this "
|
||||
"connection.")
|
||||
|
||||
|
@ -431,13 +431,13 @@ class vmmCreate(vmmGObjectUI):
|
|||
# A bit out of order, but populate arch + hv lists so we can
|
||||
# determine a default
|
||||
self.conn.invalidate_caps()
|
||||
self.caps = self.conn.get_capabilities()
|
||||
self.caps = self.conn.caps
|
||||
self.change_caps()
|
||||
self.populate_hv()
|
||||
|
||||
if self.conn.is_xen():
|
||||
if self.conn.hw_virt_supported():
|
||||
if self.conn.is_bios_virt_disabled():
|
||||
if self.conn.caps.hw_virt_supported():
|
||||
if self.conn.caps.is_bios_virt_disabled():
|
||||
error = _("Host supports full virtualization, but "
|
||||
"no related install options are available. "
|
||||
"This may mean support is disabled in your "
|
||||
|
@ -450,7 +450,7 @@ class vmmCreate(vmmGObjectUI):
|
|||
self.startup_warning(error)
|
||||
|
||||
elif self.conn.is_qemu():
|
||||
if not self.conn.is_kvm_supported():
|
||||
if not self.conn.caps.is_kvm_available():
|
||||
error = _("KVM is not available. This may mean the KVM "
|
||||
"package is not installed, or the KVM kernel modules "
|
||||
"are not loaded. Your virtual machines may perform poorly.")
|
||||
|
@ -811,10 +811,7 @@ class vmmCreate(vmmGObjectUI):
|
|||
gtype = "hvm"
|
||||
break
|
||||
|
||||
(newg, newdom) = virtinst.CapabilitiesParser.guest_lookup(
|
||||
conn=self.conn.get_backend(),
|
||||
caps=self.caps,
|
||||
os_type=gtype,
|
||||
(newg, newdom) = self.caps.guest_lookup(os_type=gtype,
|
||||
typ=dtype,
|
||||
accelerated=True,
|
||||
arch=arch)
|
||||
|
|
|
@ -785,7 +785,7 @@ class vmmDetails(vmmGObjectUI):
|
|||
clock_model.append([offset])
|
||||
|
||||
arch = self.vm.get_arch()
|
||||
caps = self.vm.conn.get_capabilities()
|
||||
caps = self.vm.conn.caps
|
||||
machines = []
|
||||
|
||||
if len(caps.guests) > 0:
|
||||
|
@ -819,7 +819,7 @@ class vmmDetails(vmmGObjectUI):
|
|||
# VCPU Pinning list
|
||||
generate_cpuset = self.widget("config-vcpupin-generate")
|
||||
generate_warn = self.widget("config-vcpupin-generate-err")
|
||||
if not self.conn.get_capabilities().host.topology:
|
||||
if not self.conn.caps.host.topology:
|
||||
generate_cpuset.set_sensitive(False)
|
||||
generate_warn.show()
|
||||
generate_warn.set_tooltip_text(_("Libvirt did not detect NUMA capabilities."))
|
||||
|
@ -883,7 +883,7 @@ class vmmDetails(vmmGObjectUI):
|
|||
no_default = not self.is_customize_dialog
|
||||
|
||||
# CPU features
|
||||
caps = self.vm.conn.get_capabilities()
|
||||
caps = self.vm.conn.caps
|
||||
cpu_values = None
|
||||
cpu_names = []
|
||||
all_features = []
|
||||
|
@ -2740,7 +2740,7 @@ class vmmDetails(vmmGObjectUI):
|
|||
|
||||
# Security details
|
||||
semodel, sectype, vmlabel, relabel = self.vm.get_seclabel()
|
||||
caps = self.vm.conn.get_capabilities()
|
||||
caps = self.vm.conn.caps
|
||||
|
||||
if caps.host.secmodel and caps.host.secmodel.model:
|
||||
semodel = caps.host.secmodel.model
|
||||
|
@ -2877,7 +2877,7 @@ class vmmDetails(vmmGObjectUI):
|
|||
def _refresh_cpu_config(self, cpu):
|
||||
feature_ui = self.widget("cpu-features")
|
||||
model = cpu.model or ""
|
||||
caps = self.vm.conn.get_capabilities()
|
||||
caps = self.vm.conn.caps
|
||||
|
||||
capscpu = None
|
||||
try:
|
||||
|
|
|
@ -408,8 +408,7 @@ class vmmDomain(vmmLibvirtObject):
|
|||
|
||||
def _build_guest(self, xml):
|
||||
return virtinst.Guest(self.conn.get_backend(),
|
||||
parsexml=xml,
|
||||
caps=self.conn.get_capabilities())
|
||||
parsexml=xml)
|
||||
|
||||
def _reparse_xml(self, ignore=None):
|
||||
self._guest = self._build_guest(self._get_domain_xml())
|
||||
|
|
|
@ -205,7 +205,7 @@ class virtimage_parser(formats.parser):
|
|||
f.close()
|
||||
|
||||
ImageParser.parse(output, input_file)
|
||||
except ImageParser.ParserException:
|
||||
except RuntimeError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
|
@ -35,9 +35,9 @@ class Boot(XMLBuilderDomain.XMLBuilderDomain):
|
|||
BOOT_DEVICE_FLOPPY, BOOT_DEVICE_NETWORK]
|
||||
|
||||
_dumpxml_xpath = "/domain/os"
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexmlnode)
|
||||
|
||||
self._bootorder = []
|
||||
self._enable_bootmenu = None
|
||||
|
|
|
@ -34,9 +34,9 @@ class CPUFeature(XMLBuilderDomain.XMLBuilderDomain):
|
|||
|
||||
POLICIES = ["force", "require", "optional", "disable", "forbid"]
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexmlnode)
|
||||
|
||||
self._name = None
|
||||
self._policy = None
|
||||
|
@ -79,7 +79,7 @@ class CPU(XMLBuilderDomain.XMLBuilderDomain):
|
|||
|
||||
MATCHS = ["minimum", "exact", "strict"]
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
self._model = None
|
||||
self._match = None
|
||||
self._vendor = None
|
||||
|
@ -91,7 +91,7 @@ class CPU(XMLBuilderDomain.XMLBuilderDomain):
|
|||
self._threads = None
|
||||
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexmlnode)
|
||||
if self._is_parse():
|
||||
return
|
||||
|
||||
|
@ -201,7 +201,7 @@ class CPU(XMLBuilderDomain.XMLBuilderDomain):
|
|||
Enact the equivalent of qemu -cpu host, pulling all info
|
||||
from capabilities about the host CPU
|
||||
"""
|
||||
cpu = self._get_caps().host.cpu
|
||||
cpu = self.conn.caps.host.cpu
|
||||
if not cpu.model:
|
||||
raise ValueError(_("No host CPU reported in capabilities"))
|
||||
|
||||
|
|
|
@ -23,16 +23,18 @@ import re
|
|||
|
||||
from virtinst import util
|
||||
|
||||
|
||||
class CapabilitiesParserException(Exception):
|
||||
def __init__(self, msg):
|
||||
Exception.__init__(self, msg)
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
class CPUValuesModel(object):
|
||||
"""
|
||||
Single <model> definition from cpu_map
|
||||
|
@ -118,7 +120,7 @@ class CPUValues(object):
|
|||
|
||||
util.parse_node_helper(xml, "cpus",
|
||||
self._parseXML,
|
||||
CapabilitiesParserException)
|
||||
RuntimeError)
|
||||
|
||||
def _parseXML(self, node):
|
||||
child = node.children
|
||||
|
@ -203,7 +205,9 @@ class CapabilityFeatures(Features):
|
|||
elif default == "off":
|
||||
d[feature] = FEATURE_OFF
|
||||
else:
|
||||
raise CapabilitiesParserException("Feature %s: value of default must be 'on' or 'off', but is '%s'" % (feature, default))
|
||||
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:
|
||||
|
@ -395,7 +399,7 @@ class Guest(object):
|
|||
{'type': self.os_type, 'arch': self.arch})
|
||||
error += domainerr
|
||||
error += machineerr
|
||||
raise CapabilitiesParserException(error)
|
||||
raise RuntimeError(error)
|
||||
|
||||
return self._favoredDomain(accelerated, domains)
|
||||
|
||||
|
@ -495,16 +499,16 @@ class SecurityModel(object):
|
|||
|
||||
|
||||
class Capabilities(object):
|
||||
def __init__(self, node=None):
|
||||
def __init__(self, xml):
|
||||
self.host = None
|
||||
self.guests = []
|
||||
self.xml = xml
|
||||
self._topology = None
|
||||
self._cpu_values = None
|
||||
|
||||
if not node is None:
|
||||
self.parseXML(node)
|
||||
|
||||
|
||||
util.parse_node_helper(self.xml, "capabilities",
|
||||
self.parseXML,
|
||||
RuntimeError)
|
||||
self._fixBrokenEmulator()
|
||||
|
||||
def _is_xen(self):
|
||||
|
@ -688,83 +692,63 @@ class Capabilities(object):
|
|||
return self._cpu_values.get_arch(arch)
|
||||
|
||||
|
||||
def parse(xml):
|
||||
return util.parse_node_helper(xml, "capabilities",
|
||||
Capabilities,
|
||||
CapabilitiesParserException)
|
||||
def guest_lookup(self, os_type=None, arch=None, typ=None,
|
||||
accelerated=False, machine=None):
|
||||
"""
|
||||
Simple virtualization availability lookup
|
||||
|
||||
Convenience function for looking up 'Guest' and 'Domain' capabilities
|
||||
objects for the desired virt type. If type, arch, or os_type are none,
|
||||
we return the default virt type associated with those values. These are
|
||||
typically:
|
||||
|
||||
def guest_lookup(conn, caps=None, os_type=None, arch=None, typ=None,
|
||||
accelerated=False, machine=None):
|
||||
"""
|
||||
Simple virtualization availability lookup
|
||||
- os_type : hvm, then xen
|
||||
- typ : kvm over plain qemu
|
||||
- arch : host arch over all others
|
||||
|
||||
Convenience function for looking up 'Guest' and 'Domain' capabilities
|
||||
objects for the desired virt type. If type, arch, or os_type are none,
|
||||
we return the default virt type associated with those values. These are
|
||||
typically:
|
||||
Otherwise the default will be the first listed in the capabilities xml.
|
||||
This function throws C{ValueError}s if any of the requested values are
|
||||
not found.
|
||||
|
||||
- os_type : hvm, then xen
|
||||
- typ : kvm over plain qemu
|
||||
- arch : host arch over all others
|
||||
@param typ: Virtualization type ('hvm', 'xen', ...)
|
||||
@type typ: C{str}
|
||||
@param arch: Guest architecture ('x86_64', 'i686' ...)
|
||||
@type arch: C{str}
|
||||
@param os_type: Hypervisor name ('qemu', 'kvm', 'xen', ...)
|
||||
@type os_type: C{str}
|
||||
@param accelerated: Whether to look for accelerated domain if none is
|
||||
specifically requested
|
||||
@type accelerated: C{bool}
|
||||
@param machine: Optional machine type to emulate
|
||||
@type machine: C{str}
|
||||
|
||||
Otherwise the default will be the first listed in the capabilities xml.
|
||||
This function throws C{ValueError}s if any of the requested values are
|
||||
not found.
|
||||
@returns: A (Capabilities Guest, Capabilities Domain) tuple
|
||||
"""
|
||||
guest = self.guestForOSType(os_type, arch)
|
||||
if not guest:
|
||||
archstr = _("for arch '%s'") % arch
|
||||
if not arch:
|
||||
archstr = ""
|
||||
|
||||
@param conn: libvirt connection
|
||||
@param caps: Optional L{Capabilities} instance (saves a lookup)
|
||||
@type caps: L{Capabilities}
|
||||
@param typ: Virtualization type ('hvm', 'xen', ...)
|
||||
@type typ: C{str}
|
||||
@param arch: Guest architecture ('x86_64', 'i686' ...)
|
||||
@type arch: C{str}
|
||||
@param os_type: Hypervisor name ('qemu', 'kvm', 'xen', ...)
|
||||
@type os_type: C{str}
|
||||
@param accelerated: Whether to look for accelerated domain if none is
|
||||
specifically requested
|
||||
@type accelerated: C{bool}
|
||||
@param machine: Optional machine type to emulate
|
||||
@type machine: C{str}
|
||||
osstr = _("virtualization type '%s'") % os_type
|
||||
if not os_type:
|
||||
osstr = _("any virtualization options")
|
||||
|
||||
@returns: A (Capabilities Guest, Capabilities Domain) tuple
|
||||
"""
|
||||
raise ValueError(_("Host does not support %(virttype)s %(arch)s") %
|
||||
{'virttype' : osstr, 'arch' : archstr})
|
||||
|
||||
if not caps:
|
||||
caps = parse(conn.getCapabilities())
|
||||
domain = guest.bestDomainType(accelerated=accelerated,
|
||||
dtype=typ,
|
||||
machine=machine)
|
||||
|
||||
guest = caps.guestForOSType(os_type, arch)
|
||||
if not guest:
|
||||
archstr = _("for arch '%s'") % arch
|
||||
if not arch:
|
||||
archstr = ""
|
||||
if domain is None:
|
||||
machinestr = "with machine '%s'" % machine
|
||||
if not machine:
|
||||
machinestr = ""
|
||||
raise ValueError(_("Host does not support domain type %(domain)s"
|
||||
"%(machine)s for virtualization type "
|
||||
"'%(virttype)s' arch '%(arch)s'") %
|
||||
{'domain': typ, 'virttype': guest.os_type,
|
||||
'arch': guest.arch, 'machine': machinestr})
|
||||
|
||||
osstr = _("virtualization type '%s'") % os_type
|
||||
if not os_type:
|
||||
osstr = _("any virtualization options")
|
||||
|
||||
raise ValueError(_("Host does not support %(virttype)s %(arch)s") %
|
||||
{'virttype' : osstr, 'arch' : archstr})
|
||||
|
||||
domain = guest.bestDomainType(accelerated=accelerated,
|
||||
dtype=typ,
|
||||
machine=machine)
|
||||
|
||||
if domain is None:
|
||||
machinestr = "with machine '%s'" % machine
|
||||
if not machine:
|
||||
machinestr = ""
|
||||
raise ValueError(_("Host does not support domain type %(domain)s"
|
||||
"%(machine)s for virtualization type "
|
||||
"'%(virttype)s' arch '%(arch)s'") %
|
||||
{'domain': typ, 'virttype': guest.os_type,
|
||||
'arch': guest.arch, 'machine': machinestr})
|
||||
|
||||
return (guest, domain)
|
||||
|
||||
|
||||
def xpathString(node, path, default=None):
|
||||
result = node.xpathEval("string(%s)" % path)
|
||||
if len(result) == 0:
|
||||
result = default
|
||||
return result
|
||||
return (guest, domain)
|
||||
|
|
|
@ -27,9 +27,9 @@ class Clock(XMLBuilderDomain.XMLBuilderDomain):
|
|||
"""
|
||||
|
||||
_dumpxml_xpath = "/domain/clock"
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexmlnode)
|
||||
|
||||
self._offset = None
|
||||
|
||||
|
|
|
@ -155,12 +155,12 @@ def _upload_file(conn, meter, destpool, src):
|
|||
|
||||
class DistroInstaller(Installer.Installer):
|
||||
def __init__(self, conn, type="xen", location=None,
|
||||
extraargs=None, os_type=None, caps=None):
|
||||
extraargs=None, os_type=None):
|
||||
# pylint: disable=W0622
|
||||
# Redefining built-in 'type', but it matches the XML so keep it
|
||||
|
||||
Installer.Installer.__init__(self, conn, type, location, extraargs,
|
||||
os_type, caps=caps)
|
||||
os_type)
|
||||
|
||||
self._livecd = False
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ class DomainFeatures(XMLBuilderDomain.XMLBuilderDomain):
|
|||
"""
|
||||
|
||||
_dumpxml_xpath = "/domain/features"
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexmlnode)
|
||||
|
||||
self._acpi = None
|
||||
self._apic = None
|
||||
|
|
|
@ -97,12 +97,12 @@ class DomainNumatune(XMLBuilderDomain.XMLBuilderDomain):
|
|||
|
||||
MEMORY_MODES = ["interleave", "strict", "preferred"]
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
self._memory_nodeset = None
|
||||
self._memory_mode = None
|
||||
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexmlnode)
|
||||
if self._is_parse():
|
||||
return
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import libvirt
|
|||
import libxml2
|
||||
|
||||
from virtinst import util
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst import support
|
||||
from virtinst import XMLBuilderDomain
|
||||
import virtinst
|
||||
|
@ -124,12 +123,10 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
|
|||
If host doesn't have a suitable NUMA configuration, a RuntimeError
|
||||
is thrown.
|
||||
"""
|
||||
caps = CapabilitiesParser.parse(conn.getCapabilities())
|
||||
|
||||
if caps.host.topology is None:
|
||||
if conn.caps.host.topology is None:
|
||||
raise RuntimeError(_("No topology section in capabilities xml."))
|
||||
|
||||
cells = caps.host.topology.cells
|
||||
cells = conn.caps.host.topology.cells
|
||||
if len(cells) <= 1:
|
||||
raise RuntimeError(_("Capabilities only show <= 1 cell. "
|
||||
"Not NUMA capable"))
|
||||
|
@ -171,7 +168,7 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
|
|||
return cpustr
|
||||
|
||||
def __init__(self, conn, type=None,
|
||||
installer=None, parsexml=None, caps=None):
|
||||
installer=None, parsexml=None):
|
||||
# pylint: disable=W0622
|
||||
# Redefining built-in 'type', but it matches the XML so keep it
|
||||
|
||||
|
@ -210,21 +207,14 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
|
|||
self._default_input_device = None
|
||||
self._default_console_device = None
|
||||
|
||||
# pylint: disable=W0212
|
||||
# Access to protected member _get_caps
|
||||
caps = caps or (self._installer and self._installer._get_caps())
|
||||
# pylint: enable=W0212
|
||||
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
caps=caps)
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml)
|
||||
if self._is_parse():
|
||||
return
|
||||
|
||||
if not self.installer:
|
||||
i = virtinst.DistroInstaller(conn,
|
||||
type=type,
|
||||
os_type=self._default_os_type,
|
||||
caps=self._get_caps())
|
||||
os_type=self._default_os_type)
|
||||
self.installer = i
|
||||
|
||||
# Add default devices (if applicable)
|
||||
|
@ -660,7 +650,6 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
|
|||
}
|
||||
|
||||
# Hand off all child element parsing to relevant classes
|
||||
caps = self._get_caps()
|
||||
for node in self._xml_node.children:
|
||||
if node.name != "devices":
|
||||
continue
|
||||
|
@ -673,24 +662,20 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
|
|||
|
||||
if objclass == virtinst.VirtualCharDevice:
|
||||
dev = objclass(self.conn, devnode.name,
|
||||
parsexmlnode=devnode, caps=caps)
|
||||
parsexmlnode=devnode)
|
||||
else:
|
||||
dev = objclass(self.conn,
|
||||
parsexmlnode=devnode, caps=caps)
|
||||
dev = objclass(self.conn, parsexmlnode=devnode)
|
||||
self._add_device(dev)
|
||||
|
||||
self._installer = virtinst.Installer.Installer(self.conn,
|
||||
parsexmlnode=self._xml_node,
|
||||
caps=caps)
|
||||
parsexmlnode=self._xml_node)
|
||||
self._features = DomainFeatures(self.conn,
|
||||
parsexmlnode=self._xml_node,
|
||||
caps=caps)
|
||||
self._clock = Clock(self.conn, parsexmlnode=self._xml_node, caps=caps)
|
||||
self._seclabel = Seclabel(self.conn, parsexmlnode=self._xml_node,
|
||||
caps=caps)
|
||||
self._cpu = CPU(self.conn, parsexmlnode=self._xml_node, caps=caps)
|
||||
parsexmlnode=self._xml_node)
|
||||
self._clock = Clock(self.conn, parsexmlnode=self._xml_node)
|
||||
self._seclabel = Seclabel(self.conn, parsexmlnode=self._xml_node)
|
||||
self._cpu = CPU(self.conn, parsexmlnode=self._xml_node)
|
||||
self._numatune = DomainNumatune(self.conn,
|
||||
parsexmlnode=self._xml_node, caps=caps)
|
||||
parsexmlnode=self._xml_node)
|
||||
|
||||
def _get_default_input_device(self):
|
||||
"""
|
||||
|
@ -766,7 +751,7 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
|
|||
if (not self.emulator and
|
||||
self.installer.is_hvm() and
|
||||
self.type == "xen"):
|
||||
if self._get_caps().host.arch in ("x86_64"):
|
||||
if self.conn.caps.host.arch in ("x86_64"):
|
||||
emulator = "/usr/lib64/xen/bin/qemu-dm"
|
||||
else:
|
||||
emulator = "/usr/lib/xen/bin/qemu-dm"
|
||||
|
@ -1298,11 +1283,11 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
|
|||
features["acpi"] = self._lookup_osdict_key("acpi")
|
||||
if features["apic"] is None:
|
||||
features["apic"] = self._lookup_osdict_key("apic")
|
||||
if features["pae"] is None and self._get_caps():
|
||||
features["pae"] = self._get_caps().support_pae()
|
||||
if features["pae"] is None:
|
||||
features["pae"] = self.conn.caps.support_pae()
|
||||
|
||||
if (self.installer.machine is None and
|
||||
self._get_caps().host.arch == "ppc64"):
|
||||
self.conn.caps.host.arch == "ppc64"):
|
||||
self.installer.machine = "pseries"
|
||||
|
||||
def _set_pv_defaults(self, devlist_func, remove_func):
|
||||
|
|
|
@ -22,7 +22,7 @@ import os
|
|||
|
||||
from virtinst import Installer
|
||||
from virtinst import ImageParser
|
||||
from virtinst import CapabilitiesParser as Cap
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst.VirtualDisk import VirtualDisk
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ class ImageInstaller(Installer.Installer):
|
|||
|
||||
# Set boot _boot_caps/_boot_parameters
|
||||
if boot_index is None:
|
||||
self._boot_caps = match_boots(self._get_caps(),
|
||||
self._boot_caps = match_boots(self.conn.caps,
|
||||
self.image.domain.boots)
|
||||
if self._boot_caps is None:
|
||||
raise RuntimeError(_("Could not find suitable boot "
|
||||
|
@ -52,7 +52,7 @@ class ImageInstaller(Installer.Installer):
|
|||
self._boot_caps = image.domain.boots[boot_index]
|
||||
|
||||
# Set up internal caps.guest object
|
||||
self._guest = self._get_caps().guestForOSType(self.boot_caps.type,
|
||||
self._guest = self.conn.caps.guestForOSType(self.boot_caps.type,
|
||||
self.boot_caps.arch)
|
||||
if self._guest is None:
|
||||
raise RuntimeError(_("Unsupported virtualization type: %s %s" %
|
||||
|
@ -88,9 +88,9 @@ class ImageInstaller(Installer.Installer):
|
|||
self._make_disks()
|
||||
|
||||
for f in ['pae', 'acpi', 'apic']:
|
||||
if self.boot_caps.features[f] & Cap.FEATURE_ON:
|
||||
if self.boot_caps.features[f] & CapabilitiesParser.FEATURE_ON:
|
||||
guest.features[f] = True
|
||||
elif self.boot_caps.features[f] & Cap.FEATURE_OFF:
|
||||
elif self.boot_caps.features[f] & CapabilitiesParser.FEATURE_OFF:
|
||||
guest.features[f] = False
|
||||
|
||||
self.bootconfig.kernel = self.boot_caps.kernel
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Sample code to parse an image XML description and
|
||||
# spit out libvirt XML; will be hooked into virt-install
|
||||
# spit out libvirt XML
|
||||
#
|
||||
# Copyright 2007, 2013 Red Hat, Inc.
|
||||
# David Lutterkort <dlutter@redhat.com>
|
||||
|
@ -22,19 +22,13 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
import libxml2
|
||||
import urlgrabber
|
||||
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst import util
|
||||
|
||||
|
||||
class ParserException(Exception):
|
||||
def __init__(self, msg):
|
||||
Exception.__init__(self, msg)
|
||||
|
||||
|
||||
class Image:
|
||||
class Image(object):
|
||||
"""The toplevel object representing a VM image"""
|
||||
def __init__(self, node=None, base=None, filename=None):
|
||||
self.storage = {}
|
||||
|
@ -77,24 +71,23 @@ class Image:
|
|||
disk.id = "disk%d.img" % len(self.storage)
|
||||
disk.file = "disk%d.img" % (len(self.storage) + 1)
|
||||
if disk.id in self.storage:
|
||||
raise ParserException("Disk file '%s' defined twice"
|
||||
% disk.file)
|
||||
raise RuntimeError("Disk file '%s' defined twice" % disk.file)
|
||||
self.storage[disk.id] = disk
|
||||
lm = node.xpathEval("domain")
|
||||
if len(lm) == 1:
|
||||
self.domain = Domain(lm[0])
|
||||
else:
|
||||
raise ParserException(_("Expected exactly one 'domain' element"))
|
||||
raise RuntimeError(_("Expected exactly one 'domain' element"))
|
||||
# Connect the disk maps to the disk definitions
|
||||
for boot in self.domain.boots:
|
||||
for d in boot.drives:
|
||||
if d.disk_id not in self.storage:
|
||||
raise ParserException(_("Disk entry for '%s' not found")
|
||||
% d.disk_id)
|
||||
raise RuntimeError(_("Disk entry for '%s' not found")
|
||||
% d.disk_id)
|
||||
d.disk = self.storage[d.disk_id]
|
||||
|
||||
|
||||
class Domain:
|
||||
class Domain(object):
|
||||
"""The description of a virtual domain as part of an image"""
|
||||
def __init__(self, node=None):
|
||||
self.boots = []
|
||||
|
@ -116,8 +109,8 @@ class Domain:
|
|||
try:
|
||||
self.memory = int(tmpmem)
|
||||
except ValueError:
|
||||
raise ParserException(_("Memory must be an integer, "
|
||||
"but is '%s'") % self.memory)
|
||||
raise RuntimeError(_("Memory must be an integer, "
|
||||
"but is '%s'") % self.memory)
|
||||
else:
|
||||
tmpmem = 0
|
||||
|
||||
|
@ -134,10 +127,12 @@ class ImageFeatures(CapabilitiesParser.Features):
|
|||
elif state == "off":
|
||||
d[feature] = CapabilitiesParser.FEATURE_OFF
|
||||
else:
|
||||
raise ParserException("The state for feature %s must be either 'on' or 'off', but is '%s'" % (feature, state))
|
||||
raise RuntimeError("The state for feature %s must be "
|
||||
"either 'on' or 'off', but is '%s'" %
|
||||
(feature, state))
|
||||
|
||||
|
||||
class Boot:
|
||||
class Boot(object):
|
||||
"""The overall description of how the image can be booted, including
|
||||
required capabilities of the host and mapping of disks into the VM"""
|
||||
def __init__(self, node=None):
|
||||
|
@ -168,7 +163,9 @@ class Boot:
|
|||
|
||||
fl = node.xpathEval("guest/features")
|
||||
if len(fl) > 1:
|
||||
raise ParserException("Expected at most one <features> element in %s boot descriptor for %s" % (self.type, self.arch))
|
||||
raise RuntimeError("Expected at most one <features> element "
|
||||
"in %s boot descriptor for %s" %
|
||||
(self.type, self.arch))
|
||||
elif len(fl) == 1:
|
||||
self.features = ImageFeatures(fl[0])
|
||||
|
||||
|
@ -188,7 +185,7 @@ class Boot:
|
|||
# and without a loader
|
||||
|
||||
|
||||
class Drive:
|
||||
class Drive(object):
|
||||
"""The mapping of a disk from the storage section to a virtual drive
|
||||
in a guest"""
|
||||
def __init__(self, node=None):
|
||||
|
@ -203,7 +200,7 @@ class Drive:
|
|||
self.target = xpathString(node, "@target")
|
||||
|
||||
|
||||
class Disk:
|
||||
class Disk(object):
|
||||
FORMAT_RAW = "raw"
|
||||
FORMAT_ISO = "iso"
|
||||
FORMAT_QCOW = "qcow"
|
||||
|
@ -298,7 +295,7 @@ class Disk:
|
|||
|
||||
def validate(cond, msg):
|
||||
if not cond:
|
||||
raise ParserException(msg)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
def xpathString(node, path, default=None):
|
||||
|
@ -312,35 +309,9 @@ def parse(xml, filename):
|
|||
"""Parse the XML description of a VM image into a data structure. Returns
|
||||
an object of class Image. BASE should be the directory where the disk
|
||||
image files for this image can be found"""
|
||||
|
||||
class ErrorHandler:
|
||||
def __init__(self):
|
||||
self.msg = ""
|
||||
def handler(self, ignore, s):
|
||||
self.msg += s
|
||||
error = ErrorHandler()
|
||||
libxml2.registerErrorHandler(error.handler, None)
|
||||
|
||||
try:
|
||||
try:
|
||||
doc = libxml2.readMemory(xml, len(xml),
|
||||
None, None,
|
||||
libxml2.XML_PARSE_NOBLANKS)
|
||||
except (libxml2.parserError, libxml2.treeError), e:
|
||||
raise ParserException("%s\n%s" % (e, error.msg))
|
||||
finally:
|
||||
libxml2.registerErrorHandler(None, None)
|
||||
|
||||
try:
|
||||
root = doc.getRootElement()
|
||||
if root.name != "image":
|
||||
raise ParserException(_("Root element is not 'image'"))
|
||||
|
||||
image = Image(root, filename=filename)
|
||||
finally:
|
||||
doc.freeDoc()
|
||||
|
||||
return image
|
||||
def cb(x):
|
||||
return Image(x, filename=filename)
|
||||
return util.parse_node_helper(xml, "image", cb, RuntimeError)
|
||||
|
||||
|
||||
def parse_file(filename):
|
||||
|
|
|
@ -28,7 +28,6 @@ from virtinst import util
|
|||
import virtinst
|
||||
from virtinst import XMLBuilderDomain
|
||||
from virtinst.XMLBuilderDomain import _xml_property
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst.Boot import Boot
|
||||
|
||||
XEN_SCRATCH = "/var/lib/xen"
|
||||
|
@ -65,12 +64,12 @@ class Installer(XMLBuilderDomain.XMLBuilderDomain):
|
|||
|
||||
def __init__(self, conn, type="xen", location=None,
|
||||
extraargs=None, os_type=None,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
parsexml=None, parsexmlnode=None):
|
||||
# pylint: disable=W0622
|
||||
# Redefining built-in 'type', but it matches the XML so keep it
|
||||
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps=caps)
|
||||
parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
self._location = None
|
||||
|
@ -91,10 +90,7 @@ class Installer(XMLBuilderDomain.XMLBuilderDomain):
|
|||
if self._is_parse():
|
||||
return
|
||||
|
||||
# FIXME: Better solution? Skip validating this since we may not be
|
||||
# able to install a VM of the host arch
|
||||
if self._get_caps():
|
||||
self._arch = self._get_caps().host.arch
|
||||
self._arch = self.conn.caps.host.arch
|
||||
|
||||
if type is None:
|
||||
type = "xen"
|
||||
|
@ -414,12 +410,10 @@ class Installer(XMLBuilderDomain.XMLBuilderDomain):
|
|||
if not self.conn:
|
||||
raise ValueError(_("A connection must be specified."))
|
||||
|
||||
guest, domain = CapabilitiesParser.guest_lookup(conn=self.conn,
|
||||
caps=self._get_caps(),
|
||||
os_type=self.os_type,
|
||||
typ=self.type,
|
||||
arch=self.arch,
|
||||
machine=self.machine)
|
||||
guest, domain = self.conn.caps.guest_lookup(os_type=self.os_type,
|
||||
typ=self.type,
|
||||
arch=self.arch,
|
||||
machine=self.machine)
|
||||
|
||||
gobj = virtinst.Guest(self.conn, installer=self)
|
||||
gobj.arch = guest.arch
|
||||
|
|
|
@ -42,9 +42,9 @@ class Seclabel(XMLBuilderDomain.XMLBuilderDomain):
|
|||
SECLABEL_MODEL_NONE]
|
||||
|
||||
_dumpxml_xpath = "/domain/seclabel"
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
self._model = None
|
||||
|
@ -59,23 +59,19 @@ class Seclabel(XMLBuilderDomain.XMLBuilderDomain):
|
|||
self.type = self.SECLABEL_TYPE_DEFAULT
|
||||
|
||||
def _get_default_model(self):
|
||||
caps = self._get_caps()
|
||||
if caps:
|
||||
if (self.SECLABEL_MODEL_TEST in
|
||||
[x.model for x in caps.host.secmodels]):
|
||||
return self.SECLABEL_MODEL_TEST
|
||||
if (self.SECLABEL_MODEL_TEST in
|
||||
[x.model for x in self.conn.caps.host.secmodels]):
|
||||
return self.SECLABEL_MODEL_TEST
|
||||
|
||||
for model in self.SECLABEL_MODELS:
|
||||
if model in [x.model for x in caps.host.secmodels]:
|
||||
return model
|
||||
for model in self.SECLABEL_MODELS:
|
||||
if model in [x.model for x in self.conn.caps.host.secmodels]:
|
||||
return model
|
||||
raise RuntimeError("No supported model found in capabilities")
|
||||
|
||||
def _guess_secmodel(self, label, imagelabel):
|
||||
# We always want the testSecurity model when running tests
|
||||
caps = self._get_caps()
|
||||
if (caps and
|
||||
self.SECLABEL_MODEL_TEST in
|
||||
[x.model for x in caps.host.secmodels]):
|
||||
if (self.SECLABEL_MODEL_TEST in
|
||||
[x.model for x in self.conn.caps.host.secmodels]):
|
||||
return self.SECLABEL_MODEL_TEST
|
||||
|
||||
if not label and not imagelabel:
|
||||
|
|
|
@ -28,9 +28,8 @@ class VirtualAudio(VirtualDevice):
|
|||
MODEL_DEFAULT = "default"
|
||||
MODELS = ["es1370", "sb16", "pcspk", "ac97", "ich6", MODEL_DEFAULT]
|
||||
|
||||
def __init__(self, conn, model=None,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)
|
||||
def __init__(self, conn, model=None, parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._model = None
|
||||
if self._is_parse():
|
||||
|
|
|
@ -175,15 +175,13 @@ class VirtualCharDevice(VirtualDevice):
|
|||
return c(conn, dev_type)
|
||||
get_dev_instance = staticmethod(get_dev_instance)
|
||||
|
||||
def __init__(self, conn, dev_type,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, dev_type, parsexml=None, parsexmlnode=None):
|
||||
if dev_type not in self.dev_types:
|
||||
raise ValueError(_("Unknown character device type '%s'") % dev_type)
|
||||
self._dev_type = dev_type
|
||||
self._virtual_device_type = self._dev_type
|
||||
|
||||
VirtualDevice.__init__(self, conn,
|
||||
parsexml, parsexmlnode, caps)
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
# Init
|
||||
self._source_path = None
|
||||
|
@ -626,8 +624,8 @@ class VirtualCharSpicevmcDevice(VirtualCharDevice):
|
|||
has_target = True
|
||||
|
||||
def __init__(self, conn, dev_type=VirtualCharDevice.DEV_CHANNEL,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
parsexml=None, parsexmlnode=None):
|
||||
VirtualCharDevice.__init__(self, conn, dev_type,
|
||||
parsexml, parsexmlnode, caps)
|
||||
parsexml, parsexmlnode)
|
||||
self._target_type = VirtualCharDevice.CHAR_CHANNEL_TARGET_VIRTIO
|
||||
self._target_name = "com.redhat.spice.0"
|
||||
|
|
|
@ -76,10 +76,8 @@ class VirtualController(VirtualDevice):
|
|||
|
||||
_controller_type = None
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None,
|
||||
model=None):
|
||||
VirtualDevice.__init__(self, conn,
|
||||
parsexml, parsexmlnode, caps)
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, model=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._index = 0
|
||||
self._ports = None
|
||||
|
@ -87,8 +85,7 @@ class VirtualController(VirtualDevice):
|
|||
self._model = None
|
||||
self._master = VirtualDeviceMaster(conn,
|
||||
parsexml=parsexml,
|
||||
parsexmlnode=parsexmlnode,
|
||||
caps=caps)
|
||||
parsexmlnode=parsexmlnode)
|
||||
|
||||
if self._is_parse():
|
||||
return
|
||||
|
@ -187,9 +184,8 @@ class VirtualControllerUSB(VirtualController):
|
|||
|
||||
|
||||
class VirtualDeviceMaster(XMLBuilderDomain):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode,
|
||||
caps=caps)
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._startport = None
|
||||
|
||||
|
|
|
@ -71,23 +71,20 @@ class VirtualDevice(XMLBuilderDomain):
|
|||
# General device type (disk, interface, etc.)
|
||||
_virtual_device_type = None
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
"""
|
||||
Initialize device state
|
||||
|
||||
@param conn: libvirt connection to validate device against
|
||||
"""
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode,
|
||||
caps=caps)
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self.alias = VirtualDeviceAlias(conn,
|
||||
parsexml=parsexml,
|
||||
parsexmlnode=parsexmlnode,
|
||||
caps=caps)
|
||||
parsexmlnode=parsexmlnode)
|
||||
self.address = VirtualDeviceAddress(conn,
|
||||
parsexml=parsexml,
|
||||
parsexmlnode=parsexmlnode,
|
||||
caps=caps)
|
||||
parsexmlnode=parsexmlnode)
|
||||
|
||||
if not self._virtual_device_type:
|
||||
raise ValueError(_("Virtual device type must be set in subclass."))
|
||||
|
@ -121,9 +118,8 @@ class VirtualDevice(XMLBuilderDomain):
|
|||
|
||||
|
||||
class VirtualDeviceAlias(XMLBuilderDomain):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode,
|
||||
caps=caps)
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._name = None
|
||||
|
||||
|
@ -150,10 +146,9 @@ class VirtualDeviceAddress(XMLBuilderDomain):
|
|||
ADDRESS_TYPE_VIRTIO_SERIAL, ADDRESS_TYPE_CCID,
|
||||
ADDRESS_TYPE_SPAPR_VIO]
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None,
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None,
|
||||
addrstr=None):
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode,
|
||||
caps=caps)
|
||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ class VirtualDisk(VirtualDevice):
|
|||
readOnly=False, sparse=True, volObject=None,
|
||||
volInstall=None, volName=None, bus=None, shareable=False,
|
||||
driverCache=None, format=None,
|
||||
validate=True, parsexml=None, parsexmlnode=None, caps=None,
|
||||
validate=True, parsexml=None, parsexmlnode=None,
|
||||
driverIO=None, sizebytes=None, nomanaged=False):
|
||||
"""
|
||||
@param path: filesystem path to the disk image.
|
||||
|
@ -583,8 +583,7 @@ class VirtualDisk(VirtualDevice):
|
|||
"""
|
||||
|
||||
VirtualDevice.__init__(self, conn=conn,
|
||||
parsexml=parsexml, parsexmlnode=parsexmlnode,
|
||||
caps=caps)
|
||||
parsexml=parsexml, parsexmlnode=parsexmlnode)
|
||||
|
||||
self._path = None
|
||||
self._size = None
|
||||
|
|
|
@ -70,9 +70,8 @@ class VirtualFilesystem(VirtualDevice):
|
|||
return "dev"
|
||||
return "dir"
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
self._mode = None
|
||||
|
|
|
@ -93,11 +93,11 @@ class VirtualGraphics(VirtualDevice):
|
|||
def __init__(self, conn, type=TYPE_VNC, port=-1, listen=None, passwd=None,
|
||||
keymap=KEYMAP_DEFAULT, parsexml=None,
|
||||
parsexmlnode=None, tlsPort=-1, channels=None,
|
||||
caps=None, passwdValidTo=None):
|
||||
passwdValidTo=None):
|
||||
# pylint: disable=W0622
|
||||
# Redefining built-in 'type', but it matches the XML so keep it
|
||||
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
self._port = None
|
||||
|
|
|
@ -71,7 +71,7 @@ class VirtualHostDevice(VirtualDevice):
|
|||
device_from_node = staticmethod(device_from_node)
|
||||
|
||||
def __init__(self, conn, nodedev=None,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
parsexml=None, parsexmlnode=None):
|
||||
"""
|
||||
@param conn: Connection the device/guest will be installed on
|
||||
@type conn: libvirt.virConnect
|
||||
|
@ -79,8 +79,7 @@ class VirtualHostDevice(VirtualDevice):
|
|||
attached to the guest
|
||||
@type nodedev: L{virtinst.NodeDeviceParser.NodeDevice}
|
||||
"""
|
||||
VirtualDevice.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._mode = None
|
||||
self._type = None
|
||||
|
|
|
@ -37,9 +37,8 @@ class VirtualInputDevice(VirtualDevice):
|
|||
input_buses = [INPUT_BUS_PS2, INPUT_BUS_USB, INPUT_BUS_XEN,
|
||||
INPUT_BUS_DEFAULT]
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
self._bus = None
|
||||
|
|
|
@ -29,9 +29,8 @@ class VirtualMemballoon(VirtualDevice):
|
|||
MODELS = ["xen", "none", MODEL_DEFAULT]
|
||||
|
||||
def __init__(self, conn=None, model=MODEL_DEFAULT,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._model = None
|
||||
|
||||
|
|
|
@ -68,9 +68,9 @@ def _countMACaddr(vms, searchmac):
|
|||
|
||||
class VirtualPort(XMLBuilderDomain.XMLBuilderDomain):
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps=caps)
|
||||
parsexmlnode)
|
||||
self._type = None
|
||||
self._managerid = None
|
||||
self._typeid = None
|
||||
|
@ -147,11 +147,11 @@ class VirtualNetworkInterface(VirtualDevice):
|
|||
|
||||
def __init__(self, conn, macaddr=None, type=TYPE_BRIDGE, bridge=None,
|
||||
network=None, model=None,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
parsexml=None, parsexmlnode=None):
|
||||
# pylint: disable=W0622
|
||||
# Redefining built-in 'type', but it matches the XML so keep it
|
||||
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._network = None
|
||||
self._bridge = None
|
||||
|
@ -161,7 +161,7 @@ class VirtualNetworkInterface(VirtualDevice):
|
|||
self._target_dev = None
|
||||
self._source_dev = None
|
||||
self._source_mode = "vepa"
|
||||
self._virtualport = VirtualPort(conn, parsexml, parsexmlnode, caps)
|
||||
self._virtualport = VirtualPort(conn, parsexml, parsexmlnode)
|
||||
|
||||
# Generate _random_mac
|
||||
self._random_mac = None
|
||||
|
|
|
@ -35,12 +35,8 @@ class VirtualRedirDevice(VirtualDevice):
|
|||
_types = ["tcp", "spicevmc", None]
|
||||
|
||||
def __init__(self, conn, bus=BUS_DEFAULT, stype=TYPE_DEFAULT,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
"""
|
||||
@param conn: Connection the device/guest will be installed on
|
||||
@type conn: libvirt.virConnect
|
||||
"""
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)
|
||||
parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
self._bus = None
|
||||
|
|
|
@ -35,9 +35,8 @@ class VirtualSmartCardDevice(VirtualDevice):
|
|||
_types = ["tcp", "spicevmc", None]
|
||||
|
||||
def __init__(self, conn, mode=MODE_DEFAULT,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn,
|
||||
parsexml, parsexmlnode, caps)
|
||||
parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._mode = None
|
||||
self._type = None
|
||||
|
|
|
@ -59,8 +59,8 @@ class VirtualTPMDevice(VirtualDevice):
|
|||
get_dev_instance = staticmethod(get_dev_instance)
|
||||
|
||||
def __init__(self, conn, typ=TYPE_DEFAULT,
|
||||
parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)
|
||||
parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._type = None
|
||||
self._model = self.TPM_TIS
|
||||
|
|
|
@ -35,9 +35,8 @@ class VirtualVideoDevice(VirtualDevice):
|
|||
return model.upper()
|
||||
return model.capitalize()
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn,
|
||||
parsexml, parsexmlnode, caps)
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._model_type = None
|
||||
self._vram = None
|
||||
|
|
|
@ -55,9 +55,8 @@ class VirtualWatchdog(VirtualDevice):
|
|||
else:
|
||||
return action
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml,
|
||||
parsexmlnode, caps)
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
|
||||
|
||||
self._model = None
|
||||
self._action = None
|
||||
|
|
|
@ -24,7 +24,6 @@ import threading
|
|||
|
||||
import libxml2
|
||||
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst import util
|
||||
|
||||
_xml_refs_lock = threading.Lock()
|
||||
|
@ -389,7 +388,7 @@ class XMLBuilderDomain(object):
|
|||
"""
|
||||
|
||||
_dumpxml_xpath = "."
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
"""
|
||||
Initialize state
|
||||
|
||||
|
@ -398,20 +397,12 @@ class XMLBuilderDomain(object):
|
|||
@param parsexml: Optional XML string to parse
|
||||
@type parsexml: C{str}
|
||||
@param parsexmlnode: Option xpathNode to use
|
||||
@param caps: Capabilities() instance
|
||||
"""
|
||||
self._conn = conn
|
||||
self.__caps = None
|
||||
|
||||
self._xml_node = None
|
||||
self._xml_ctx = None
|
||||
|
||||
|
||||
if caps:
|
||||
if not isinstance(caps, CapabilitiesParser.Capabilities):
|
||||
raise ValueError("caps must be a Capabilities instance")
|
||||
self.__caps = caps
|
||||
|
||||
if parsexml or parsexmlnode:
|
||||
self._parsexml(parsexml, parsexmlnode)
|
||||
|
||||
|
@ -447,11 +438,6 @@ class XMLBuilderDomain(object):
|
|||
return self._conn
|
||||
conn = property(_get_conn)
|
||||
|
||||
def _get_caps(self):
|
||||
if not self.__caps:
|
||||
self.__caps = CapabilitiesParser.parse(self.conn.getCapabilities())
|
||||
return self.__caps
|
||||
|
||||
def _check_bool(self, val, name):
|
||||
if val not in [True, False]:
|
||||
raise ValueError(_("'%s' must be True or False" % name))
|
||||
|
|
|
@ -23,6 +23,7 @@ import re
|
|||
import libvirt
|
||||
|
||||
from virtinst import support
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst.cli import parse_optstr
|
||||
from virtinst.util import uri_split
|
||||
|
||||
|
@ -54,6 +55,8 @@ class VirtualConnection(object):
|
|||
self._libvirtconn = None
|
||||
self._urisplits = uri_split(self._uri)
|
||||
|
||||
self._caps = None
|
||||
|
||||
|
||||
# Just proxy virConnect access for now
|
||||
def __getattr__(self, attr):
|
||||
|
@ -73,6 +76,13 @@ class VirtualConnection(object):
|
|||
|
||||
libvirtconn = property(lambda self: getattr(self, "_libvirtconn"))
|
||||
|
||||
def _get_caps(self):
|
||||
if not self._caps:
|
||||
self._caps = CapabilitiesParser.Capabilities(
|
||||
self.libvirtconn.getCapabilities())
|
||||
return self._caps
|
||||
caps = property(_get_caps)
|
||||
|
||||
|
||||
##############
|
||||
# Public API #
|
||||
|
@ -82,6 +92,9 @@ class VirtualConnection(object):
|
|||
self._libvirtconn = None
|
||||
self._uri = None
|
||||
|
||||
def invalidate_caps(self):
|
||||
self._caps = None
|
||||
|
||||
def is_open(self):
|
||||
return bool(self._libvirtconn)
|
||||
|
||||
|
|
Loading…
Reference in New Issue