mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-12-22 13:34:07 +03:00
Move connection state management into vmmConnection class
so there is always a vmmConnection object even for disconnected connections. The vmmManager class listens for signals in vmmEngine and vmmConnection to see when new connections are added, existing ones removed, and the connection state changes
This commit is contained in:
parent
db9086e189
commit
dc391b698a
2
AUTHORS
2
AUTHORS
@ -30,4 +30,6 @@ Further patches have been submitted by:
|
||||
|
||||
<...send a patch & get your name here...>
|
||||
|
||||
Also lots of translations from the Fedora translation team. See
|
||||
the individual .po files for the translators.
|
||||
|
||||
|
@ -130,23 +130,19 @@ def show_engine(engine, show, uri, uuid):
|
||||
engine.show_console(uri, uuid)
|
||||
elif show=='summary' or uri:
|
||||
engine.connect_to_uri(uri)
|
||||
elif engine.config.get_connections() != None and len(engine.config.get_connections()) > 0:
|
||||
engine.load_stored_uris()
|
||||
else:
|
||||
tryuri = None
|
||||
if os.path.exists("/var/lib/xend") and os.path.exists("/proc/xen"):
|
||||
tryuri = "xen"
|
||||
elif os.path.exists("/usr/bin/qemu"):
|
||||
if os.getuid() == 0:
|
||||
tryuri = "qemu:///system"
|
||||
else:
|
||||
tryuri = "qemu:///session"
|
||||
if tryuri is not None:
|
||||
conn = engine.connect_to_uri(tryuri)
|
||||
if conn is None:
|
||||
tryuri = None
|
||||
if tryuri is None:
|
||||
engine.show_connect()
|
||||
if engine.config.get_connections() is None or len(engine.config.get_connections()) == 0:
|
||||
tryuri = None
|
||||
if os.path.exists("/var/lib/xend") and os.path.exists("/proc/xen"):
|
||||
tryuri = "xen"
|
||||
elif os.path.exists("/usr/bin/qemu"):
|
||||
if os.getuid() == 0:
|
||||
tryuri = "qemu:///system"
|
||||
else:
|
||||
tryuri = "qemu:///session"
|
||||
if tryuri is not None:
|
||||
conn = engine.add_connection(tryuri)
|
||||
engine.show_manager()
|
||||
|
||||
# maps --show-* to remote manager (ie dbus call) methods
|
||||
def show_remote(managerObj, show, uri, uuid):
|
||||
|
@ -31,7 +31,6 @@ from virtManager.domain import vmmDomain
|
||||
from virtManager.network import vmmNetwork
|
||||
from virtManager.netdev import vmmNetDevice
|
||||
|
||||
# static methods for getting various bits out of the URI
|
||||
def get_local_hostname():
|
||||
try:
|
||||
(host, aliases, ipaddrs) = gethostbyaddr(gethostname())
|
||||
@ -39,58 +38,6 @@ def get_local_hostname():
|
||||
except:
|
||||
logging.warning("Unable to resolve local hostname for machine")
|
||||
return "localhost"
|
||||
|
||||
def get_short_hostname(uri):
|
||||
hostname = get_hostname(uri)
|
||||
offset = hostname.find(".")
|
||||
if offset > 0 and not hostname[0].isdigit():
|
||||
return hostname[0:offset]
|
||||
return hostname
|
||||
|
||||
def get_hostname(uri, resolveLocal=False):
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(uri)
|
||||
|
||||
if netloc != "":
|
||||
return netloc
|
||||
except Exception, e:
|
||||
logging.warning("Cannot parse URI %s: %s" % (uri, str(e)))
|
||||
|
||||
if resolveLocal:
|
||||
return get_local_hostname()
|
||||
return "localhost"
|
||||
|
||||
def is_remote(uri):
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(uri)
|
||||
if netloc == "":
|
||||
return False
|
||||
return True
|
||||
except:
|
||||
return True
|
||||
|
||||
def get_transport(uri):
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(uri)
|
||||
if scheme:
|
||||
offset = scheme.find("+")
|
||||
if offset > 0:
|
||||
return [scheme[offset:], username]
|
||||
except:
|
||||
pass
|
||||
return [None, None]
|
||||
|
||||
def get_driver(uri):
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(uri)
|
||||
if scheme:
|
||||
offset = scheme.find("+")
|
||||
if offset > 0:
|
||||
return scheme[:offset]
|
||||
return scheme
|
||||
except Exception, e:
|
||||
pass
|
||||
return None
|
||||
|
||||
# Standard python urlparse is utterly braindead - refusing to parse URIs
|
||||
# in any useful fashion unless the 'scheme' is in some pre-defined white
|
||||
@ -147,38 +94,38 @@ class vmmConnection(gobject.GObject):
|
||||
[str]),
|
||||
"resources-sampled": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
[]),
|
||||
"disconnected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [str])
|
||||
"state-changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
[]),
|
||||
}
|
||||
|
||||
def __init__(self, config, uri, readOnly, active=True):
|
||||
STATE_DISCONNECTED = 0
|
||||
STATE_CONNECTING = 1
|
||||
STATE_ACTIVE = 2
|
||||
STATE_INACTIVE = 3
|
||||
|
||||
def __init__(self, config, uri, readOnly = None):
|
||||
self.__gobject_init__()
|
||||
self.config = config
|
||||
self.uri = uri
|
||||
self.readOnly = readOnly
|
||||
self._active = active
|
||||
|
||||
openURI = uri
|
||||
if openURI == "Xen":
|
||||
openURI = None
|
||||
self.uri = uri
|
||||
if self.uri is None or self.uri.lower() == "xen":
|
||||
self.uri = "xen:///"
|
||||
|
||||
if readOnly is None:
|
||||
try:
|
||||
self.vmm = libvirt.open(openURI)
|
||||
self.readOnly = False
|
||||
except:
|
||||
self.vmm = libvirt.openReadOnly(openURI)
|
||||
self.readOnly = True
|
||||
else:
|
||||
if readOnly:
|
||||
self.vmm = libvirt.openReadOnly(openURI)
|
||||
else:
|
||||
self.vmm = libvirt.open(openURI)
|
||||
self.state = self.STATE_DISCONNECTED
|
||||
self.vmm = None
|
||||
|
||||
# Host network devices. name -> vmmNetDevice object
|
||||
self.netdevs = {}
|
||||
# Virtual networks UUUID -> vmmNetwork object
|
||||
self.nets = {}
|
||||
# Virtual machines. UUID -> vmmDomain object
|
||||
self.vms = {}
|
||||
# Running virtual machines. UUID -> vmmDomain object
|
||||
self.activeUUIDs = []
|
||||
# Resource utilization statistics
|
||||
self.record = []
|
||||
self.hostinfo = None
|
||||
|
||||
self.detect_network_devices()
|
||||
|
||||
@ -219,12 +166,10 @@ class vmmConnection(gobject.GObject):
|
||||
# welcomed...
|
||||
sysfspath = obj.GetPropertyString("linux.sysfs_path")
|
||||
|
||||
# If running a device in bridged mode, there's a reasonable
|
||||
# chance that the actual ethernet device has been renamed to
|
||||
# something else. ethN -> pethN
|
||||
# Sick, disgusting hack for Xen netloop crack which renames
|
||||
# ethN -> pethN, but which HAL never sees
|
||||
psysfspath = sysfspath[0:len(sysfspath)-len(name)] + "p" + name
|
||||
if os.path.exists(psysfspath):
|
||||
name = "p" + name
|
||||
sysfspath = psysfspath
|
||||
|
||||
brportpath = os.path.join(sysfspath, "brport")
|
||||
@ -260,44 +205,61 @@ class vmmConnection(gobject.GObject):
|
||||
return self.readOnly
|
||||
|
||||
def get_type(self):
|
||||
if self.vmm is None:
|
||||
return None
|
||||
return self.vmm.getType()
|
||||
|
||||
def get_name(self):
|
||||
def get_short_hostname(self):
|
||||
hostname = self.get_hostname()
|
||||
offset = hostname.find(".")
|
||||
if offset > 0 and not hostname[0].isdigit():
|
||||
return hostname[0:offset]
|
||||
return hostname
|
||||
|
||||
def get_hostname(self, resolveLocal=False):
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(self.uri)
|
||||
|
||||
i = scheme.find("+")
|
||||
if i > 0:
|
||||
scheme = scheme[0:i]
|
||||
|
||||
if netloc == "":
|
||||
netloc = get_local_hostname()
|
||||
|
||||
if scheme == "xen":
|
||||
return "Xen on %s" % netloc
|
||||
elif scheme == "qemu":
|
||||
if path == "/session":
|
||||
return "QEMU session on %s" % netloc
|
||||
else:
|
||||
return "QEMU system on %s" % netloc
|
||||
elif scheme == "test":
|
||||
return "Test on %s" % netloc
|
||||
if netloc != "":
|
||||
return netloc
|
||||
except Exception, e:
|
||||
logging.warning("Cannot parse URI %s: %s" % (self.uri, str(e)))
|
||||
|
||||
return self.uri
|
||||
|
||||
def get_short_hostname(self):
|
||||
return get_short_hostname(self.uri)
|
||||
|
||||
def get_hostname(self, resolveLocal=False):
|
||||
return get_hostname(self.uri, resolveLocal)
|
||||
if resolveLocal:
|
||||
return get_local_hostname()
|
||||
return "localhost"
|
||||
|
||||
def get_transport(self):
|
||||
return get_transport(self.uri)
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(self.uri)
|
||||
if scheme:
|
||||
offset = scheme.index("+")
|
||||
if offset > 0:
|
||||
return [scheme[offset:], username]
|
||||
except:
|
||||
pass
|
||||
return [None, None]
|
||||
|
||||
def get_driver(self):
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(self.uri)
|
||||
if scheme:
|
||||
offset = scheme.find("+")
|
||||
if offset > 0:
|
||||
return scheme[:offset]
|
||||
return scheme
|
||||
except Exception, e:
|
||||
pass
|
||||
return "xen"
|
||||
|
||||
def is_remote(self):
|
||||
return is_remote(self.uri)
|
||||
try:
|
||||
(scheme, username, netloc, path, query, fragment) = uri_split(self.uri)
|
||||
if netloc == "":
|
||||
return False
|
||||
return True
|
||||
except:
|
||||
return True
|
||||
|
||||
def get_uri(self):
|
||||
return self.uri
|
||||
@ -311,13 +273,57 @@ class vmmConnection(gobject.GObject):
|
||||
def get_net_device(self, path):
|
||||
return self.netdevs[path]
|
||||
|
||||
def open(self):
|
||||
if self.state != self.STATE_DISCONNECTED:
|
||||
return
|
||||
|
||||
self.state = self.STATE_CONNECTING
|
||||
self.emit("state-changed")
|
||||
try:
|
||||
if self.readOnly is None:
|
||||
try:
|
||||
self.vmm = libvirt.open(self.uri)
|
||||
self.readOnly = False
|
||||
except:
|
||||
self.vmm = libvirt.openReadOnly(self.uri)
|
||||
self.readOnly = True
|
||||
else:
|
||||
if self.readOnly:
|
||||
self.vmm = libvirt.openReadOnly(self.uri)
|
||||
else:
|
||||
self.vmm = libvirt.open(self.uri)
|
||||
self.state = self.STATE_ACTIVE
|
||||
self.tick()
|
||||
self.emit("state-changed")
|
||||
except:
|
||||
self.state = self.STATE_DISCONNECTED
|
||||
self.emit("state-changed")
|
||||
raise
|
||||
|
||||
def pause(self):
|
||||
if self.state != self.STATE_ACTIVE:
|
||||
return
|
||||
self.state = self.STATE_INACTIVE
|
||||
self.emit("state-changed")
|
||||
|
||||
def resume(self):
|
||||
if self.state != self.STATE_INACTIVE:
|
||||
return
|
||||
self.state = self.STATE_ACTIVE
|
||||
self.emit("state-changed")
|
||||
|
||||
def close(self):
|
||||
if self.vmm == None:
|
||||
return
|
||||
|
||||
#self.vmm.close()
|
||||
self.vmm = None
|
||||
self.emit("disconnected", self.uri)
|
||||
self.nets = {}
|
||||
self.vms = {}
|
||||
self.activeUUIDs = []
|
||||
self.record = []
|
||||
self.state = self.STATE_DISCONNECTED
|
||||
self.emit("state-changed")
|
||||
|
||||
def list_vm_uuids(self):
|
||||
return self.vms.keys()
|
||||
@ -348,6 +354,8 @@ class vmmConnection(gobject.GObject):
|
||||
return handle_id
|
||||
|
||||
def pretty_host_memory_size(self):
|
||||
if self.vmm is None:
|
||||
return ""
|
||||
mem = self.host_memory_size()
|
||||
if mem > (1024*1024):
|
||||
return "%2.2f GB" % (mem/(1024.0*1024.0))
|
||||
@ -356,15 +364,23 @@ class vmmConnection(gobject.GObject):
|
||||
|
||||
|
||||
def host_memory_size(self):
|
||||
if self.vmm is None:
|
||||
return 0
|
||||
return self.hostinfo[1]*1024
|
||||
|
||||
def host_architecture(self):
|
||||
if self.vmm is None:
|
||||
return ""
|
||||
return self.hostinfo[0]
|
||||
|
||||
def host_active_processor_count(self):
|
||||
if self.vmm is None:
|
||||
return 0
|
||||
return self.hostinfo[2]
|
||||
|
||||
def host_maximum_processor_count(self):
|
||||
if self.vmm is None:
|
||||
return 0
|
||||
return self.hostinfo[4] * self.hostinfo[5] * self.hostinfo[6] * self.hostinfo[7]
|
||||
|
||||
def create_network(self, xml, start=True, autostart=True):
|
||||
@ -388,10 +404,7 @@ class vmmConnection(gobject.GObject):
|
||||
return status
|
||||
|
||||
def tick(self, noStatsUpdate=False):
|
||||
if self.vmm == None:
|
||||
return
|
||||
|
||||
if not self.active:
|
||||
if self.state != self.STATE_ACTIVE:
|
||||
return
|
||||
|
||||
oldNets = self.nets
|
||||
@ -411,7 +424,9 @@ class vmmConnection(gobject.GObject):
|
||||
logging.warn("Unable to list inactive networks")
|
||||
|
||||
# check of net devices
|
||||
newPaths = self.hal_iface.FindDeviceByCapability("net")
|
||||
newPaths = []
|
||||
if self.hal_iface:
|
||||
newPaths = self.hal_iface.FindDeviceByCapability("net")
|
||||
for newPath in newPaths:
|
||||
self._device_added(newPath)
|
||||
|
||||
@ -583,11 +598,11 @@ class vmmConnection(gobject.GObject):
|
||||
self.vms[uuid].tick(now)
|
||||
|
||||
if not noStatsUpdate:
|
||||
self.recalculate_stats(now)
|
||||
self._recalculate_stats(now)
|
||||
|
||||
return 1
|
||||
|
||||
def recalculate_stats(self, now):
|
||||
def _recalculate_stats(self, now):
|
||||
expected = self.config.get_stats_history_length()
|
||||
current = len(self.record)
|
||||
if current > expected:
|
||||
@ -694,48 +709,20 @@ class vmmConnection(gobject.GObject):
|
||||
uuid.append('-')
|
||||
return "".join(uuid)
|
||||
|
||||
def get_state(self):
|
||||
return self.state
|
||||
|
||||
# Standard python urlparse is utterly braindead - refusing to parse URIs
|
||||
# in any useful fashion unless the 'scheme' is in some pre-defined white
|
||||
# list. Theis functions is a hacked version of urlparse
|
||||
|
||||
def uri_split(self):
|
||||
uri = self.uri
|
||||
username = netloc = query = fragment = ''
|
||||
i = uri.find(":")
|
||||
if i > 0:
|
||||
scheme, uri = uri[:i].lower(), uri[i+1:]
|
||||
if uri[:2] == '//':
|
||||
netloc, uri = self._splitnetloc(uri, 2)
|
||||
offset = netloc.find("@")
|
||||
if offset > 0:
|
||||
username = netloc[0:offset]
|
||||
netloc = netloc[offset+1:]
|
||||
if '#' in uri:
|
||||
uri, fragment = uri.split('#', 1)
|
||||
if '?' in uri:
|
||||
uri, query = uri.split('?', 1)
|
||||
def get_state_text(self):
|
||||
if self.state == self.STATE_DISCONNECTED:
|
||||
return _("Disconnected")
|
||||
elif self.state == self.STATE_CONNECTING:
|
||||
return _("Connecting")
|
||||
elif self.state == self.STATE_ACTIVE:
|
||||
return _("Active")
|
||||
elif self.state == self.STATE_INACTIVE:
|
||||
return _("Inactive")
|
||||
else:
|
||||
scheme = uri.lower()
|
||||
|
||||
return scheme, username, netloc, uri, query, fragment
|
||||
|
||||
def _splitnetloc(self, url, start=0):
|
||||
for c in '/?#': # the order is important!
|
||||
delim = url.find(c, start)
|
||||
if delim >= 0:
|
||||
break
|
||||
else:
|
||||
delim = len(url)
|
||||
return url[start:delim], url[delim:]
|
||||
|
||||
|
||||
def is_active(self):
|
||||
return self._active
|
||||
def set_active(self, val):
|
||||
self._active = val
|
||||
active = property(is_active, set_active)
|
||||
|
||||
return _("Unknown")
|
||||
|
||||
gobject.type_register(vmmConnection)
|
||||
|
||||
|
@ -151,7 +151,7 @@ class vmmDomain(gobject.GObject):
|
||||
self.emit("status-changed", status)
|
||||
|
||||
def tick(self, now):
|
||||
if not self.connection.active:
|
||||
if self.connection.get_state() != self.connection.STATE_ACTIVE:
|
||||
return
|
||||
# Clear cached XML
|
||||
self.xml = None
|
||||
|
@ -37,8 +37,16 @@ from virtManager.serialcon import vmmSerialConsole
|
||||
from virtManager.error import vmmErrorDialog
|
||||
from virtManager.host import vmmHost
|
||||
|
||||
class vmmEngine:
|
||||
class vmmEngine(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
"connection-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
[object]),
|
||||
"connection-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
[object])
|
||||
}
|
||||
|
||||
def __init__(self, config):
|
||||
self.__gobject_init__()
|
||||
self.windowConnect = None
|
||||
self.windowPreferences = None
|
||||
self.windowAbout = None
|
||||
@ -53,25 +61,15 @@ class vmmEngine:
|
||||
self.config.on_stats_update_interval_changed(self.reschedule_timer)
|
||||
|
||||
self.schedule_timer()
|
||||
self.load_stored_uris()
|
||||
self.tick()
|
||||
|
||||
|
||||
def _do_connection_disconnected(self, connection, hvuri):
|
||||
del self.connections[hvuri]
|
||||
if len(self.connections.keys()) == 0 and self.windowConnect == None \
|
||||
and self.windowManager == None:
|
||||
gtk.main_quit()
|
||||
if self.windowManager is not None:
|
||||
self.windowManager.disconnect_connection(hvuri)
|
||||
|
||||
def load_stored_uris(self):
|
||||
uris = self.config.get_connections()
|
||||
if uris != None:
|
||||
logging.debug("About to connect to uris %s" % uris)
|
||||
manager = self.get_manager()
|
||||
for uri in uris:
|
||||
manager.add_connection(uri)
|
||||
self.show_manager()
|
||||
self.add_connection(uri)
|
||||
|
||||
def connect_to_uri(self, uri, readOnly=None):
|
||||
return self._connect_to_uri(None, uri, readOnly)
|
||||
@ -301,7 +299,7 @@ class vmmEngine:
|
||||
|
||||
def get_manager(self):
|
||||
if self.windowManager == None:
|
||||
self.windowManager = vmmManager(self.get_config())
|
||||
self.windowManager = vmmManager(self.get_config(), self)
|
||||
self.windowManager.connect("action-show-console", self._do_show_console)
|
||||
self.windowManager.connect("action-show-terminal", self._do_show_terminal)
|
||||
self.windowManager.connect("action-show-details", self._do_show_details)
|
||||
@ -329,20 +327,39 @@ class vmmEngine:
|
||||
self.windowCreate.reset_state()
|
||||
self.windowCreate.show()
|
||||
|
||||
def add_connection(self, uri, readOnly=None):
|
||||
conn = vmmConnection(self.get_config(), uri, readOnly)
|
||||
self.connections[uri] = {
|
||||
"connection": conn,
|
||||
"windowHost": None,
|
||||
"windowDetails": {},
|
||||
"windowConsole": {},
|
||||
"windowSerialConsole": {},
|
||||
}
|
||||
self.connections[uri]["connection"].connect("vm-removed", self._do_vm_removed)
|
||||
self.connections[uri]["connection"].tick()
|
||||
self.emit("connection-added", conn)
|
||||
self.config.add_connection(conn.get_uri())
|
||||
|
||||
def remove_connection(self, uri):
|
||||
conn = self.connections[uri]["connection"]
|
||||
conn.close()
|
||||
self.emit("connection-removed", conn)
|
||||
del self.connections[uri]
|
||||
self.config.remove_connection(conn.get_uri())
|
||||
|
||||
def connect(self, name, callback):
|
||||
handle_id = gobject.GObject.connect(self, name, callback)
|
||||
|
||||
if name == "connection-added":
|
||||
for uri in self.connections.keys():
|
||||
self.emit("connection-added", self.connections[uri]["connection"])
|
||||
|
||||
return handle_id
|
||||
|
||||
def get_connection(self, uri, readOnly=None):
|
||||
if not(self.connections.has_key(uri)):
|
||||
conn = vmmConnection(self.get_config(), uri, readOnly)
|
||||
self.connections[uri] = {
|
||||
"connection": conn,
|
||||
"windowHost": None,
|
||||
"windowDetails": {},
|
||||
"windowConsole": {},
|
||||
"windowSerialConsole": {},
|
||||
}
|
||||
self.connections[uri]["connection"].connect("disconnected", self._do_connection_disconnected)
|
||||
self.connections[uri]["connection"].connect("vm-removed", self._do_vm_removed)
|
||||
self.get_manager().connect_connection(self.connections[uri]["connection"])
|
||||
self.connections[uri]["connection"].tick()
|
||||
self.add_connection(uri, readOnly)
|
||||
|
||||
return self.connections[uri]["connection"]
|
||||
|
||||
@ -394,3 +411,5 @@ class vmmEngine:
|
||||
vm.destroy()
|
||||
else:
|
||||
return
|
||||
|
||||
gobject.type_register(vmmEngine)
|
||||
|
@ -26,9 +26,8 @@ import logging
|
||||
import sparkline
|
||||
import libvirt
|
||||
|
||||
import virtManager.connection as static_conn
|
||||
from virtManager.connection import vmmConnection
|
||||
from virtManager.asyncjob import vmmAsyncJob
|
||||
|
||||
|
||||
|
||||
VMLIST_SORT_ID = 1
|
||||
@ -85,10 +84,11 @@ class vmmManager(gobject.GObject):
|
||||
"action-show-help": (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, [str]),}
|
||||
|
||||
def __init__(self, config):
|
||||
def __init__(self, config, engine):
|
||||
self.__gobject_init__()
|
||||
self.window = gtk.glade.XML(config.get_glade_dir() + "/vmm-manager.glade", "vmm-manager", domain="virt-manager")
|
||||
self.config = config
|
||||
self.engine = engine
|
||||
self.connections = {}
|
||||
self.prepare_vmlist()
|
||||
|
||||
@ -180,12 +180,12 @@ class vmmManager(gobject.GObject):
|
||||
|
||||
self.connmenu_items["connect"] = gtk.ImageMenuItem(gtk.STOCK_CONNECT)
|
||||
self.connmenu_items["connect"].show()
|
||||
self.connmenu_items["connect"].connect("activate", self.create_connection)
|
||||
self.connmenu_items["connect"].connect("activate", self.open_connection)
|
||||
self.connmenu.add(self.connmenu_items["connect"])
|
||||
|
||||
self.connmenu_items["disconnect"] = gtk.ImageMenuItem(gtk.STOCK_DISCONNECT)
|
||||
self.connmenu_items["disconnect"].show()
|
||||
self.connmenu_items["disconnect"].connect("activate", self.destroy_connection)
|
||||
self.connmenu_items["disconnect"].connect("activate", self.close_connection)
|
||||
self.connmenu.add(self.connmenu_items["disconnect"])
|
||||
self.connmenu.show()
|
||||
|
||||
@ -199,7 +199,7 @@ class vmmManager(gobject.GObject):
|
||||
"on_menu_view_network_traffic_activate" : self.toggle_network_traffic_visible_conf,
|
||||
|
||||
"on_vm_manager_delete_event": self.close,
|
||||
"on_menu_file_open_connection_activate": self.open_connection,
|
||||
"on_menu_file_open_connection_activate": self.new_connection,
|
||||
"on_menu_file_quit_activate": self.exit_app,
|
||||
"on_menu_file_close_activate": self.close,
|
||||
"on_menu_restore_saved_activate": self.restore_saved,
|
||||
@ -228,6 +228,9 @@ class vmmManager(gobject.GObject):
|
||||
|
||||
self.window.get_widget("menu_file_restore_saved").set_sensitive(False)
|
||||
|
||||
self.engine.connect("connection-added", self._add_connection)
|
||||
self.engine.connect("connection-removed", self._remove_connection)
|
||||
|
||||
def show(self):
|
||||
win = self.window.get_widget("vmm-manager")
|
||||
win.show_all()
|
||||
@ -239,7 +242,7 @@ class vmmManager(gobject.GObject):
|
||||
conn.close()
|
||||
win = self.window.get_widget("vmm-manager")
|
||||
win.hide()
|
||||
return 1
|
||||
gtk.main_quit()
|
||||
|
||||
def is_visible(self):
|
||||
if self.window.get_widget("vmm-manager").flags() & gtk.VISIBLE:
|
||||
@ -249,7 +252,7 @@ class vmmManager(gobject.GObject):
|
||||
def exit_app(self, src=None, src2=None):
|
||||
gtk.main_quit()
|
||||
|
||||
def open_connection(self, src=None):
|
||||
def new_connection(self, src=None):
|
||||
self.emit("action-show-connect")
|
||||
|
||||
def is_showing_active(self):
|
||||
@ -274,7 +277,7 @@ class vmmManager(gobject.GObject):
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT),
|
||||
None)
|
||||
self.fcdialog.set_current_folder(self.config.get_default_save_dir(self.connections[self.get_current_connection()]))
|
||||
self.fcdialog.set_current_folder(self.config.get_default_save_dir(self.get_current_connection()))
|
||||
# pop up progress dialog
|
||||
response = self.fcdialog.run()
|
||||
self.fcdialog.hide()
|
||||
@ -317,7 +320,7 @@ class vmmManager(gobject.GObject):
|
||||
return False
|
||||
|
||||
def restore_saved_callback(self, file_to_load, ignore1=None):
|
||||
status = self.connections[self.get_current_connection()].restore(file_to_load)
|
||||
status = self.get_current_connection().restore(file_to_load)
|
||||
if(status != 0):
|
||||
self.domain_restore_error = _("Error restoring domain '%s'. Is the domain already running?") % file_to_load
|
||||
|
||||
@ -403,30 +406,25 @@ class vmmManager(gobject.GObject):
|
||||
# Expand a connection when adding a vm to it
|
||||
self.window.get_widget("vm-list").expand_row(model.get_path(parent), False)
|
||||
|
||||
def _append_connection(self, model, uri):
|
||||
def _append_connection(self, model, conn):
|
||||
row = []
|
||||
if self.connections.has_key(uri):
|
||||
row.insert(ROW_HANDLE, self.connections[uri])
|
||||
row.insert(ROW_STATUS, _("Connected"))
|
||||
row.insert(ROW_ACTION, "")
|
||||
else:
|
||||
row.insert(ROW_HANDLE, None)
|
||||
row.insert(ROW_STATUS, _("Disconnected"))
|
||||
row.insert(ROW_HANDLE, conn)
|
||||
row.insert(ROW_STATUS, conn.get_state_text())
|
||||
if conn.get_state() == vmmConnection.STATE_DISCONNECTED:
|
||||
row.insert(ROW_ACTION, gtk.STOCK_DELETE)
|
||||
row.insert(ROW_NAME, static_conn.get_short_hostname(uri))
|
||||
drv = static_conn.get_driver(uri)
|
||||
if drv is None:
|
||||
drv = "xen"
|
||||
row.insert(ROW_ID, drv)
|
||||
else:
|
||||
row.insert(ROW_ACTION, "")
|
||||
row.insert(ROW_NAME, conn.get_short_hostname())
|
||||
row.insert(ROW_ID, conn.get_driver())
|
||||
row.insert(ROW_STATUS_ICON, None)
|
||||
row.insert(ROW_CPU, "")
|
||||
row.insert(ROW_VCPUS, 0)
|
||||
row.insert(ROW_MEM, "")
|
||||
row.insert(ROW_MEM_USAGE, 0)
|
||||
row.insert(ROW_KEY, uri)
|
||||
row.insert(ROW_CPU, "%2.2f %%" % conn.cpu_time_percentage())
|
||||
row.insert(ROW_VCPUS, conn.host_active_processor_count())
|
||||
row.insert(ROW_MEM, conn.pretty_current_memory())
|
||||
row.insert(ROW_MEM_USAGE, conn.current_memory_percentage())
|
||||
row.insert(ROW_KEY, conn.get_uri())
|
||||
iter = model.append(None, row)
|
||||
path = model.get_path(iter)
|
||||
self.rows[uri] = model[path]
|
||||
self.rows[conn.get_uri()] = model[path]
|
||||
|
||||
def vm_removed(self, connection, uri, vmuuid):
|
||||
vmlist = self.window.get_widget("vm-list")
|
||||
@ -493,19 +491,33 @@ class vmmManager(gobject.GObject):
|
||||
row[ROW_ACTION] = gtk.STOCK_DELETE
|
||||
model.row_changed(row.path, row.iter)
|
||||
|
||||
def conn_refresh_resources(self, connection):
|
||||
def conn_state_changed(self, conn):
|
||||
if conn.get_state() in [conn.STATE_ACTIVE, conn.STATE_INACTIVE]:
|
||||
self.window.get_widget("menu_host_details").set_sensitive(True)
|
||||
else:
|
||||
self.window.get_widget("menu_host_details").set_sensitive(False)
|
||||
self.conn_refresh_resources(conn)
|
||||
|
||||
def conn_refresh_resources(self, conn):
|
||||
vmlist = self.window.get_widget("vm-list")
|
||||
model = vmlist.get_model()
|
||||
if not(self.rows.has_key(connection.get_uri())):
|
||||
return
|
||||
|
||||
row = self.rows[connection.get_uri()]
|
||||
row[ROW_STATUS] = _("Active")
|
||||
row[ROW_CPU] = "%2.2f %%" % connection.cpu_time_percentage()
|
||||
row[ROW_VCPUS] = connection.host_active_processor_count()
|
||||
row[ROW_MEM] = connection.pretty_current_memory()
|
||||
row[ROW_MEM_USAGE] = connection.current_memory_percentage()
|
||||
row[ROW_ACTION] = gtk.STOCK_NEW
|
||||
row = self.rows[conn.get_uri()]
|
||||
row[ROW_STATUS] = conn.get_state_text()
|
||||
row[ROW_CPU] = "%2.2f %%" % conn.cpu_time_percentage()
|
||||
row[ROW_VCPUS] = conn.host_active_processor_count()
|
||||
row[ROW_MEM] = conn.pretty_current_memory()
|
||||
row[ROW_MEM_USAGE] = conn.current_memory_percentage()
|
||||
if conn.get_state() == vmmConnection.STATE_DISCONNECTED:
|
||||
row[ROW_ACTION] = gtk.STOCK_DELETE
|
||||
parent = self.rows[conn.get_uri()].iter
|
||||
if parent is not None:
|
||||
child = model.iter_children(parent)
|
||||
while child is not None:
|
||||
del self.rows[model.get_value(child, ROW_KEY)]
|
||||
model.remove(child)
|
||||
child = model.iter_children(parent)
|
||||
else:
|
||||
row[ROW_ACTION] = gtk.STOCK_NEW
|
||||
model.row_changed(row.path, row.iter)
|
||||
|
||||
def current_vm(self):
|
||||
@ -517,7 +529,7 @@ class vmmManager(gobject.GObject):
|
||||
return active[0].get_value(active[1], ROW_HANDLE)
|
||||
return None
|
||||
|
||||
def get_current_connection(self):
|
||||
def current_connection(self):
|
||||
# returns a uri
|
||||
vmlist = self.window.get_widget("vm-list")
|
||||
selection = vmlist.get_selection()
|
||||
@ -527,9 +539,9 @@ class vmmManager(gobject.GObject):
|
||||
# return the connection of the currently selected vm, or the
|
||||
# currently selected connection
|
||||
if parent is not None:
|
||||
return active[0].get_value(parent, ROW_KEY)
|
||||
return active[0].get_value(parent, ROW_HANDLE)
|
||||
else:
|
||||
return active[0].get_value(active[1], ROW_KEY)
|
||||
return active[0].get_value(active[1], ROW_HANDLE)
|
||||
return None
|
||||
|
||||
def current_vmuuid(self):
|
||||
@ -538,6 +550,12 @@ class vmmManager(gobject.GObject):
|
||||
return None
|
||||
return vm.get_uuid()
|
||||
|
||||
def current_connection_uri(self):
|
||||
conn = self.current_connection()
|
||||
if conn is None:
|
||||
return None
|
||||
return conn.get_uri()
|
||||
|
||||
def show_vm_details(self,ignore):
|
||||
vm = self.current_vm()
|
||||
if vm is None:
|
||||
@ -546,23 +564,23 @@ class vmmManager(gobject.GObject):
|
||||
self.emit("action-show-details", conn.get_uri(), self.current_vmuuid())
|
||||
|
||||
def show_vm_create(self,ignore):
|
||||
self.emit("action-show-create", self.get_current_connection())
|
||||
self.emit("action-show-create", self.current_connection_uri())
|
||||
|
||||
def destroy_connection(self, ignore):
|
||||
current_uri = self.get_current_connection()
|
||||
if self.connections.has_key(current_uri):
|
||||
self.connections[current_uri].close()
|
||||
def close_connection(self, ignore):
|
||||
conn = self.current_connection()
|
||||
if conn.get_state() != vmmConnection.STATE_DISCONNECTED:
|
||||
conn.close()
|
||||
|
||||
def create_connection(self, ignore = None):
|
||||
current_uri = self.get_current_connection()
|
||||
if not self.connections.has_key(current_uri):
|
||||
self.emit("action-connect", current_uri)
|
||||
def open_connection(self, ignore = None):
|
||||
conn = self.current_connection()
|
||||
if conn.get_state() == vmmConnection.STATE_DISCONNECTED:
|
||||
conn.open()
|
||||
|
||||
def open_vm_console(self,ignore,ignore2=None,ignore3=None):
|
||||
if self.current_vmuuid():
|
||||
self.emit("action-show-console", self.get_current_connection(), self.current_vmuuid())
|
||||
elif self.get_current_connection():
|
||||
self.create_connection()
|
||||
self.emit("action-show-console", self.current_connection_uri(), self.current_vmuuid())
|
||||
elif self.current_connection():
|
||||
self.open_connection()
|
||||
|
||||
|
||||
def vm_selected(self, selection):
|
||||
@ -587,7 +605,11 @@ class vmmManager(gobject.GObject):
|
||||
self.window.get_widget("vm-open").set_sensitive(False)
|
||||
self.window.get_widget("menu_edit_details").set_sensitive(False)
|
||||
self.window.get_widget("menu_edit_delete").set_sensitive(False)
|
||||
self.window.get_widget("menu_host_details").set_sensitive(True)
|
||||
conn = self.current_connection()
|
||||
if conn is None or conn.get_state() in [conn.STATE_ACTIVE, conn.STATE_INACTIVE]:
|
||||
self.window.get_widget("menu_host_details").set_sensitive(True)
|
||||
else:
|
||||
self.window.get_widget("menu_host_details").set_sensitive(False)
|
||||
|
||||
def popup_vm_menu(self, widget, event):
|
||||
tuple = widget.get_path_at_pos(int(event.x), int(event.y))
|
||||
@ -652,9 +674,9 @@ class vmmManager(gobject.GObject):
|
||||
conn.tick(noStatsUpdate=True)
|
||||
return False
|
||||
else:
|
||||
uri = model.get_value(iter, ROW_KEY)
|
||||
conn = model.get_value(iter, ROW_HANDLE)
|
||||
if event.button == 3:
|
||||
if self.connections.has_key(uri):
|
||||
if conn.get_state() != vmmConnection.STATE_DISCONNECTED:
|
||||
self.connmenu_items["create"].set_sensitive(True)
|
||||
self.connmenu_items["disconnect"].set_sensitive(True)
|
||||
self.connmenu_items["connect"].set_sensitive(False)
|
||||
@ -668,8 +690,8 @@ class vmmManager(gobject.GObject):
|
||||
area = widget.get_cell_area(path, widget.get_column(COL_ACTION))
|
||||
if int(event.x) > area.x and int(event.x) < area.x + area.width:
|
||||
# clicked the action column
|
||||
if self.connections.has_key(uri):
|
||||
if self.connections[uri].is_remote():
|
||||
if conn.get_state() != vmmConnection.STATE_DISCONNECTED:
|
||||
if conn.is_remote():
|
||||
warn = gtk.MessageDialog(self.window.get_widget("vmm-manager"),
|
||||
gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
gtk.MESSAGE_WARNING,
|
||||
@ -678,19 +700,19 @@ class vmmManager(gobject.GObject):
|
||||
result = warn.run()
|
||||
warn.destroy()
|
||||
else:
|
||||
self.emit("action-show-create", uri)
|
||||
self.emit("action-show-create", conn.get_uri())
|
||||
else:
|
||||
warn = gtk.MessageDialog(self.window.get_widget("vmm-manager"),
|
||||
gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
gtk.MESSAGE_WARNING,
|
||||
gtk.BUTTONS_YES_NO,
|
||||
_("This will permanently delete the connection \"%s\", are you sure?") % self.rows[uri][ROW_NAME])
|
||||
_("This will permanently delete the connection \"%s\", are you sure?") % self.rows[conn.get_uri()][ROW_NAME])
|
||||
result = warn.run()
|
||||
warn.destroy()
|
||||
if result == gtk.RESPONSE_NO:
|
||||
return
|
||||
self.delete_connection(uri)
|
||||
return False
|
||||
self.engine.remove_connection(conn.get_uri())
|
||||
return False
|
||||
|
||||
def show_about(self, src):
|
||||
self.emit("action-show-about")
|
||||
@ -703,7 +725,7 @@ class vmmManager(gobject.GObject):
|
||||
self.emit("action-show-preferences")
|
||||
|
||||
def show_host(self, src):
|
||||
self.emit("action-show-host", self.get_current_connection())
|
||||
self.emit("action-show-host", self.current_connection_uri())
|
||||
|
||||
def prepare_vmlist(self):
|
||||
vmlist = self.window.get_widget("vm-list")
|
||||
@ -921,52 +943,21 @@ class vmmManager(gobject.GObject):
|
||||
vm = self.current_vm()
|
||||
if vm is not None:
|
||||
vm.resume()
|
||||
|
||||
def connect_connection(self, connection):
|
||||
connection.connect("vm-added", self.vm_added)
|
||||
connection.connect("vm-removed", self.vm_removed)
|
||||
connection.connect("resources-sampled", self.conn_refresh_resources)
|
||||
connection.connect("vm-started", self.vm_started)
|
||||
self.connections[connection.uri] = connection
|
||||
self.add_connection(connection.uri)
|
||||
|
||||
def add_connection(self, uri):
|
||||
def _add_connection(self, engine, conn):
|
||||
conn.connect("vm-added", self.vm_added)
|
||||
conn.connect("vm-removed", self.vm_removed)
|
||||
conn.connect("resources-sampled", self.conn_refresh_resources)
|
||||
conn.connect("state-changed", self.conn_state_changed)
|
||||
conn.connect("vm-started", self.vm_started)
|
||||
# add the connection to the treeModel
|
||||
vmlist = self.window.get_widget("vm-list")
|
||||
if self.rows.has_key(uri):
|
||||
if self.connections.has_key(uri):
|
||||
self.rows[uri][ROW_HANDLE] = self.connections[uri]
|
||||
else:
|
||||
self._append_connection(vmlist.get_model(), uri)
|
||||
self.config.add_connection(uri)
|
||||
|
||||
def disconnect_connection(self, uri):
|
||||
treeview = self.window.get_widget("vm-list")
|
||||
model = treeview.get_model()
|
||||
parent = self.rows[uri].iter
|
||||
if parent is not None:
|
||||
child = model.iter_children(parent)
|
||||
while child is not None:
|
||||
del self.rows[model.get_value(child, ROW_KEY)]
|
||||
model.remove(child)
|
||||
child = model.iter_children(parent)
|
||||
row = self.rows[uri]
|
||||
row[ROW_HANDLE] = None
|
||||
# keep uri and name for connection, so we can reconnect if needed
|
||||
row[ROW_STATUS] = _("Disconnected")
|
||||
row[ROW_VCPUS] = 0
|
||||
row[ROW_MEM] = ""
|
||||
row[ROW_MEM_USAGE] = 0
|
||||
row[ROW_ACTION] = gtk.STOCK_DELETE
|
||||
treeview.get_model().row_changed(row.path, row.iter)
|
||||
del self.connections[uri]
|
||||
if not self.rows.has_key(conn.get_uri()):
|
||||
self._append_connection(vmlist.get_model(), conn)
|
||||
|
||||
def delete_connection(self, uri):
|
||||
def _remove_connection(self, engine, conn):
|
||||
model = self.window.get_widget("vm-list").get_model()
|
||||
parent = self.rows[uri].iter
|
||||
if self.rows[uri][ROW_HANDLE] is not None:
|
||||
# connection is still connected, don't delete it
|
||||
return
|
||||
parent = self.rows[conn.get_uri()].iter
|
||||
if parent is not None:
|
||||
child = model.iter_children(parent)
|
||||
while child is not None:
|
||||
@ -974,27 +965,16 @@ class vmmManager(gobject.GObject):
|
||||
model.remove(child)
|
||||
child = model.iter_children(parent)
|
||||
model.remove(parent)
|
||||
del self.rows[uri]
|
||||
self.config.remove_connection(uri)
|
||||
del self.rows[conn.get_uri()]
|
||||
|
||||
def row_expanded(self, treeview, iter, path):
|
||||
conn = treeview.get_model().get_value(iter,ROW_HANDLE)
|
||||
if conn is None:
|
||||
treeview.collapse_row(path, false)
|
||||
return
|
||||
logging.debug("Activating connection %s" % conn.get_name())
|
||||
conn.active = True
|
||||
|
||||
logging.debug("Activating connection %s" % conn.get_uri())
|
||||
conn.resume()
|
||||
|
||||
def row_collapsed(self, treeview, iter, path):
|
||||
conn = treeview.get_model().get_value(iter,ROW_HANDLE)
|
||||
logging.debug("Deactivating connection %s" % conn.get_name())
|
||||
conn.active = False
|
||||
row = self.rows[conn.get_uri()]
|
||||
row[ROW_STATUS] = _("Inactive")
|
||||
row[ROW_CPU] = ""
|
||||
row[ROW_VCPUS] = 0
|
||||
row[ROW_MEM] = ""
|
||||
row[ROW_MEM_USAGE] = 0
|
||||
treeview.get_model().row_changed(row.path, row.iter)
|
||||
logging.debug("Deactivating connection %s" % conn.get_uri())
|
||||
conn.pause()
|
||||
|
||||
gobject.type_register(vmmManager)
|
||||
|
Loading…
Reference in New Issue
Block a user