mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-10-27 01:55:20 +03:00
capabilities: Store results of guest_lookup together
Simplifies API users lives to not have to remember whether caps guest or caps domain contains a particular value.
This commit is contained in:
parent
81a1910d90
commit
97259c4d9b
21
virt-install
21
virt-install
@ -353,23 +353,21 @@ def get_guest(conn, options):
|
||||
arch = "i686"
|
||||
|
||||
try:
|
||||
(capsguest,
|
||||
capsdomain) = conn.caps.guest_lookup(
|
||||
os_type=req_virt_type,
|
||||
arch=arch,
|
||||
typ=req_hv_type,
|
||||
machine=options.machine)
|
||||
guest = conn.caps.build_virtinst_guest(conn, capsguest, capsdomain)
|
||||
guest = conn.caps.lookup_virtinst_guest(
|
||||
os_type=req_virt_type,
|
||||
arch=arch,
|
||||
typ=req_hv_type,
|
||||
machine=options.machine)
|
||||
except Exception, e:
|
||||
fail(e)
|
||||
|
||||
if (not req_virt_type and
|
||||
not req_hv_type and
|
||||
conn.is_qemu() and
|
||||
capsguest.arch in ["i686", "x86_64"] and
|
||||
not capsdomain.is_accelerated()):
|
||||
guest.os.arch in ["i686", "x86_64"] and
|
||||
not guest.type == "kvm"):
|
||||
logging.warn("KVM acceleration not available, using '%s'",
|
||||
capsdomain.hypervisor_type)
|
||||
guest.type)
|
||||
|
||||
return guest
|
||||
|
||||
@ -398,8 +396,7 @@ def set_install_media(guest, location, cdpath, distro_variant):
|
||||
|
||||
|
||||
def do_test_media_detection(conn, url):
|
||||
(capsguest, capsdomain) = conn.caps.guest_lookup()
|
||||
guest = conn.caps.build_virtinst_guest(conn, capsguest, capsdomain)
|
||||
guest = conn.caps.lookup_virtinst_guest()
|
||||
guest.installer = virtinst.DistroInstaller(conn)
|
||||
guest.installer.location = url
|
||||
print_stdout(guest.installer.detect_distro(guest), do_force=True)
|
||||
|
@ -82,8 +82,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
self.engine = engine
|
||||
|
||||
self.conn = None
|
||||
self.capsguest = None
|
||||
self.capsdomain = None
|
||||
self.capsinfo = None
|
||||
|
||||
self.guest = None
|
||||
self.disk = None
|
||||
@ -186,8 +185,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
self.remove_conn()
|
||||
|
||||
self.conn = None
|
||||
self.capsguest = None
|
||||
self.capsdomain = None
|
||||
self.capsinfo = None
|
||||
|
||||
self.guest = None
|
||||
self.disk = None
|
||||
@ -212,8 +210,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
|
||||
def remove_conn(self):
|
||||
self.conn = None
|
||||
self.capsguest = None
|
||||
self.capsdomain = None
|
||||
self.capsinfo = None
|
||||
|
||||
def set_conn(self, newconn, force_validate=False):
|
||||
if self.conn == newconn and not force_validate:
|
||||
@ -407,23 +404,22 @@ class vmmCreate(vmmGObjectUI):
|
||||
self.topwin.resize(1, 1)
|
||||
|
||||
def set_caps_state(self):
|
||||
# State that is dependent on when capsguest changes
|
||||
# State that is dependent on when capsinfo changes
|
||||
|
||||
# Helper state
|
||||
is_local = not self.conn.is_remote()
|
||||
is_storage_capable = self.conn.is_storage_capable()
|
||||
can_storage = (is_local or is_storage_capable)
|
||||
is_pv = (self.capsguest.os_type == "xen")
|
||||
is_pv = (self.capsinfo.os_type == "xen")
|
||||
is_container = self.conn.is_container()
|
||||
can_remote_url = self.conn.get_backend().support_remote_url_install()
|
||||
|
||||
installable_arch = (self.capsguest.arch in
|
||||
installable_arch = (self.capsinfo.arch in
|
||||
["i686", "x86_64", "ppc64", "ia64"])
|
||||
|
||||
if self.capsguest.arch == "aarch64":
|
||||
if self.capsinfo.arch == "aarch64":
|
||||
try:
|
||||
guest = self.conn.caps.build_virtinst_guest(
|
||||
self.conn.get_backend(), self.capsguest, self.capsdomain)
|
||||
guest = self.conn.caps.build_virtinst_guest(self.capsinfo)
|
||||
guest.set_uefi_default()
|
||||
installable_arch = True
|
||||
logging.debug("UEFI found for aarch64, setting it as default.")
|
||||
@ -470,7 +466,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
|
||||
if not installable_arch:
|
||||
msg = (_("Architecture '%s' is not installable") %
|
||||
self.capsguest.arch)
|
||||
self.capsinfo.arch)
|
||||
tree_tt = msg
|
||||
local_tt = msg
|
||||
pxe_tt = msg
|
||||
@ -498,9 +494,9 @@ class vmmCreate(vmmGObjectUI):
|
||||
self.widget("virt-install-box").set_visible(not is_container)
|
||||
self.widget("container-install-box").set_visible(is_container)
|
||||
|
||||
show_dtb = ("arm" in self.capsguest.arch or
|
||||
"microblaze" in self.capsguest.arch or
|
||||
"ppc" in self.capsguest.arch)
|
||||
show_dtb = ("arm" in self.capsinfo.arch or
|
||||
"microblaze" in self.capsinfo.arch or
|
||||
"ppc" in self.capsinfo.arch)
|
||||
self.widget("config-kernel-box").set_visible(not installable_arch)
|
||||
uiutil.set_grid_row_visible(self.widget("config-dtb"), show_dtb)
|
||||
|
||||
@ -663,8 +659,8 @@ class vmmCreate(vmmGObjectUI):
|
||||
continue
|
||||
|
||||
# Determine if this is the default given by guest_lookup
|
||||
if (gtype == self.capsguest.os_type and
|
||||
self.capsdomain.hypervisor_type == domtype):
|
||||
if (gtype == self.capsinfo.os_type and
|
||||
self.capsinfo.hypervisor_type == domtype):
|
||||
default = len(model)
|
||||
|
||||
model.append([label, gtype])
|
||||
@ -682,7 +678,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
default = 0
|
||||
archs = []
|
||||
for guest in self.conn.caps.guests:
|
||||
if guest.os_type == self.capsguest.os_type:
|
||||
if guest.os_type == self.capsinfo.os_type:
|
||||
archs.append(guest.arch)
|
||||
|
||||
# Combine x86/i686 to avoid confusion
|
||||
@ -706,8 +702,8 @@ class vmmCreate(vmmGObjectUI):
|
||||
archs = prios + archs
|
||||
|
||||
default = 0
|
||||
if self.capsguest.arch in archs:
|
||||
default = archs.index(self.capsguest.arch)
|
||||
if self.capsinfo.arch in archs:
|
||||
default = archs.index(self.capsinfo.arch)
|
||||
|
||||
for arch in archs:
|
||||
model.append([arch, pretty_arch(arch)])
|
||||
@ -721,15 +717,14 @@ class vmmCreate(vmmGObjectUI):
|
||||
model = lst.get_model()
|
||||
model.clear()
|
||||
|
||||
machines = self.capsdomain.machines[:]
|
||||
if self.capsguest.arch in ["i686", "x86_64"]:
|
||||
machines = self.capsinfo.machines[:]
|
||||
if self.capsinfo.arch in ["i686", "x86_64"]:
|
||||
machines = []
|
||||
machines.sort()
|
||||
|
||||
defmachine = None
|
||||
prios = []
|
||||
recommended_machine = self.capsdomain.get_recommended_machine(
|
||||
self.conn.get_backend(), self.capsguest)
|
||||
recommended_machine = self.capsinfo.get_recommended_machine()
|
||||
if recommended_machine:
|
||||
defmachine = recommended_machine
|
||||
prios = [defmachine]
|
||||
@ -889,17 +884,19 @@ class vmmCreate(vmmGObjectUI):
|
||||
gtype = "hvm"
|
||||
break
|
||||
|
||||
(newg, newdom) = self.conn.caps.guest_lookup(os_type=gtype, arch=arch)
|
||||
capsinfo = self.conn.caps.guest_lookup(os_type=gtype, arch=arch)
|
||||
newg, newdom = capsinfo.get_caps_objects()
|
||||
|
||||
if self.capsguest == newg and self.capsdomain and newdom:
|
||||
return
|
||||
if self.capsinfo:
|
||||
oldg, olddom = self.capsinfo.get_caps_objects()
|
||||
if oldg == newg and olddom and newdom:
|
||||
return
|
||||
|
||||
self.capsguest = newg
|
||||
self.capsdomain = newdom
|
||||
self.capsinfo = capsinfo
|
||||
logging.debug("Guest type set to os_type=%s, arch=%s, dom_type=%s",
|
||||
self.capsguest.os_type,
|
||||
self.capsguest.arch,
|
||||
self.capsdomain.hypervisor_type)
|
||||
self.capsinfo.os_type,
|
||||
self.capsinfo.arch,
|
||||
self.capsinfo.hypervisor_type)
|
||||
self.populate_machine()
|
||||
self.set_caps_state()
|
||||
|
||||
@ -1108,7 +1105,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
|
||||
def machine_changed(self, ignore):
|
||||
machine = self.get_config_machine()
|
||||
show_dtb_virtio = (self.capsguest.arch == "armv7l" and
|
||||
show_dtb_virtio = (self.capsinfo.arch == "armv7l" and
|
||||
machine in ["vexpress-a9", "vexpress-15"])
|
||||
uiutil.set_grid_row_visible(
|
||||
self.widget("config-dtb-warn-virtio"), show_dtb_virtio)
|
||||
@ -1154,7 +1151,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
if not arch:
|
||||
return
|
||||
|
||||
self.change_caps(self.capsguest.os_type, arch)
|
||||
self.change_caps(self.capsinfo.os_type, arch)
|
||||
|
||||
def media_box_changed(self, widget):
|
||||
self.mediaDetected = False
|
||||
@ -1408,8 +1405,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
page.set_visible(nr == pagenum)
|
||||
|
||||
def build_guest(self, variant):
|
||||
guest = self.conn.caps.build_virtinst_guest(
|
||||
self.conn.get_backend(), self.capsguest, self.capsdomain)
|
||||
guest = self.conn.caps.build_virtinst_guest(self.capsinfo)
|
||||
guest.os.machine = self.get_config_machine()
|
||||
|
||||
# Generate UUID (makes customize dialog happy)
|
||||
@ -1627,11 +1623,11 @@ class vmmCreate(vmmGObjectUI):
|
||||
self.guest.os.dtb = dtb
|
||||
self.guest.os.kernel_args = kargs
|
||||
|
||||
require_kernel = ("arm" in self.capsguest.arch)
|
||||
require_kernel = ("arm" in self.capsinfo.arch)
|
||||
if require_kernel and not kernel:
|
||||
return self.err.val_err(
|
||||
_("A kernel is required for %s guests.") %
|
||||
self.capsguest.arch)
|
||||
self.capsinfo.arch)
|
||||
|
||||
try:
|
||||
name = self._generate_default_name(distro, variant)
|
||||
@ -2092,8 +2088,8 @@ class vmmCreate(vmmGObjectUI):
|
||||
emu = None
|
||||
if self.guest:
|
||||
emu = self.guest.emulator
|
||||
elif self.capsdomain:
|
||||
emu = self.capsdomain.emulator
|
||||
elif self.capsinfo:
|
||||
emu = self.capsinfo.emulator
|
||||
|
||||
ret = self.conn.stable_defaults(emu)
|
||||
return ret
|
||||
|
@ -758,13 +758,13 @@ class vmmDetails(vmmGObjectUI):
|
||||
|
||||
machines = []
|
||||
try:
|
||||
ignore, domain = caps.guest_lookup(
|
||||
capsinfo = caps.guest_lookup(
|
||||
os_type=self.vm.get_abi_type(),
|
||||
arch=self.vm.get_arch(),
|
||||
typ=self.vm.get_hv_type(),
|
||||
machine=self.vm.get_machtype())
|
||||
|
||||
machines = domain.machines[:]
|
||||
machines = capsinfo.machines[:]
|
||||
except:
|
||||
logging.exception("Error determining machine list")
|
||||
|
||||
|
@ -316,8 +316,7 @@ def _import_file(doc, ctx, conn, input_file):
|
||||
ignore = os_id
|
||||
ignore = os_vmware
|
||||
|
||||
(capsguest, capsdomain) = conn.caps.guest_lookup()
|
||||
guest = conn.caps.build_virtinst_guest(conn, capsguest, capsdomain)
|
||||
guest = conn.caps.lookup_virtinst_guest()
|
||||
guest.installer = virtinst.ImportInstaller(conn)
|
||||
|
||||
if not name:
|
||||
|
@ -295,8 +295,7 @@ class vmx_parser(parser_class):
|
||||
not os.path.exists(disk.path)):
|
||||
disk.path = None
|
||||
|
||||
(capsguest, capsdomain) = conn.caps.guest_lookup()
|
||||
guest = conn.caps.build_virtinst_guest(conn, capsguest, capsdomain)
|
||||
guest = conn.caps.lookup_virtinst_guest()
|
||||
guest.installer = virtinst.ImportInstaller(conn)
|
||||
|
||||
guest.name = name.replace(" ", "_")
|
||||
|
@ -222,15 +222,17 @@ class _CapsDomain(XMLBuilder):
|
||||
# Public APIs #
|
||||
###############
|
||||
|
||||
def get_recommended_machine(self, conn, capsguest):
|
||||
def get_recommended_machine(self, capsguest):
|
||||
if self._recommended_machine:
|
||||
return self._recommended_machine
|
||||
|
||||
if not conn.is_test() and not conn.is_qemu():
|
||||
if not self.conn.is_test() and not self.conn.is_qemu():
|
||||
return None
|
||||
|
||||
if capsguest.arch in ["ppc64", "ppc64le"] and "pseries" in self.machines:
|
||||
if (capsguest.arch in ["ppc64", "ppc64le"] and
|
||||
"pseries" in self.machines):
|
||||
return "pseries"
|
||||
|
||||
if capsguest.arch in ["armv7l", "aarch64"]:
|
||||
if "virt" in self.machines:
|
||||
return "virt"
|
||||
@ -242,9 +244,6 @@ class _CapsDomain(XMLBuilder):
|
||||
def set_recommended_machine(self, machine):
|
||||
self._recommended_machine = machine
|
||||
|
||||
def is_accelerated(self):
|
||||
return self.hypervisor_type in ["kvm"]
|
||||
|
||||
|
||||
class _CapsGuestFeatures(XMLBuilder):
|
||||
_XML_ROOT_NAME = "features"
|
||||
@ -259,17 +258,17 @@ class _CapsGuest(XMLBuilder):
|
||||
def __init__(self, *args, **kwargs):
|
||||
XMLBuilder.__init__(self, *args, **kwargs)
|
||||
|
||||
self.machines = []
|
||||
machines = []
|
||||
for m in self._machines:
|
||||
self.machines.append(m.name)
|
||||
machines.append(m.name)
|
||||
if m.canonical:
|
||||
self.machines.append(m.canonical)
|
||||
machines.append(m.canonical)
|
||||
|
||||
for d in self.domains:
|
||||
if not d.emulator:
|
||||
d.emulator = self.emulator
|
||||
d.emulator = self._emulator
|
||||
if not d.machines:
|
||||
d.machines = self.machines
|
||||
d.machines = machines
|
||||
|
||||
|
||||
_XML_ROOT_NAME = "guest"
|
||||
@ -277,7 +276,7 @@ class _CapsGuest(XMLBuilder):
|
||||
os_type = XMLProperty("./os_type")
|
||||
arch = XMLProperty("./arch/@name")
|
||||
loader = XMLProperty("./arch/loader")
|
||||
emulator = XMLProperty("./arch/emulator")
|
||||
_emulator = XMLProperty("./arch/emulator")
|
||||
|
||||
domains = XMLChildProperty(_CapsDomain, relative_xpath="./arch")
|
||||
features = XMLChildProperty(_CapsGuestFeatures, is_single=True)
|
||||
@ -324,6 +323,30 @@ class _CapsGuest(XMLBuilder):
|
||||
# Main capabilities object #
|
||||
############################
|
||||
|
||||
class _CapsInfo(object):
|
||||
"""
|
||||
Container object to hold the results of guest_lookup, so users don't
|
||||
need to juggle two objects
|
||||
"""
|
||||
def __init__(self, guest, domain):
|
||||
self._guest = guest
|
||||
self._domain = domain
|
||||
|
||||
self.hypervisor_type = self._domain.hypervisor_type
|
||||
self.os_type = self._guest.os_type
|
||||
self.arch = self._guest.arch
|
||||
self.loader = self._guest.loader
|
||||
|
||||
self.emulator = self._domain.emulator
|
||||
self.machines = self._domain.machines[:]
|
||||
|
||||
def get_caps_objects(self):
|
||||
return self._guest, self._domain
|
||||
|
||||
def get_recommended_machine(self):
|
||||
return self._domain.get_recommended_machine(self._guest)
|
||||
|
||||
|
||||
class Capabilities(XMLBuilder):
|
||||
# Set by the test suite to force a particular code path
|
||||
_force_cpumap = False
|
||||
@ -453,7 +476,7 @@ class Capabilities(XMLBuilder):
|
||||
@param os_type: Hypervisor name ('qemu', 'kvm', 'xen', ...)
|
||||
@param machine: Optional machine type to emulate
|
||||
|
||||
@returns: A (Capabilities Guest, Capabilities Domain) tuple
|
||||
@returns: A _CapsInfo object containing the found guest and domain
|
||||
"""
|
||||
guest = self._guestForOSType(os_type, arch)
|
||||
if not guest:
|
||||
@ -479,16 +502,31 @@ class Capabilities(XMLBuilder):
|
||||
{'domain': typ, 'virttype': guest.os_type,
|
||||
'arch': guest.arch, 'machine': machinestr})
|
||||
|
||||
return (guest, domain)
|
||||
capsinfo = _CapsInfo(guest, domain)
|
||||
return capsinfo
|
||||
|
||||
def build_virtinst_guest(self, conn, guest, domain):
|
||||
def build_virtinst_guest(self, capsinfo):
|
||||
"""
|
||||
Fill in a new Guest() object from the results of guest_lookup
|
||||
"""
|
||||
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 = guest.loader
|
||||
gobj.emulator = domain.emulator
|
||||
gobj.os.machine = domain.get_recommended_machine(conn, guest)
|
||||
gobj = Guest(self.conn)
|
||||
gobj.type = capsinfo.hypervisor_type
|
||||
gobj.os.os_type = capsinfo.os_type
|
||||
gobj.os.arch = capsinfo.arch
|
||||
gobj.os.loader = capsinfo.loader
|
||||
gobj.emulator = capsinfo.emulator
|
||||
|
||||
gobj.os.machine = capsinfo.get_recommended_machine()
|
||||
|
||||
return gobj
|
||||
|
||||
def lookup_virtinst_guest(self, *args, **kwargs):
|
||||
"""
|
||||
Call guest_lookup and pass the results to build_virtinst_guest.
|
||||
|
||||
This is a shortcut for API users that don't need to do anything
|
||||
with the output from guest_lookup
|
||||
"""
|
||||
capsinfo = self.guest_lookup(*args, **kwargs)
|
||||
return self.build_virtinst_guest(capsinfo)
|
||||
|
Loading…
Reference in New Issue
Block a user