diff --git a/virtManager/connection.py b/virtManager/connection.py index 627c1fc8..022d84f7 100644 --- a/virtManager/connection.py +++ b/virtManager/connection.py @@ -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 diff --git a/virtManager/domain.py b/virtManager/domain.py index ea39e831..6d884eca 100644 --- a/virtManager/domain.py +++ b/virtManager/domain.py @@ -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() diff --git a/virtManager/interface.py b/virtManager/interface.py index c001617b..96398509 100644 --- a/virtManager/interface.py +++ b/virtManager/interface.py @@ -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 diff --git a/virtManager/libvirtobject.py b/virtManager/libvirtobject.py index bf5ac423..ec761ffa 100644 --- a/virtManager/libvirtobject.py +++ b/virtManager/libvirtobject.py @@ -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 # ########################## diff --git a/virtManager/network.py b/virtManager/network.py index ff9eb37d..c9d5b4d7 100644 --- a/virtManager/network.py +++ b/virtManager/network.py @@ -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 diff --git a/virtManager/storagepool.py b/virtManager/storagepool.py index de9acb7a..365d3fc5 100644 --- a/virtManager/storagepool.py +++ b/virtManager/storagepool.py @@ -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 diff --git a/virtinst/connection.py b/virtinst/connection.py index 3a0a62f3..9f851589 100644 --- a/virtinst/connection.py +++ b/virtinst/connection.py @@ -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) ################### diff --git a/virtinst/support.py b/virtinst/support.py index 3985b1f5..6b6f4eff 100644 --- a/virtinst/support.py +++ b/virtinst/support.py @@ -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