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:
Daniel P. Berrange 2007-09-09 22:57:24 -04:00
parent db9086e189
commit dc391b698a
6 changed files with 300 additions and 316 deletions

View File

@ -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.

View File

@ -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):

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)