Move opening of connections into a background thread to avoid locking the UI
This commit is contained in:
parent
99c92b9471
commit
96eb9f5f24
|
@ -26,6 +26,8 @@ from time import time
|
|||
import logging
|
||||
from socket import gethostbyaddr, gethostname
|
||||
import dbus
|
||||
import threading
|
||||
import gtk
|
||||
|
||||
from virtManager.domain import vmmDomain
|
||||
from virtManager.network import vmmNetwork
|
||||
|
@ -96,6 +98,8 @@ class vmmConnection(gobject.GObject):
|
|||
[]),
|
||||
"state-changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
[]),
|
||||
"connect-error": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
[str]),
|
||||
}
|
||||
|
||||
STATE_DISCONNECTED = 0
|
||||
|
@ -108,6 +112,8 @@ class vmmConnection(gobject.GObject):
|
|||
self.config = config
|
||||
self.readOnly = readOnly
|
||||
|
||||
self.connectThread = None
|
||||
self.connectError = None
|
||||
self.uri = uri
|
||||
if self.uri is None or self.uri.lower() == "xen":
|
||||
self.uri = "xen:///"
|
||||
|
@ -279,6 +285,15 @@ class vmmConnection(gobject.GObject):
|
|||
|
||||
self.state = self.STATE_CONNECTING
|
||||
self.emit("state-changed")
|
||||
|
||||
logging.debug("Scheduling background open thread for " + self.uri)
|
||||
self.connectThread = threading.Thread(target = self._open_thread, name="Connect " + self.uri)
|
||||
self.connectThread.setDaemon(True)
|
||||
self.connectThread.start()
|
||||
|
||||
|
||||
def _open_thread(self):
|
||||
logging.debug("Background thread is running")
|
||||
try:
|
||||
if self.readOnly is None:
|
||||
try:
|
||||
|
@ -293,12 +308,42 @@ class vmmConnection(gobject.GObject):
|
|||
else:
|
||||
self.vmm = libvirt.open(self.uri)
|
||||
self.state = self.STATE_ACTIVE
|
||||
self.tick()
|
||||
self.emit("state-changed")
|
||||
except:
|
||||
self.state = self.STATE_DISCONNECTED
|
||||
|
||||
(type, value, stacktrace) = sys.exc_info ()
|
||||
# Detailed error message, in English so it can be Googled.
|
||||
self.connectError = \
|
||||
("Unable to open connection to hypervisor URI '%s':\n" %
|
||||
str(self.uri)) + \
|
||||
str(type) + " " + str(value) + "\n" + \
|
||||
traceback.format_exc (stacktrace)
|
||||
logging.error(self.connectError)
|
||||
|
||||
# We want to kill off this thread asap, so schedule a gobject
|
||||
# idle even to inform the UI of result
|
||||
logging.debug("Background open thread complete, scheduling notify")
|
||||
gtk.gdk.threads_enter()
|
||||
try:
|
||||
gobject.idle_add(self._open_notify)
|
||||
finally:
|
||||
gtk.gdk.threads_leave()
|
||||
self.connectThread = None
|
||||
|
||||
def _open_notify(self):
|
||||
logging.debug("Notifying open result")
|
||||
gtk.gdk.threads_enter()
|
||||
try:
|
||||
if self.state == self.STATE_ACTIVE:
|
||||
self.tick()
|
||||
self.emit("state-changed")
|
||||
raise
|
||||
|
||||
if self.state == self.STATE_DISCONNECTED:
|
||||
self.emit("connect-error", self.connectError)
|
||||
self.connectError = None
|
||||
finally:
|
||||
gtk.gdk.threads_leave()
|
||||
|
||||
|
||||
def pause(self):
|
||||
if self.state != self.STATE_ACTIVE:
|
||||
|
|
|
@ -34,7 +34,6 @@ from virtManager.console import vmmConsole
|
|||
from virtManager.asyncjob import vmmAsyncJob
|
||||
from virtManager.create import vmmCreate
|
||||
from virtManager.serialcon import vmmSerialConsole
|
||||
from virtManager.error import vmmErrorDialog
|
||||
from virtManager.host import vmmHost
|
||||
|
||||
class vmmEngine(gobject.GObject):
|
||||
|
@ -82,43 +81,6 @@ class vmmEngine(gobject.GObject):
|
|||
self.show_manager()
|
||||
return conn
|
||||
except:
|
||||
(type, value, stacktrace) = sys.exc_info ()
|
||||
|
||||
# Detailed error message, in English so it can be Googled.
|
||||
details = \
|
||||
("Unable to open connection to hypervisor URI '%s':\n" %
|
||||
str(uri)) + \
|
||||
str(type) + " " + str(value) + "\n" + \
|
||||
traceback.format_exc (stacktrace)
|
||||
logging.error (details)
|
||||
|
||||
# Error dialog.
|
||||
if uri is None:
|
||||
uri = "xen"
|
||||
if uri == "xen":
|
||||
dg = vmmErrorDialog (None, 0, gtk.MESSAGE_ERROR,
|
||||
gtk.BUTTONS_CLOSE,
|
||||
_("Unable to open a connection to the Xen hypervisor/daemon.\n\n" +
|
||||
"Verify that:\n" +
|
||||
" - A Xen host kernel was booted\n" +
|
||||
" - The Xen service has been started\n"),
|
||||
details)
|
||||
elif uri.startswith("qemu:"):
|
||||
dg = vmmErrorDialog (None, 0, gtk.MESSAGE_ERROR,
|
||||
gtk.BUTTONS_CLOSE,
|
||||
_("Unable to open a connection to the QEMU management daemon.\n\n" +
|
||||
"Verify that:\n" +
|
||||
" - The 'libvirt_qemud' daemon has been started\n"),
|
||||
details)
|
||||
else:
|
||||
dg = vmmErrorDialog (None, 0, gtk.MESSAGE_ERROR,
|
||||
gtk.BUTTONS_CLOSE,
|
||||
_("Unable to open connection to hypervisor '%s'") % str(uri),
|
||||
details)
|
||||
dg.set_title(_("Virtual Machine Manager Connection Failure"))
|
||||
dg.run()
|
||||
dg.hide()
|
||||
dg.destroy()
|
||||
return None
|
||||
|
||||
def _connect_cancelled(self, connect):
|
||||
|
|
|
@ -22,13 +22,14 @@ import gtk
|
|||
import gtk.glade
|
||||
import threading
|
||||
import logging
|
||||
import sys
|
||||
|
||||
import sparkline
|
||||
import libvirt
|
||||
|
||||
from virtManager.connection import vmmConnection
|
||||
from virtManager.asyncjob import vmmAsyncJob
|
||||
|
||||
from virtManager.error import vmmErrorDialog
|
||||
|
||||
VMLIST_SORT_ID = 1
|
||||
VMLIST_SORT_NAME = 2
|
||||
|
@ -503,7 +504,7 @@ class vmmManager(gobject.GObject):
|
|||
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:
|
||||
if conn.get_state() in [vmmConnection.STATE_DISCONNECTED, vmmConnection.STATE_CONNECTING]:
|
||||
row[ROW_ACTION] = gtk.STOCK_DELETE
|
||||
parent = self.rows[conn.get_uri()].iter
|
||||
if parent is not None:
|
||||
|
@ -942,6 +943,7 @@ class vmmManager(gobject.GObject):
|
|||
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("connect-error", self._connect_error)
|
||||
conn.connect("vm-started", self.vm_started)
|
||||
# add the connection to the treeModel
|
||||
vmlist = self.window.get_widget("vm-list")
|
||||
|
@ -970,4 +972,26 @@ class vmmManager(gobject.GObject):
|
|||
logging.debug("Deactivating connection %s" % conn.get_uri())
|
||||
conn.pause()
|
||||
|
||||
def _connect_error(self, conn, details):
|
||||
if conn.get_driver() == "xen" and not conn.is_remote():
|
||||
dg = vmmErrorDialog (None, 0, gtk.MESSAGE_ERROR,
|
||||
gtk.BUTTONS_CLOSE,
|
||||
_("Unable to open a connection to the Xen hypervisor/daemon.\n\n" +
|
||||
"Verify that:\n" +
|
||||
" - A Xen host kernel was booted\n" +
|
||||
" - The Xen service has been started\n"),
|
||||
details)
|
||||
else:
|
||||
dg = vmmErrorDialog (None, 0, gtk.MESSAGE_ERROR,
|
||||
gtk.BUTTONS_CLOSE,
|
||||
_("Unable to open a connection to the libvirt management daemon.\n\n" +
|
||||
"Verify that:\n" +
|
||||
" - The 'libvirtd' daemon has been started\n"),
|
||||
details)
|
||||
dg.set_title(_("Virtual Machine Manager Connection Failure"))
|
||||
dg.run()
|
||||
dg.hide()
|
||||
dg.destroy()
|
||||
|
||||
|
||||
gobject.type_register(vmmManager)
|
||||
|
|
Loading…
Reference in New Issue