From 7a5dc7c544f00659892c8b64f46d2e35dce3dc6e Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sat, 28 Sep 2013 20:05:13 -0400 Subject: [PATCH] devicedisk: path_in_use_by: Check backing stores as well Plumb through a fetch_all_vols helper for this, and do all the caching bits. --- virtManager/connection.py | 13 ++++-- virtManager/domain.py | 3 -- virtManager/storagepool.py | 5 ++- virtinst/connection.py | 81 +++++++++++++++++++++++--------------- virtinst/devicedisk.py | 27 +++++++------ virtinst/storage.py | 10 ++--- 6 files changed, 81 insertions(+), 58 deletions(-) diff --git a/virtManager/connection.py b/virtManager/connection.py index 4af8a6b98..cfe0d3f3d 100644 --- a/virtManager/connection.py +++ b/virtManager/connection.py @@ -136,9 +136,16 @@ class vmmConnection(vmmGObject): def _init_virtconn(self): self._backend.cb_fetch_all_guests = ( - lambda: [vm.get_guest_for_virtinst_func(refresh_if_nec=False) - for vm in self.vms.values()]) - self._backend.cb_fetch_all_pools = lambda: self.pools.values() + lambda: [obj.get_xmlobj(refresh_if_nec=False) + for obj in self.vms.values()]) + self._backend.cb_fetch_all_pools = ( + lambda: [obj.get_xmlobj(refresh_if_nec=False) + for obj in self.pools.values()]) + self._backend.cb_fetch_all_vols = ( + lambda: [obj.get_xmlobj(refresh_if_nec=False) + for pool in self.pools.values() + for obj in pool.get_volumes(refresh=False).values()]) + def _init_netdev(self): """ diff --git a/virtManager/domain.py b/virtManager/domain.py index b3b9875bf..8e1512cb8 100644 --- a/virtManager/domain.py +++ b/virtManager/domain.py @@ -405,9 +405,6 @@ class vmmDomain(vmmLibvirtObject): raise RuntimeError(_("Could not find specified device in the " "inactive VM configuration: %s") % repr(origdev)) - def get_guest_for_virtinst_func(self, *args, **kwargs): - return self.get_xmlobj(*args, **kwargs) - ############################## # Persistent XML change APIs # diff --git a/virtManager/storagepool.py b/virtManager/storagepool.py index fc6de7a7e..def7f6886 100644 --- a/virtManager/storagepool.py +++ b/virtManager/storagepool.py @@ -178,8 +178,9 @@ class vmmStoragePool(vmmLibvirtObject): # Volume handling # ################### - def get_volumes(self): - self.update_volumes() + def get_volumes(self, refresh=True): + if refresh: + self.update_volumes() return self._volumes def get_volume(self, uuid): diff --git a/virtinst/connection.py b/virtinst/connection.py index 5abf97502..4200dedad 100644 --- a/virtinst/connection.py +++ b/virtinst/connection.py @@ -23,8 +23,10 @@ import weakref import libvirt -from virtinst import Guest from virtinst import CapabilitiesParser +from virtinst import Guest +from virtinst import StoragePool +from virtinst import StorageVolume from virtinst import pollhelpers from virtinst import support from virtinst import util @@ -58,25 +60,6 @@ def _sanitize_xml(xml): return xml -class _FetchObjWrapper(object): - """ - Wrapper to make virDomain etc. objects have a similar XML API as - virt-manager objects, so fetch_all* callers get similar results - """ - def __init__(self, backend): - self._backend = backend - self._xml = None - self._xmlobj = None - - def get_xml(self, refresh_if_nec=True): - if self._xml is None or refresh_if_nec: - self._xml = self._backend.XMLDesc(0) - return self._xml - - def get_backend(self): - return self._backend - - class VirtualConnection(object): """ Wrapper for libvirt connection that provides various bits like @@ -122,6 +105,7 @@ class VirtualConnection(object): # own cached object lists, rather than doing fresh calls self.cb_fetch_all_guests = None self.cb_fetch_all_pools = None + self.cb_fetch_all_vols = None ############## @@ -182,12 +166,7 @@ class VirtualConnection(object): self._uri = self._libvirtconn.getURI() self._urisplits = util.uri_split(self._uri) - def fetch_all_guests(self): - # pylint: disable=E1102 - if self.cb_fetch_all_guests: - return self.cb_fetch_all_guests() - # pylint: enable=E1102 - + def _fetch_all_guests_cached(self): key = "vms" if key in self._fetch_cache: return self._fetch_cache[key] @@ -200,23 +179,61 @@ class VirtualConnection(object): self._fetch_cache[key] = ret return ret - def fetch_all_pools(self): - # pylint: disable=E1102 - if self.cb_fetch_all_pools: - return self.cb_fetch_all_pools() - # pylint: enable=E1102 + def fetch_all_guests(self): + """ + Returns a list of Guest() objects + """ + if self.cb_fetch_all_guests: + return self.cb_fetch_all_guests() # pylint: disable=E1102 + return self._fetch_all_guests_cached() + def _fetch_all_pools_cached(self): key = "pools" if key in self._fetch_cache: return self._fetch_cache[key] ignore, ignore, ret = pollhelpers.fetch_pools(self, {}, lambda obj, ignore: obj) - ret = [_FetchObjWrapper(obj) for obj in ret.values()] + ret = [StoragePool(weakref.ref(self), parsexml=obj.XMLDesc(0)) + for obj in ret.values()] if self.cache_object_fetch: self._fetch_cache[key] = ret return ret + def fetch_all_pools(self): + """ + Returns a list of StoragePool objects + """ + if self.cb_fetch_all_pools: + return self.cb_fetch_all_pools() # pylint: disable=E1102 + return self._fetch_all_pools_cached() + + def _fetch_all_vols_cached(self): + key = "vols" + if key in self._fetch_cache: + return self._fetch_cache[key] + + ret = [] + for xmlobj in self.fetch_all_pools(): + pool = self._libvirtconn.storagePoolLookupByName(xmlobj.name) + # XXX: Should implement pollhelpers support for listAllVolumes + for volname in pool.listVolumes(): + vol = pool.storageVolLookupByName(volname) + ret.append(StorageVolume(weakref.ref(self), + parsexml=vol.XMLDesc(0))) + + if self.cache_object_fetch: + self._fetch_cache[key] = ret + return ret + + def fetch_all_vols(self): + """ + Returns a list of StorageVolume objects + """ + if self.cb_fetch_all_vols: + return self.cb_fetch_all_vols() # pylint: disable=E1102 + return self._fetch_all_vols_cached() + def clear_cache(self): self._fetch_cache = {} diff --git a/virtinst/devicedisk.py b/virtinst/devicedisk.py index 2e362626f..39f3ad7d9 100644 --- a/virtinst/devicedisk.py +++ b/virtinst/devicedisk.py @@ -337,23 +337,26 @@ class VirtualDisk(VirtualDevice): """ if not path: return + ret = [] + + vols = [] + for vol in conn.fetch_all_vols(): + if path == vol.backing_store: + vols.append(vol.target_path) vms = conn.fetch_all_guests() - names = [] for vm in vms: - found = False for disk in vm.get_devices("disk"): - if disk.path != path: - continue - if check_conflict: - if disk.shareable: - continue - found = True - break - if found: - names.append(vm.name) + if disk.path == path: + if check_conflict: + if disk.shareable: + continue + if vm.name not in ret: + ret.append(vm.name) - return names + if disk.path in vols and vm.name not in ret: + ret.append(vm.name) + return ret @staticmethod def stat_local_path(path): diff --git a/virtinst/storage.py b/virtinst/storage.py index 176fd9cfd..ff29e19f9 100644 --- a/virtinst/storage.py +++ b/virtinst/storage.py @@ -217,15 +217,13 @@ class StoragePool(_StorageObject): return None def check_pool(pool, path): - xml = pool.get_xml(refresh_if_nec=False) - xml_path = StoragePool(conn, parsexml=xml).target_path + xml_path = pool.target_path if xml_path is not None and os.path.abspath(xml_path) == path: - return pool + return True for pool in conn.fetch_all_pools(): - p = check_pool(pool, path) - if p: - return p.get_backend() + if check_pool(pool, path): + return conn.storagePoolLookupByName(pool.name) return None