mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-01-24 07:16:40 -06:00
VirtualConnection: Allow using virt-manager object caches
So when we call into virtinst it doesn't do a whole round of object lookup and XML fetching.
This commit is contained in:
parent
9f3e17d270
commit
7a2caee6e1
@ -42,6 +42,7 @@ load-plugins=
|
||||
# I0011: Warn about locally disabled pylint msgs
|
||||
# R0201: Method could be a function
|
||||
#
|
||||
# W0108: Lambda may not be necessary
|
||||
# W0142: Used * or ** magic*
|
||||
# W0603: Using the global statement
|
||||
# W0702: No exception type specified for 'catch'
|
||||
@ -53,7 +54,7 @@ load-plugins=
|
||||
# W1001: Use of 'property' on old style class,
|
||||
# pylint can't detect our Gtk subclasses are new style
|
||||
# W0511: FIXME and XXX: messages
|
||||
disable=Design,Similarities,C0103,C0111,C0301,C0302,I0011,R0201,W0142,W0603,W0702,W0703,W1401,W1001,W0511
|
||||
disable=Design,Similarities,C0103,C0111,C0301,C0302,I0011,R0201,W0108,W0142,W0603,W0702,W0703,W1401,W1001,W0511
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
@ -127,11 +127,17 @@ class vmmConnection(vmmGObject):
|
||||
self.mediadev_error = ""
|
||||
self.mediadev_use_libvirt = False
|
||||
|
||||
self._init_virtconn()
|
||||
|
||||
|
||||
#################
|
||||
# Init routines #
|
||||
#################
|
||||
|
||||
def _init_virtconn(self):
|
||||
self._backend.cb_fetch_all_guests = lambda: self.vms.values()
|
||||
self._backend.cb_fetch_all_pools = lambda: self.pools.values()
|
||||
|
||||
def _init_netdev(self):
|
||||
"""
|
||||
Determine how we will be polling for net devices (HAL or libvirt)
|
||||
|
@ -469,8 +469,6 @@ class VirtualDisk(VirtualDevice):
|
||||
vms = conn.fetch_all_guests()
|
||||
|
||||
def count_cb(ctx):
|
||||
c = 0
|
||||
|
||||
template = "count(/domain/devices/disk["
|
||||
if check_conflict:
|
||||
template += "not(shareable) and "
|
||||
@ -478,16 +476,15 @@ class VirtualDisk(VirtualDevice):
|
||||
|
||||
for dtype in VirtualDisk._target_props:
|
||||
xpath = template % (dtype, util.xml_escape(path))
|
||||
c += ctx.xpathEval(xpath)
|
||||
|
||||
return c
|
||||
if ctx.xpathEval(xpath):
|
||||
return True
|
||||
return False
|
||||
|
||||
names = []
|
||||
for vm in vms:
|
||||
xml = vm.XMLDesc(0)
|
||||
tmpcount = util.get_xml_path(xml, func=count_cb)
|
||||
if tmpcount:
|
||||
names.append(vm.name())
|
||||
xml = vm.get_xml(refresh_if_nec=False)
|
||||
if util.get_xml_path(xml, func=count_cb):
|
||||
names.append(vm.get_backend().name())
|
||||
|
||||
return names
|
||||
|
||||
|
@ -46,26 +46,6 @@ def _compareMAC(p, q):
|
||||
return 0
|
||||
|
||||
|
||||
def _countMACaddr(vms, searchmac):
|
||||
if not searchmac:
|
||||
return
|
||||
|
||||
def count_cb(ctx):
|
||||
c = 0
|
||||
|
||||
for mac in ctx.xpathEval("/domain/devices/interface/mac"):
|
||||
macaddr = mac.xpathEval("attribute::address")[0].content
|
||||
if macaddr and _compareMAC(searchmac, macaddr) == 0:
|
||||
c += 1
|
||||
return c
|
||||
|
||||
count = 0
|
||||
for vm in vms:
|
||||
xml = vm.XMLDesc(0)
|
||||
count += util.get_xml_path(xml, func=count_cb)
|
||||
return count
|
||||
|
||||
|
||||
class VirtualPort(XMLBuilderDomain.XMLBuilderDomain):
|
||||
|
||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||
@ -332,16 +312,22 @@ class VirtualNetworkInterface(VirtualDevice):
|
||||
Non fatal collisions (mac addr collides with inactive guest) will
|
||||
return (False, "description of collision")
|
||||
"""
|
||||
mac = mac or self.macaddr
|
||||
if mac is None:
|
||||
searchmac = mac or self.macaddr
|
||||
if searchmac is None:
|
||||
return (False, None)
|
||||
|
||||
vms = self.conn.fetch_all_guests()
|
||||
|
||||
if _countMACaddr(vms, mac) > 0:
|
||||
return (True, _("The MAC address '%s' is in use "
|
||||
"by another virtual machine.") % mac)
|
||||
def count_cb(ctx):
|
||||
for mac in ctx.xpathEval("/domain/devices/interface/mac"):
|
||||
macaddr = mac.xpathEval("attribute::address")[0].content
|
||||
if macaddr and _compareMAC(searchmac, macaddr) == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
for vm in self.conn.fetch_all_guests():
|
||||
xml = vm.get_xml(refresh_if_nec=False)
|
||||
if util.get_xml_path(xml, func=count_cb):
|
||||
return (True, _("The MAC address '%s' is in use "
|
||||
"by another virtual machine.") % searchmac)
|
||||
return (False, None)
|
||||
|
||||
def setup(self, meter=None):
|
||||
|
@ -31,6 +31,24 @@ from virtinst.cli import parse_optstr
|
||||
_virtinst_uri_magic = "__virtinst_test__"
|
||||
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
@ -70,6 +88,11 @@ class VirtualConnection(object):
|
||||
# isn't hammering the connection over and over
|
||||
self.cache_object_fetch = False
|
||||
|
||||
# These let virt-manager register a callback which provides its
|
||||
# own cached object lists, rather than doing fresh calls
|
||||
self.cb_fetch_all_guests = None
|
||||
self.cb_fetch_all_pools = None
|
||||
|
||||
|
||||
##############
|
||||
# Properties #
|
||||
@ -127,25 +150,35 @@ class VirtualConnection(object):
|
||||
self._libvirtconn = conn
|
||||
|
||||
def fetch_all_guests(self):
|
||||
# pylint: disable=E1102
|
||||
if self.cb_fetch_all_guests:
|
||||
return self.cb_fetch_all_guests()
|
||||
# pylint: enable=E1102
|
||||
|
||||
key = "vms"
|
||||
if key in self._fetch_cache:
|
||||
return self._fetch_cache[key]
|
||||
|
||||
ignore, ignore, ret = pollhelpers.fetch_vms(self, {},
|
||||
lambda obj, ignore: obj)
|
||||
ret = ret.values()
|
||||
ret = [_FetchObjWrapper(obj) for obj in ret.values()]
|
||||
if self.cache_object_fetch:
|
||||
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
|
||||
|
||||
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 = ret.values()
|
||||
ret = [_FetchObjWrapper(obj) for obj in ret.values()]
|
||||
if self.cache_object_fetch:
|
||||
self._fetch_cache[key] = ret
|
||||
return ret
|
||||
|
@ -465,14 +465,15 @@ def lookup_pool_by_path(conn, path):
|
||||
return None
|
||||
|
||||
def check_pool(pool, path):
|
||||
xml_path = get_xml_path(pool.XMLDesc(0), "/pool/target/path")
|
||||
xml_path = get_xml_path(pool.get_xml(refresh_if_nec=False),
|
||||
"/pool/target/path")
|
||||
if xml_path is not None and os.path.abspath(xml_path) == path:
|
||||
return pool
|
||||
|
||||
for pool in conn.fetch_all_pools():
|
||||
p = check_pool(pool, path)
|
||||
if p:
|
||||
return p
|
||||
return p.get_backend()
|
||||
return None
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user