mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
support: Rework support check invocations
SupportCache.check_support(SUPPORT_FOOBAR, args) becomes SupportCache.foobar(args) And SupportCache absorbs the caching infrastructure from VirtinstConnection. For now we add some hackery to hide the API change from callers, but this will be undone in the next patch
This commit is contained in:
@@ -127,7 +127,7 @@ class SkipChecks:
|
||||
msg = check()
|
||||
skip = bool(msg)
|
||||
else:
|
||||
skip = not conn._check_version(check) # pylint: disable=protected-access
|
||||
skip = not conn.support._check_version(check) # pylint: disable=protected-access
|
||||
msg = "Skipping check due to version < %s" % check
|
||||
|
||||
if skip:
|
||||
|
||||
@@ -426,11 +426,11 @@ class vmmConnection(vmmGObject):
|
||||
# API support helpers #
|
||||
#######################
|
||||
|
||||
for _supportname in [_supportname for _supportname in
|
||||
dir(virtinst.VirtinstConnection) if
|
||||
_supportname.startswith("SUPPORT_")]:
|
||||
locals()[_supportname] = getattr(virtinst.VirtinstConnection,
|
||||
_supportname)
|
||||
def __getattr__(self, attr):
|
||||
if attr.startswith("SUPPORT_"):
|
||||
return getattr(self._backend.support, attr.split("_", 1)[1].lower())
|
||||
raise AttributeError
|
||||
|
||||
def check_support(self, *args):
|
||||
# pylint: disable=no-value-for-parameter
|
||||
return self._backend.check_support(*args)
|
||||
|
||||
@@ -57,7 +57,6 @@ class VirtinstConnection(object):
|
||||
self._uriobj = URI(self._uri)
|
||||
self._caps = None
|
||||
|
||||
self._support_cache = {}
|
||||
self._fetch_cache = {}
|
||||
|
||||
# These let virt-manager register a callback which provides its
|
||||
@@ -68,7 +67,7 @@ class VirtinstConnection(object):
|
||||
self.cb_fetch_all_nodedevs = None
|
||||
self.cb_cache_new_pool = None
|
||||
|
||||
self.support = support.SupportCache()
|
||||
self.support = support.SupportCache(weakref.proxy(self))
|
||||
|
||||
|
||||
##############
|
||||
@@ -79,6 +78,9 @@ class VirtinstConnection(object):
|
||||
if attr in self.__dict__:
|
||||
return self.__dict__[attr]
|
||||
|
||||
if attr.startswith("SUPPORT_"):
|
||||
return getattr(self.support, attr.split("_", 1)[1].lower())
|
||||
|
||||
# Proxy virConnect API calls
|
||||
libvirtconn = self.__dict__.get("_libvirtconn")
|
||||
return getattr(libvirtconn, attr)
|
||||
@@ -380,30 +382,13 @@ class VirtinstConnection(object):
|
||||
# Support check helpers #
|
||||
#########################
|
||||
|
||||
for _supportname in [_supportname for _supportname in
|
||||
dir(support.SupportCache) if
|
||||
_supportname.startswith("SUPPORT_")]:
|
||||
locals()[_supportname] = getattr(support.SupportCache, _supportname)
|
||||
|
||||
|
||||
def check_support(self, features, data=None):
|
||||
def _check_support(key):
|
||||
if key not in self._support_cache:
|
||||
self._support_cache[key] = self.support.check_support(
|
||||
self, key, data or self)
|
||||
return self._support_cache[key]
|
||||
|
||||
for f in util.listify(features):
|
||||
# 'and' condition over the feature list
|
||||
if not _check_support(f):
|
||||
if not f(data):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _check_version(self, version):
|
||||
# Entry point for the test suite to do simple version checks,
|
||||
# actual code should only use check_support
|
||||
return self.support.check_version(self, version)
|
||||
|
||||
def support_remote_url_install(self):
|
||||
if self._magic_uri:
|
||||
return False
|
||||
|
||||
@@ -162,16 +162,31 @@ class _SupportCheck(object):
|
||||
"support checks for libvirt versions less than 0.7.3, "
|
||||
"since required APIs were not available. ver=%s" % vstr)
|
||||
|
||||
def check_support(self, conn, data):
|
||||
def __call__(self, virtconn, data=None):
|
||||
"""
|
||||
Attempt to determine if a specific libvirt feature is support given
|
||||
the passed connection.
|
||||
|
||||
:param virtconn: VirtinstConnection to check feature on
|
||||
:param feature: Feature type to check support for
|
||||
:type feature: One of the SUPPORT_* flags
|
||||
:param data: Option libvirt object to use in feature checking
|
||||
:type data: Could be virDomain, virNetwork, virStoragePool, hv name, etc
|
||||
|
||||
:returns: True if feature is supported, False otherwise
|
||||
"""
|
||||
if "VirtinstConnection" in repr(data):
|
||||
data = data.get_conn_for_api_arg()
|
||||
|
||||
ret = _check_function(self.function, self.flag, self.run_args, data)
|
||||
if ret is not None:
|
||||
return ret
|
||||
|
||||
# Do this after the function check, since there's an ordering issue
|
||||
# with VirtinstConnection
|
||||
hv_type = conn.get_uri_driver()
|
||||
actual_libvirt_version = conn.daemon_version()
|
||||
actual_hv_version = conn.conn_version()
|
||||
hv_type = virtconn.get_uri_driver()
|
||||
actual_libvirt_version = virtconn.daemon_version()
|
||||
actual_hv_version = virtconn.conn_version()
|
||||
|
||||
# Check that local libvirt version is sufficient
|
||||
v = _version_str_to_int(self.version)
|
||||
@@ -197,145 +212,135 @@ class _SupportCheck(object):
|
||||
return True
|
||||
|
||||
|
||||
_SUPPORT_ID = 0
|
||||
_SUPPORT_OBJS = []
|
||||
|
||||
|
||||
def _make(*args, **kwargs):
|
||||
global _SUPPORT_ID
|
||||
_SUPPORT_ID += 1
|
||||
obj = _SupportCheck(*args, **kwargs)
|
||||
_SUPPORT_OBJS.append(obj)
|
||||
return _SUPPORT_ID
|
||||
"""
|
||||
Create a _SupportCheck from the passed args, then turn it into a
|
||||
SupportCache method which captures and caches the returned support
|
||||
value in self._cache
|
||||
"""
|
||||
# pylint: disable=protected-access
|
||||
support_obj = _SupportCheck(*args, **kwargs)
|
||||
|
||||
def cache_wrapper(self, data=None):
|
||||
if support_obj not in self._cache:
|
||||
support_ret = support_obj(self._virtconn, data or self._virtconn)
|
||||
self._cache[support_obj] = support_ret
|
||||
return self._cache[support_obj]
|
||||
|
||||
return cache_wrapper
|
||||
|
||||
|
||||
class SupportCache:
|
||||
"""
|
||||
Class containing all support checks and access APIs
|
||||
Class containing all support checks and access APIs, and support for
|
||||
caching returned results
|
||||
"""
|
||||
def __init__(self, virtconn):
|
||||
self._cache = {}
|
||||
self._virtconn = virtconn
|
||||
|
||||
SUPPORT_CONN_STORAGE = _make(
|
||||
conn_storage = _make(
|
||||
function="virConnect.listStoragePools", run_args=())
|
||||
SUPPORT_CONN_NODEDEV = _make(
|
||||
conn_nodedev = _make(
|
||||
function="virConnect.listDevices", run_args=(None, 0))
|
||||
SUPPORT_CONN_NETWORK = _make(function="virConnect.listNetworks", run_args=())
|
||||
SUPPORT_CONN_INTERFACE = _make(
|
||||
conn_network = _make(function="virConnect.listNetworks", run_args=())
|
||||
conn_interface = _make(
|
||||
function="virConnect.listInterfaces", run_args=())
|
||||
SUPPORT_CONN_STREAM = _make(function="virConnect.newStream", run_args=(0,))
|
||||
SUPPORT_CONN_LISTALLDOMAINS = _make(
|
||||
conn_stream = _make(function="virConnect.newStream", run_args=(0,))
|
||||
conn_listalldomains = _make(
|
||||
function="virConnect.listAllDomains", run_args=())
|
||||
SUPPORT_CONN_LISTALLNETWORKS = _make(
|
||||
conn_listallnetworks = _make(
|
||||
function="virConnect.listAllNetworks", run_args=())
|
||||
SUPPORT_CONN_LISTALLSTORAGEPOOLS = _make(
|
||||
conn_listallstoragepools = _make(
|
||||
function="virConnect.listAllStoragePools", run_args=())
|
||||
SUPPORT_CONN_LISTALLINTERFACES = _make(
|
||||
conn_listallinterfaces = _make(
|
||||
function="virConnect.listAllInterfaces", run_args=())
|
||||
SUPPORT_CONN_LISTALLDEVICES = _make(
|
||||
conn_listalldevices = _make(
|
||||
function="virConnect.listAllDevices", run_args=())
|
||||
SUPPORT_CONN_WORKING_XEN_EVENTS = _make(hv_version={"xen": "4.0.0", "all": 0})
|
||||
conn_working_xen_events = _make(hv_version={"xen": "4.0.0", "all": 0})
|
||||
# This is an arbitrary check to say whether it's a good idea to
|
||||
# default to qcow2. It might be fine for xen or qemu older than the versions
|
||||
# here, but until someone tests things I'm going to be a bit conservative.
|
||||
SUPPORT_CONN_DEFAULT_QCOW2 = _make(hv_version={"qemu": "1.2.0", "test": 0})
|
||||
SUPPORT_CONN_AUTOSOCKET = _make(hv_libvirt_version={"qemu": "1.0.6"})
|
||||
SUPPORT_CONN_PM_DISABLE = _make(hv_version={"qemu": "1.2.0", "test": 0})
|
||||
SUPPORT_CONN_QCOW2_LAZY_REFCOUNTS = _make(
|
||||
conn_default_qcow2 = _make(hv_version={"qemu": "1.2.0", "test": 0})
|
||||
conn_autosocket = _make(hv_libvirt_version={"qemu": "1.0.6"})
|
||||
conn_pm_disable = _make(hv_version={"qemu": "1.2.0", "test": 0})
|
||||
conn_qcow2_lazy_refcounts = _make(
|
||||
version="1.1.0", hv_version={"qemu": "1.2.0", "test": 0})
|
||||
SUPPORT_CONN_HYPERV_VAPIC = _make(
|
||||
conn_hyperv_vapic = _make(
|
||||
version="1.1.0", hv_version={"qemu": "1.1.0", "test": 0})
|
||||
SUPPORT_CONN_HYPERV_CLOCK = _make(
|
||||
conn_hyperv_clock = _make(
|
||||
version="1.2.2", hv_version={"qemu": "1.5.3", "test": 0})
|
||||
SUPPORT_CONN_DOMAIN_CAPABILITIES = _make(
|
||||
conn_domain_capabilities = _make(
|
||||
function="virConnect.getDomainCapabilities",
|
||||
run_args=(None, None, None, None))
|
||||
SUPPORT_CONN_DOMAIN_RESET = _make(version="0.9.7", hv_version={"qemu": 0})
|
||||
SUPPORT_CONN_VMPORT = _make(
|
||||
conn_domain_reset = _make(version="0.9.7", hv_version={"qemu": 0})
|
||||
conn_vmport = _make(
|
||||
version="1.2.16", hv_version={"qemu": "2.2.0", "test": 0})
|
||||
SUPPORT_CONN_MEM_STATS_PERIOD = _make(
|
||||
conn_mem_stats_period = _make(
|
||||
function="virDomain.setMemoryStatsPeriod",
|
||||
version="1.1.1", hv_version={"qemu": 0})
|
||||
# spice GL is actually enabled with libvirt 1.3.3, but 3.1.0 is the
|
||||
# first version that sorts out the qemu:///system + cgroup issues
|
||||
SUPPORT_CONN_SPICE_GL = _make(version="3.1.0",
|
||||
conn_spice_gl = _make(version="3.1.0",
|
||||
hv_version={"qemu": "2.6.0", "test": 0})
|
||||
SUPPORT_CONN_SPICE_RENDERNODE = _make(version="3.1.0",
|
||||
conn_spice_rendernode = _make(version="3.1.0",
|
||||
hv_version={"qemu": "2.9.0", "test": 0})
|
||||
SUPPORT_CONN_VIDEO_VIRTIO_ACCEL3D = _make(version="1.3.0",
|
||||
conn_video_virtio_accel3d = _make(version="1.3.0",
|
||||
hv_version={"qemu": "2.5.0", "test": 0})
|
||||
SUPPORT_CONN_GRAPHICS_LISTEN_NONE = _make(version="2.0.0")
|
||||
SUPPORT_CONN_RNG_URANDOM = _make(version="1.3.4")
|
||||
SUPPORT_CONN_USB3_PORTS = _make(version="1.3.5")
|
||||
SUPPORT_CONN_MACHVIRT_PCI_DEFAULT = _make(version="3.0.0")
|
||||
SUPPORT_CONN_QEMU_XHCI = _make(version="3.3.0", hv_version={"qemu": "2.9.0"})
|
||||
SUPPORT_CONN_VNC_NONE_AUTH = _make(hv_version={"qemu": "2.9.0"})
|
||||
SUPPORT_CONN_DEVICE_BOOT_ORDER = _make(hv_version={"qemu": 0, "test": 0})
|
||||
SUPPORT_CONN_RISCV_VIRT_PCI_DEFAULT = _make(version="5.3.0", hv_version={"qemu": "4.0.0"})
|
||||
conn_graphics_listen_none = _make(version="2.0.0")
|
||||
conn_rng_urandom = _make(version="1.3.4")
|
||||
conn_usb3_ports = _make(version="1.3.5")
|
||||
conn_machvirt_pci_default = _make(version="3.0.0")
|
||||
conn_qemu_xhci = _make(version="3.3.0", hv_version={"qemu": "2.9.0"})
|
||||
conn_vnc_none_auth = _make(hv_version={"qemu": "2.9.0"})
|
||||
conn_device_boot_order = _make(hv_version={"qemu": 0, "test": 0})
|
||||
conn_riscv_virt_pci_default = _make(version="5.3.0", hv_version={"qemu": "4.0.0"})
|
||||
|
||||
# We choose qemu 2.11.0 as the first version to target for q35 default.
|
||||
# That's not really based on anything except reasonably modern at the
|
||||
# time of these patches.
|
||||
SUPPORT_QEMU_Q35_DEFAULT = _make(hv_version={"qemu": "2.11.0", "test": "0"})
|
||||
qemu_q35_default = _make(hv_version={"qemu": "2.11.0", "test": "0"})
|
||||
|
||||
# This is for disk <driver name=qemu>. xen supports this, but it's
|
||||
# limited to arbitrary new enough xen, since I know libxl can handle it
|
||||
# but I don't think the old xend driver does.
|
||||
SUPPORT_CONN_DISK_DRIVER_NAME_QEMU = _make(
|
||||
conn_disk_driver_name_qemu = _make(
|
||||
hv_version={"qemu": 0, "xen": "4.2.0"},
|
||||
hv_libvirt_version={"qemu": 0, "xen": "1.1.0"})
|
||||
|
||||
# Domain checks
|
||||
SUPPORT_DOMAIN_XML_INACTIVE = _make(function="virDomain.XMLDesc", run_args=(),
|
||||
domain_xml_inactive = _make(function="virDomain.XMLDesc", run_args=(),
|
||||
flag="VIR_DOMAIN_XML_INACTIVE")
|
||||
SUPPORT_DOMAIN_XML_SECURE = _make(function="virDomain.XMLDesc", run_args=(),
|
||||
domain_xml_secure = _make(function="virDomain.XMLDesc", run_args=(),
|
||||
flag="VIR_DOMAIN_XML_SECURE")
|
||||
SUPPORT_DOMAIN_MANAGED_SAVE = _make(
|
||||
domain_managed_save = _make(
|
||||
function="virDomain.hasManagedSaveImage",
|
||||
run_args=(0,))
|
||||
SUPPORT_DOMAIN_JOB_INFO = _make(function="virDomain.jobInfo", run_args=())
|
||||
SUPPORT_DOMAIN_LIST_SNAPSHOTS = _make(
|
||||
domain_job_info = _make(function="virDomain.jobInfo", run_args=())
|
||||
domain_list_snapshots = _make(
|
||||
function="virDomain.listAllSnapshots", run_args=())
|
||||
SUPPORT_DOMAIN_MEMORY_STATS = _make(
|
||||
domain_memory_stats = _make(
|
||||
function="virDomain.memoryStats", run_args=())
|
||||
SUPPORT_DOMAIN_STATE = _make(function="virDomain.state", run_args=())
|
||||
SUPPORT_DOMAIN_OPEN_GRAPHICS = _make(function="virDomain.openGraphicsFD",
|
||||
domain_state = _make(function="virDomain.state", run_args=())
|
||||
domain_open_graphics = _make(function="virDomain.openGraphicsFD",
|
||||
version="1.2.8", hv_version={"qemu": 0})
|
||||
|
||||
# Pool checks
|
||||
SUPPORT_POOL_ISACTIVE = _make(function="virStoragePool.isActive", run_args=())
|
||||
SUPPORT_POOL_LISTALLVOLUMES = _make(
|
||||
pool_isactive = _make(function="virStoragePool.isActive", run_args=())
|
||||
pool_listallvolumes = _make(
|
||||
function="virStoragePool.listAllVolumes", run_args=())
|
||||
SUPPORT_POOL_METADATA_PREALLOC = _make(
|
||||
pool_metadata_prealloc = _make(
|
||||
flag="VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA",
|
||||
version="1.0.1")
|
||||
|
||||
# Network checks
|
||||
SUPPORT_NET_ISACTIVE = _make(function="virNetwork.isActive", run_args=())
|
||||
net_isactive = _make(function="virNetwork.isActive", run_args=())
|
||||
|
||||
|
||||
def check_support(self, virtconn, feature, data=None):
|
||||
"""
|
||||
Attempt to determine if a specific libvirt feature is support given
|
||||
the passed connection.
|
||||
|
||||
:param virtconn: Libvirt connection to check feature on
|
||||
:param feature: Feature type to check support for
|
||||
:type feature: One of the SUPPORT_* flags
|
||||
:param data: Option libvirt object to use in feature checking
|
||||
:type data: Could be virDomain, virNetwork, virStoragePool, hv name, etc
|
||||
|
||||
:returns: True if feature is supported, False otherwise
|
||||
"""
|
||||
if "VirtinstConnection" in repr(data):
|
||||
data = data.get_conn_for_api_arg()
|
||||
|
||||
sobj = _SUPPORT_OBJS[feature - 1]
|
||||
return sobj.check_support(virtconn, data)
|
||||
|
||||
|
||||
def check_version(self, virtconn, version):
|
||||
def _check_version(self, version):
|
||||
"""
|
||||
Check libvirt version. Useful for the test suite so we don't need
|
||||
to keep adding new support checks.
|
||||
"""
|
||||
sobj = _SupportCheck(version=version)
|
||||
return sobj.check_support(virtconn, None)
|
||||
return sobj(self._virtconn, None)
|
||||
|
||||
Reference in New Issue
Block a user