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

View File

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

View File

@ -25,12 +25,12 @@ from virtManager.libvirtobject import vmmLibvirtObject
class vmmInterface(vmmLibvirtObject): class vmmInterface(vmmLibvirtObject):
def __init__(self, conn, interface, name, active): def __init__(self, conn, interface, name):
vmmLibvirtObject.__init__(self, conn) vmmLibvirtObject.__init__(self, conn)
self.interface = interface # Libvirt virInterface object self.interface = interface # Libvirt virInterface object
self.name = name # String name 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 = None # xml cache
self._xml_flags = None self._xml_flags = None
@ -39,6 +39,9 @@ class vmmInterface(vmmLibvirtObject):
self._active_xml_flags) = self.conn.get_interface_flags( self._active_xml_flags) = self.conn.get_interface_flags(
self.interface) self.interface)
self._support_isactive = None
self.tick()
self.refresh_xml() self.refresh_xml()
# Routines from vmmLibvirtObject # Routines from vmmLibvirtObject
@ -60,11 +63,27 @@ class vmmInterface(vmmLibvirtObject):
return util.xpath(self.get_xml(inactive=True), *args, **kwargs) return util.xpath(self.get_xml(inactive=True), *args, **kwargs)
def set_active(self, state): def set_active(self, state):
if state != self.active: if state == self.active:
self.idle_emit(state and "started" or "stopped") return
self.idle_emit(state and "started" or "stopped")
self.active = state self.active = state
self.refresh_xml() 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): def is_active(self):
return self.active return self.active

View File

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

View File

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

View File

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

View File

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