virtManager: connection: Switch to tick() paradigm for all objects

This is going to be much slower than what we currently do, but we
will be trying to fix that shortly.
This commit is contained in:
Cole Robinson 2013-07-07 08:05:23 -04:00
parent 2e47d2e5fa
commit b7ee86541d
8 changed files with 133 additions and 54 deletions

View File

@ -405,6 +405,8 @@ class vmmConnection(vmmGObject):
return self._backend.check_interface_support(*args)
def check_stream_support(self, *args):
return self._backend.check_stream_support(*args)
def check_net_support(self, *args):
return self._backend.check_net_support(*args)
def is_storage_capable(self):
if self._storage_capable is None:
@ -969,7 +971,7 @@ class vmmConnection(vmmGObject):
except Exception, e:
logging.debug("Unable to list inactive %ss: %s", typename, e)
def check_obj(key, is_active):
def check_obj(key):
if key not in origlist:
try:
obj = lookup_func(key)
@ -979,30 +981,18 @@ class vmmConnection(vmmGObject):
return
# Object is brand new this tick period
current[key] = build_func(obj, key, is_active)
current[key] = build_func(obj, key)
new[key] = current[key]
else:
# Previously known object, see if it changed state
current[key] = origlist[key]
if current[key].is_active() != is_active:
current[key].set_active(is_active)
del origlist[key]
for name in newActiveNames:
for name in newActiveNames + newInactiveNames:
try:
check_obj(name, True)
check_obj(name)
except:
logging.exception("Couldn't fetch active "
"%s '%s'", typename, name)
for name in newInactiveNames:
try:
check_obj(name, False)
except:
logging.exception("Couldn't fetch inactive "
"%s '%s'", typename, name)
logging.exception("Couldn't fetch %s '%s'", typename, name)
return (origlist, new, current)
@ -1013,8 +1003,7 @@ class vmmConnection(vmmGObject):
inactive_list = self._backend.listDefinedNetworks
check_support = self.is_network_capable
lookup_func = self._backend.networkLookupByName
build_func = (lambda obj, key, is_active:
vmmNetwork(self, obj, key, is_active))
build_func = (lambda obj, key: vmmNetwork(self, obj, key))
return self._poll_helper(orig, name, check_support,
active_list, inactive_list,
@ -1027,8 +1016,7 @@ class vmmConnection(vmmGObject):
inactive_list = self._backend.listDefinedStoragePools
check_support = self.is_storage_capable
lookup_func = self._backend.storagePoolLookupByName
build_func = (lambda obj, key, is_active:
vmmStoragePool(self, obj, key, is_active))
build_func = (lambda obj, key: vmmStoragePool(self, obj, key))
return self._poll_helper(orig, name, check_support,
active_list, inactive_list,
@ -1041,8 +1029,7 @@ class vmmConnection(vmmGObject):
inactive_list = self._backend.listDefinedInterfaces
check_support = self.is_interface_capable
lookup_func = self._backend.interfaceLookupByName
build_func = (lambda obj, key, is_active:
vmmInterface(self, obj, key, is_active))
build_func = (lambda obj, key: vmmInterface(self, obj, key))
return self._poll_helper(orig, name, check_support,
active_list, inactive_list,
@ -1056,7 +1043,7 @@ class vmmConnection(vmmGObject):
inactive_list = lambda: []
check_support = self.is_nodedev_capable
lookup_func = self._backend.nodeDeviceLookupByName
build_func = lambda obj, key, ignore: vmmNodeDevice(self, obj, key)
build_func = lambda obj, key: vmmNodeDevice(self, obj, key)
return self._poll_helper(orig, name, check_support,
active_list, inactive_list,
@ -1236,18 +1223,24 @@ class vmmConnection(vmmGObject):
self.idle_add(tick_send_signals)
# Finally, we sample each domain
now = time.time()
updateVMs = vms.values()
if noStatsUpdate:
updateVMs = newVMs.values()
ticklist = []
def add_to_ticklist(l, args=()):
ticklist.extend([(o, args) for o in l.values()])
for vm in updateVMs:
updateVMs = noStatsUpdate and newVMs or vms
add_to_ticklist(updateVMs, (now,))
add_to_ticklist(noStatsUpdate and newNets or nets)
add_to_ticklist(noStatsUpdate and newPools or pools)
add_to_ticklist(noStatsUpdate and newInterfaces or interfaces)
add_to_ticklist(self.mediadevs)
for obj, args in ticklist:
try:
vm.tick(now)
obj.tick(*args)
except Exception, e:
logging.exception("Tick for VM '%s' failed", vm.get_name())
logging.exception("Tick for %s failed", obj)
if (isinstance(e, libvirt.libvirtError) and
(getattr(e, "get_error_code")() ==
libvirt.VIR_ERR_SYSTEM_ERROR)):
@ -1257,11 +1250,8 @@ class vmmConnection(vmmGObject):
"connection doesn't seem to have dropped. "
"Ignoring.")
for dev in self.mediadevs.values():
dev.tick()
if not noStatsUpdate:
self._recalculate_stats(now, updateVMs)
self._recalculate_stats(now, updateVMs.values())
self.idle_emit("resources-sampled")
return 1

View File

@ -1714,9 +1714,6 @@ class vmmDomain(vmmLibvirtObject):
return rd, wr
def tick(self, now=None):
if self.conn.get_state() != self.conn.STATE_ACTIVE:
return
if now is None:
now = time.time()

View File

@ -25,12 +25,12 @@ from virtManager.libvirtobject import vmmLibvirtObject
class vmmInterface(vmmLibvirtObject):
def __init__(self, conn, interface, name, active):
def __init__(self, conn, interface, name):
vmmLibvirtObject.__init__(self, conn)
self.interface = interface # Libvirt virInterface object
self.name = name # String name
self.active = active # bool indicating if it is running
self.active = True # bool indicating if it is running
self._xml = None # xml cache
self._xml_flags = None
@ -39,6 +39,9 @@ class vmmInterface(vmmLibvirtObject):
self._active_xml_flags) = self.conn.get_interface_flags(
self.interface)
self._support_isactive = None
self.tick()
self.refresh_xml()
# Routines from vmmLibvirtObject
@ -60,11 +63,27 @@ class vmmInterface(vmmLibvirtObject):
return util.xpath(self.get_xml(inactive=True), *args, **kwargs)
def set_active(self, state):
if state != self.active:
self.idle_emit(state and "started" or "stopped")
if state == self.active:
return
self.idle_emit(state and "started" or "stopped")
self.active = state
self.refresh_xml()
def _backend_get_active(self):
ret = True
if self._support_isactive is None:
self._support_isactive = self.conn.check_interface_support(
self.interface,
self.conn.SUPPORT_INTERFACE_ISACTIVE)
if not self._support_isactive:
return True
return bool(self.interface.isActive())
def tick(self):
self.set_active(self._backend_get_active())
def is_active(self):
return self.active

View File

@ -82,6 +82,7 @@ class vmmLibvirtObject(vmmGObject):
def tick(self, now):
ignore = now
##################
# Public XML API #
##################
@ -120,6 +121,7 @@ class vmmLibvirtObject(vmmGObject):
if origxml != self._xml or forcesignal:
self.idle_emit("config-changed")
######################################
# Internal XML cache/update routines #
######################################
@ -128,6 +130,7 @@ class vmmLibvirtObject(vmmGObject):
# Mark cached xml as invalid
self._is_xml_valid = False
##########################
# Internal API functions #
##########################

View File

@ -47,11 +47,16 @@ class vmmNetwork(vmmLibvirtObject):
return desc
def __init__(self, conn, net, uuid, active):
def __init__(self, conn, net, uuid):
vmmLibvirtObject.__init__(self, conn)
self.net = net
self.uuid = uuid
self.active = active
self.active = True
self._support_isactive = None
self.tick()
# Required class methods
def get_name(self):
@ -62,8 +67,9 @@ class vmmNetwork(vmmLibvirtObject):
return self.conn.get_backend().networkDefineXML(xml)
def set_active(self, state):
if state != self.active:
self.idle_emit(state and "started" or "stopped")
if state == self.active:
return
self.idle_emit(state and "started" or "stopped")
self.active = state
def is_active(self):
@ -89,7 +95,6 @@ class vmmNetwork(vmmLibvirtObject):
def delete(self):
self.net.undefine()
del(self.net)
self.net = None
def set_autostart(self, value):
@ -98,6 +103,24 @@ class vmmNetwork(vmmLibvirtObject):
def get_autostart(self):
return self.net.autostart()
def _backend_get_active(self):
if self._support_isactive is None:
self._support_isactive = self.conn.check_net_support(
self.net,
self.conn.SUPPORT_NET_ISACTIVE)
if not self._support_isactive:
return True
return bool(self.net.isActive())
def tick(self):
self.set_active(self._backend_get_active())
########################
# XML parsing routines #
########################
def get_ipv4_static_route(self):
doc = None
ret = None

View File

@ -34,16 +34,19 @@ class vmmStoragePool(vmmLibvirtObject):
"refreshed": (GObject.SignalFlags.RUN_FIRST, None, [])
}
def __init__(self, conn, pool, uuid, active):
def __init__(self, conn, pool, uuid):
vmmLibvirtObject.__init__(self, conn)
self.pool = pool # Libvirt pool object
self.uuid = uuid # String UUID
self.active = active # bool indicating if it is running
self.active = True # bool indicating if it is running
self._volumes = {} # UUID->vmmStorageVolume mapping of the
# pools associated volumes
self._support_isactive = None
self.tick()
self.refresh()
# Required class methods
@ -56,8 +59,9 @@ class vmmStoragePool(vmmLibvirtObject):
def set_active(self, state):
if state != self.active:
self.idle_emit(state and "started" or "stopped")
if state == self.active:
return
self.idle_emit(state and "started" or "stopped")
self.active = state
self.refresh_xml()
@ -119,6 +123,19 @@ class vmmStoragePool(vmmLibvirtObject):
def get_volume(self, uuid):
return self._volumes[uuid]
def _backend_get_active(self):
if self._support_isactive is None:
self._support_isactive = self.conn.check_pool_support(
self.pool,
self.conn.SUPPORT_STORAGE_ISACTIVE)
if not self._support_isactive:
return True
return bool(self.pool.isActive())
def tick(self):
self.set_active(self._backend_get_active())
def refresh(self):
if not self.active:
return

View File

@ -233,6 +233,8 @@ class VirtualConnection(object):
def check_stream_support(self, feature):
return (self.check_conn_support(self.SUPPORT_CONN_STREAM) and
support.check_support(self, feature, self))
def check_net_support(self, net, feature):
return support.check_support(self, feature, net)
###################

View File

@ -35,7 +35,7 @@ from virtinst import util
SUPPORT_CONN_MAXVCPUS_XML,
SUPPORT_CONN_STREAM,
SUPPORT_CONN_GETVERSION,
SUPPORT_CONN_LIBVERSION) = range(12)
SUPPORT_CONN_LIBVERSION) = range(1, 13)
# Flags for check_domain_support
(SUPPORT_DOMAIN_GETVCPUS,
@ -51,13 +51,15 @@ from virtinst import util
# Flags for check_pool_support
(SUPPORT_STORAGE_CREATEVOLFROM,
SUPPORT_STORAGE_UPLOAD) = range(2000, 2002)
SUPPORT_STORAGE_UPLOAD,
SUPPORT_STORAGE_ISACTIVE) = range(2000, 2003)
# Flags for check_nodedev_support
(SUPPORT_NODEDEV_PCI_DETACH,) = range(3000, 3001)
# Flags for check_interface_support
(SUPPORT_INTERFACE_XML_INACTIVE,) = range(4000, 4001)
(SUPPORT_INTERFACE_XML_INACTIVE,
SUPPORT_INTERFACE_ISACTIVE) = range(4000, 4002)
# Flags for check_conn_hv_support
(SUPPORT_CONN_HV_VIRTIO,
@ -72,6 +74,9 @@ from virtinst import util
# Flags for check_stream_support
(SUPPORT_STREAM_UPLOAD,) = range(6000, 6001)
# Flags for check_net_support
(SUPPORT_NET_ISACTIVE,) = range(7000, 7001)
# Possible keys:
#
@ -230,6 +235,11 @@ _support_dict = {
"function" : "virStoragePool.createXMLFrom",
"version" : 6004,
},
SUPPORT_STORAGE_ISACTIVE : {
"function" : "virStoragePool.isActive",
"args": (),
},
##################
# Nodedev checks #
@ -251,6 +261,10 @@ _support_dict = {
"args" : (),
"flag" : "VIR_INTERFACE_XML_INACTIVE",
},
SUPPORT_INTERFACE_ISACTIVE : {
"function" : "virInterface.isActive",
"args": (),
},
##################
@ -304,11 +318,25 @@ _support_dict = {
},
#################
# Stream checks #
#################
SUPPORT_STREAM_UPLOAD : {
# Latest I tested with, and since we will use it by default
# for URL installs, want to be sure it works
"version" : 9004,
},
##################
# Network checks #
##################
SUPPORT_NET_ISACTIVE : {
"function" : "virNetwork.isActive",
"args": (),
},
}
# RHEL6 has lots of feature backports, and since libvirt doesn't