diff options
-rw-r--r-- | tests/clitest.py | 2 | ||||
-rw-r--r-- | virtManager/connection.py | 10 | ||||
-rw-r--r-- | virtinst/connection.py | 25 | ||||
-rw-r--r-- | virtinst/support.py | 167 |
4 files changed, 97 insertions, 107 deletions
diff --git a/tests/clitest.py b/tests/clitest.py index 01f76b8a..6b3c4dc0 100644 --- a/tests/clitest.py +++ b/tests/clitest.py @@ -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: diff --git a/virtManager/connection.py b/virtManager/connection.py index 091679ac..dbff756f 100644 --- a/virtManager/connection.py +++ b/virtManager/connection.py @@ -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) diff --git a/virtinst/connection.py b/virtinst/connection.py index 558b6142..57d74ffa 100644 --- a/virtinst/connection.py +++ b/virtinst/connection.py @@ -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 diff --git a/virtinst/support.py b/virtinst/support.py index 96f0dfac..48a75ac9 100644 --- a/virtinst/support.py +++ b/virtinst/support.py @@ -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): + """ + 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] -def _make(*args, **kwargs): - global _SUPPORT_ID - _SUPPORT_ID += 1 - obj = _SupportCheck(*args, **kwargs) - _SUPPORT_OBJS.append(obj) - return _SUPPORT_ID + 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=()) - - - 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) + net_isactive = _make(function="virNetwork.isActive", run_args=()) - 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) |