a6a15d4ac1
app is run (bz 548430) Check packagekit for KVM and libvirtd (bz 513494) Fake a reboot implementation if libvirt doesn't support it (bz 532216) Mark some strings as translatable (bz 572645)
941 lines
34 KiB
Diff
941 lines
34 KiB
Diff
# HG changeset patch
|
|
# User Cole Robinson <crobinso@redhat.com>
|
|
# Date 1265909520 18000
|
|
# Node ID 2a65e0b160a98b1969484ff61a8dcafc66f508d2
|
|
# Parent 40fb60222e4e1cc6a03942bbcfb9d2e727236410
|
|
Make sure all idle and timeout routines are thread safe.
|
|
|
|
Unbeknownst to me, these functions are not run thread safe:
|
|
|
|
http://library.gnome.org/devel/gdk/unstable/gdk-Threads.html
|
|
|
|
However since they are run from the main loop, the chance of them conflicting
|
|
with another running thread is slim, since we have very few threads that
|
|
actually update the UI.
|
|
|
|
diff -r 40fb60222e4e -r 2a65e0b160a9 src/virtManager/connection.py
|
|
--- a/src/virtManager/connection.py Thu Feb 11 09:32:05 2010 -0500
|
|
+++ b/src/virtManager/connection.py Thu Feb 11 12:32:00 2010 -0500
|
|
@@ -988,8 +988,8 @@
|
|
self.vms.keys())
|
|
|
|
if self.state == self.STATE_DISCONNECTED:
|
|
- gobject.idle_add(util.idle_emit, self, "connect-error",
|
|
- self.connectError)
|
|
+ util.safe_idle_add(util.idle_emit, self, "connect-error",
|
|
+ self.connectError)
|
|
self.connectError = None
|
|
finally:
|
|
self.connectThreadEvent.set()
|
|
@@ -1445,7 +1445,7 @@
|
|
for name in newNodedevs:
|
|
self.emit("nodedev-added", self.uri, name)
|
|
|
|
- gobject.idle_add(tick_send_signals)
|
|
+ util.safe_idle_add(tick_send_signals)
|
|
|
|
# Finally, we sample each domain
|
|
now = time()
|
|
@@ -1468,7 +1468,7 @@
|
|
if not noStatsUpdate:
|
|
self._recalculate_stats(now)
|
|
|
|
- gobject.idle_add(util.idle_emit, self, "resources-sampled")
|
|
+ util.safe_idle_add(util.idle_emit, self, "resources-sampled")
|
|
|
|
return 1
|
|
|
|
diff -r 40fb60222e4e -r 2a65e0b160a9 src/virtManager/console.py
|
|
--- a/src/virtManager/console.py Thu Feb 11 09:32:05 2010 -0500
|
|
+++ b/src/virtManager/console.py Thu Feb 11 12:32:00 2010 -0500
|
|
@@ -477,7 +478,7 @@
|
|
logging.error("Too many connection failures, not retrying again")
|
|
return
|
|
logging.warn("Retrying connection in %d ms", self.vncViewerRetryDelay)
|
|
- gobject.timeout_add(self.vncViewerRetryDelay, self.retry_login)
|
|
+ util.safe_timeout_add(self.vncViewerRetryDelay, self.retry_login)
|
|
if self.vncViewerRetryDelay < 2000:
|
|
self.vncViewerRetryDelay = self.vncViewerRetryDelay * 2
|
|
|
|
@@ -489,12 +490,8 @@
|
|
libvirt.VIR_DOMAIN_CRASHED ]:
|
|
return
|
|
|
|
- gtk.gdk.threads_enter()
|
|
- try:
|
|
- self.try_login()
|
|
- return
|
|
- finally:
|
|
- gtk.gdk.threads_leave()
|
|
+ self.try_login()
|
|
+ return
|
|
|
|
def open_tunnel(self, server, vncaddr, vncport, username, sshport):
|
|
if self.vncTunnel is not None:
|
|
@@ -676,7 +673,7 @@
|
|
|
|
def unset_cb(src):
|
|
src.queue_resize_no_redraw()
|
|
- gobject.idle_add(restore_scroll, src)
|
|
+ util.safe_idle_add(restore_scroll, src)
|
|
return False
|
|
|
|
def request_cb(src, req):
|
|
@@ -686,7 +683,7 @@
|
|
|
|
src.disconnect(signal_id)
|
|
|
|
- gobject.idle_add(unset_cb, widget)
|
|
+ util.safe_idle_add(unset_cb, widget)
|
|
return False
|
|
|
|
# Disable scroll bars while we resize, since resizing to the VM's
|
|
diff -r 40fb60222e4e -r 2a65e0b160a9 src/virtManager/create.py
|
|
--- a/src/virtManager/create.py Thu Feb 11 09:32:05 2010 -0500
|
|
+++ b/src/virtManager/create.py Thu Feb 11 12:32:00 2010 -0500
|
|
@@ -349,7 +349,7 @@
|
|
|
|
# Storage
|
|
if not self.host_storage_timer:
|
|
- self.host_storage_timer = gobject.timeout_add(3 * 1000,
|
|
+ self.host_storage_timer = util.safe_timeout_add(3 * 1000,
|
|
self.host_space_tick)
|
|
self.window.get_widget("enable-storage").set_active(True)
|
|
self.window.get_widget("config-storage-create").set_active(True)
|
|
diff -r 40fb60222e4e -r 2a65e0b160a9 src/virtManager/domain.py
|
|
--- a/src/virtManager/domain.py Thu Feb 11 09:32:05 2010 -0500
|
|
+++ b/src/virtManager/domain.py Thu Feb 11 12:32:00 2010 -0500
|
|
@@ -1357,7 +1357,7 @@
|
|
if origxml != self._xml:
|
|
# 'tick' to make sure we have the latest time
|
|
self.tick(time.time())
|
|
- gobject.idle_add(util.idle_emit, self, "config-changed")
|
|
+ util.safe_idle_add(util.idle_emit, self, "config-changed")
|
|
|
|
def _redefine(self, xml_func, *args):
|
|
"""
|
|
@@ -1848,7 +1848,7 @@
|
|
self._startup_vcpus = None
|
|
self.vcpu_max_count()
|
|
self.lastStatus = status
|
|
- gobject.idle_add(util.idle_emit, self, "status-changed", status)
|
|
+ util.safe_idle_add(util.idle_emit, self, "status-changed", status)
|
|
|
|
|
|
def tick(self, now):
|
|
@@ -1917,7 +1917,7 @@
|
|
|
|
self.record.insert(0, newStats)
|
|
self._update_status(info[0])
|
|
- gobject.idle_add(util.idle_emit, self, "resources-sampled")
|
|
+ util.safe_idle_add(util.idle_emit, self, "resources-sampled")
|
|
|
|
|
|
class vmmDomainVirtinst(vmmDomainBase):
|
|
diff -r 40fb60222e4e -r 2a65e0b160a9 src/virtManager/engine.py
|
|
--- a/src/virtManager/engine.py Thu Feb 11 09:32:05 2010 -0500
|
|
+++ b/src/virtManager/engine.py Thu Feb 11 12:32:00 2010 -0500
|
|
@@ -191,6 +191,8 @@
|
|
gobject.source_remove(self.timer)
|
|
self.timer = None
|
|
|
|
+ # No need to use 'safe_timeout_add', the tick should be
|
|
+ # manually made thread safe
|
|
self.timer = gobject.timeout_add(interval, self.tick)
|
|
|
|
def tick(self):
|
|
@@ -205,7 +207,7 @@
|
|
|
|
self._tick_thread = threading.Thread(name="Tick thread",
|
|
target=self._tick, args=())
|
|
- self._tick_thread.daemon = False
|
|
+ self._tick_thread.daemon = True
|
|
self._tick_thread.start()
|
|
return 1
|
|
|
|
@@ -221,7 +223,7 @@
|
|
logging.exception("Could not refresh connection %s." % uri)
|
|
logging.debug("Closing connection since libvirtd "
|
|
"appears to have stopped.")
|
|
- gobject.idle_add(conn.close)
|
|
+ util.safe_idle_add(conn.close)
|
|
else:
|
|
raise
|
|
return 1
|
|
diff -r 40fb60222e4e -r 2a65e0b160a9 src/virtManager/mediadev.py
|
|
--- a/src/virtManager/mediadev.py Thu Feb 11 09:32:05 2010 -0500
|
|
+++ b/src/virtManager/mediadev.py Thu Feb 11 12:32:00 2010 -0500
|
|
@@ -23,6 +23,8 @@
|
|
|
|
import virtinst
|
|
|
|
+from virtManager import util
|
|
+
|
|
MEDIA_FLOPPY = "floppy"
|
|
MEDIA_CDROM = "cdrom"
|
|
|
|
@@ -136,8 +138,8 @@
|
|
if self.poll_signal:
|
|
return
|
|
|
|
- self.poll_signal = gobject.timeout_add(MEDIA_TIMEOUT * 1000,
|
|
- self._poll_for_media)
|
|
+ self.poll_signal = util.safe_timeout_add(MEDIA_TIMEOUT * 1000,
|
|
+ self._poll_for_media)
|
|
|
|
def disable_poll_for_media(self):
|
|
self.poll_signal = None
|
|
diff -r 40fb60222e4e -r 2a65e0b160a9 src/virtManager/util.py
|
|
--- a/src/virtManager/util.py Thu Feb 11 09:32:05 2010 -0500
|
|
+++ b/src/virtManager/util.py Thu Feb 11 12:32:00 2010 -0500
|
|
@@ -18,12 +18,14 @@
|
|
# MA 02110-1301 USA.
|
|
#
|
|
|
|
-import logging
|
|
import gtk
|
|
-import libxml2
|
|
-import os.path
|
|
+import gobject
|
|
|
|
import libvirt
|
|
+import libxml2
|
|
+
|
|
+import logging
|
|
+import os.path
|
|
|
|
import virtManager
|
|
import virtinst
|
|
@@ -245,6 +247,25 @@
|
|
self.emit(signal, *args)
|
|
return False
|
|
|
|
+def _safe_wrapper(func, *args):
|
|
+ gtk.gdk.threads_enter()
|
|
+ try:
|
|
+ func(*args)
|
|
+ finally:
|
|
+ gtk.gdk.threads_leave()
|
|
+
|
|
+def safe_idle_add(func, *args):
|
|
+ """
|
|
+ Make sure idle functions are run thread safe
|
|
+ """
|
|
+ return gobject.idle_add(_safe_wrapper, func, *args)
|
|
+
|
|
+def safe_timeout_add(timeout, func, *args):
|
|
+ """
|
|
+ Make sure timeout functions are run thread safe
|
|
+ """
|
|
+ return gobject.timeout_add(timeout, _safe_wrapper, func, *args)
|
|
+
|
|
def uuidstr(rawuuid):
|
|
hx = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
|
|
uuid = []
|
|
diff -rup virt-manager-0.8.3/src/virtManager/connection.py new/src/virtManager/connection.py
|
|
--- virt-manager-0.8.3/src/virtManager/connection.py 2010-03-22 10:17:19.000000000 -0400
|
|
+++ new/src/virtManager/connection.py 2010-03-22 10:18:23.000000000 -0400
|
|
@@ -935,14 +935,14 @@ class vmmConnection(gobject.GObject):
|
|
# 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")
|
|
- gobject.idle_add(self._open_notify)
|
|
+ util.safe_idle_add(self._open_notify)
|
|
self.connectThread = None
|
|
|
|
def _open_notify(self):
|
|
logging.debug("Notifying open result")
|
|
|
|
try:
|
|
- gobject.idle_add(util.idle_emit, self, "state-changed")
|
|
+ util.safe_idle_add(util.idle_emit, self, "state-changed")
|
|
|
|
if self.state == self.STATE_ACTIVE:
|
|
logging.debug("%s capabilities:\n%s" %
|
|
diff -rup virt-manager-0.8.3/src/virtManager/console.py new/src/virtManager/console.py
|
|
--- virt-manager-0.8.3/src/virtManager/console.py 2010-03-22 10:17:19.000000000 -0400
|
|
+++ new/src/virtManager/console.py 2010-03-22 10:18:58.000000000 -0400
|
|
@@ -30,6 +30,7 @@ import gtkvnc
|
|
import os
|
|
import socket
|
|
|
|
+from virtManager import util
|
|
from virtManager.error import vmmErrorDialog
|
|
|
|
# Console pages
|
|
# HG changeset patch
|
|
# User Cole Robinson <crobinso@redhat.com>
|
|
# Date 1266506262 18000
|
|
# Node ID 6124400e5d9f7241519a2fdfed17dd5463dbe79c
|
|
# Parent cea6cdd27c83d70d0191d94d1cedab447c095001
|
|
util: Fix return value of safe idle timeouts
|
|
|
|
diff -r cea6cdd27c83 -r 6124400e5d9f src/virtManager/util.py
|
|
--- a/src/virtManager/util.py Wed Feb 17 16:40:33 2010 -0500
|
|
+++ b/src/virtManager/util.py Thu Feb 18 10:17:42 2010 -0500
|
|
@@ -250,7 +250,7 @@
|
|
def _safe_wrapper(func, *args):
|
|
gtk.gdk.threads_enter()
|
|
try:
|
|
- func(*args)
|
|
+ return func(*args)
|
|
finally:
|
|
gtk.gdk.threads_leave()
|
|
|
|
diff -rup abc/src/virtManager/asyncjob.py virt-manager-0.8.3/src/virtManager/asyncjob.py
|
|
--- abc/src/virtManager/asyncjob.py 2010-03-21 22:43:09.000000000 -0400
|
|
+++ virt-manager-0.8.3/src/virtManager/asyncjob.py 2010-03-21 22:44:22.000000000 -0400
|
|
@@ -25,25 +25,31 @@ import gtk.gdk
|
|
import gtk.glade
|
|
import gobject
|
|
|
|
-# Displays a progress bar while executing the "callback" method.
|
|
+from virtManager import util
|
|
|
|
-class vmmAsyncJob(gobject.GObject):
|
|
- # This thin wrapper only exists so we can put debugging
|
|
- # code in the run() method every now & then
|
|
- class asyncJobWorker(threading.Thread):
|
|
- def __init__(self, callback, args):
|
|
- threading.Thread.__init__(self, target=callback, args=args)
|
|
+# This thin wrapper only exists so we can put debugging
|
|
+# code in the run() method every now & then
|
|
+class asyncJobWorker(threading.Thread):
|
|
+ def __init__(self, callback, args):
|
|
+ threading.Thread.__init__(self, target=callback, args=args)
|
|
+
|
|
+ def run(self):
|
|
+ threading.Thread.run(self)
|
|
|
|
- def run(self):
|
|
- threading.Thread.run(self)
|
|
+# Displays a progress bar while executing the "callback" method.
|
|
+class vmmAsyncJob(gobject.GObject):
|
|
|
|
def __init__(self, config, callback, args=None,
|
|
text=_("Please wait a few moments..."),
|
|
- title=_("Operation in progress")):
|
|
+ title=_("Operation in progress"),
|
|
+ run_main=True):
|
|
self.__gobject_init__()
|
|
self.config = config
|
|
+ self.run_main = bool(run_main)
|
|
|
|
- self.window = gtk.glade.XML(config.get_glade_dir() + "/vmm-progress.glade", "vmm-progress", domain="virt-manager")
|
|
+ self.window = gtk.glade.XML(config.get_glade_dir() + \
|
|
+ "/vmm-progress.glade",
|
|
+ "vmm-progress", domain="virt-manager")
|
|
self.window.get_widget("pbar-text").set_text(text)
|
|
|
|
self.topwin = self.window.get_widget("vmm-progress")
|
|
@@ -52,20 +58,27 @@ class vmmAsyncJob(gobject.GObject):
|
|
|
|
# Callback sets this if there is an error
|
|
self._error_info = None
|
|
+ self._data = None
|
|
+
|
|
self.stage = self.window.get_widget("pbar-stage")
|
|
self.pbar = self.window.get_widget("pbar")
|
|
|
|
args.append(self)
|
|
- self.bg_thread = vmmAsyncJob.asyncJobWorker(callback, args)
|
|
+ self.bg_thread = asyncJobWorker(callback, args)
|
|
self.bg_thread.setDaemon(True)
|
|
self.is_pulsing = True
|
|
|
|
def run(self):
|
|
- timer = gobject.timeout_add (100, self.exit_if_necessary)
|
|
+ timer = gobject.timeout_add(100, self.exit_if_necessary)
|
|
self.topwin.present()
|
|
self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
|
- self.bg_thread.start()
|
|
- gtk.main()
|
|
+
|
|
+ if self.run_main:
|
|
+ self.bg_thread.start()
|
|
+ gtk.main()
|
|
+ else:
|
|
+ self.bg_thread.run()
|
|
+
|
|
gobject.source_remove(timer)
|
|
timer = 0
|
|
|
|
@@ -74,7 +87,7 @@ class vmmAsyncJob(gobject.GObject):
|
|
# async dialog is running. This forces us to clean up properly
|
|
# and not leave a dead process around.
|
|
logging.debug("Forcing main_quit from async job.")
|
|
- self._exit_if_necessary(force_exit=True)
|
|
+ self.exit_if_necessary(force_exit=True)
|
|
|
|
self.topwin.destroy()
|
|
|
|
@@ -132,6 +145,11 @@ class vmmAsyncJob(gobject.GObject):
|
|
return (None, None)
|
|
return self._error_info
|
|
|
|
+ def set_data(self, data):
|
|
+ self._data = data
|
|
+ def get_data(self):
|
|
+ return self._data
|
|
+
|
|
def exit_if_necessary(self):
|
|
gtk.gdk.threads_enter()
|
|
try:
|
|
@@ -140,11 +158,15 @@ class vmmAsyncJob(gobject.GObject):
|
|
gtk.gdk.threads_leave()
|
|
|
|
def _exit_if_necessary(self, force_exit=False):
|
|
- if self.bg_thread.isAlive() and not force_exit:
|
|
- if(self.is_pulsing):
|
|
+ thread_active = (self.bg_thread.isAlive() or not self.run_main)
|
|
+
|
|
+ if thread_active and not force_exit:
|
|
+ if (self.is_pulsing):
|
|
+ # Don't call pulse_pbar: this function is thread wrapped
|
|
self.pbar.pulse()
|
|
return True
|
|
else:
|
|
- gtk.main_quit()
|
|
+ if self.run_main:
|
|
+ gtk.main_quit()
|
|
return False
|
|
|
|
# HG changeset patch
|
|
# User Cole Robinson <crobinso@redhat.com>
|
|
# Date 1267580154 18000
|
|
# Node ID a52c2654d7db28dca4e28f2170f23fea7a727b24
|
|
# Parent da1c162094663d6ffa474d6b2a05130277ec01dc
|
|
manager: Improve startup error when no default connection.
|
|
|
|
diff -r da1c16209466 -r a52c2654d7db src/virtManager/manager.py
|
|
--- a/src/virtManager/manager.py Tue Mar 02 12:18:48 2010 -0500
|
|
+++ b/src/virtManager/manager.py Tue Mar 02 20:35:54 2010 -0500
|
|
@@ -130,7 +130,6 @@
|
|
self.engine = engine
|
|
|
|
self.delete_dialog = None
|
|
- self.startup_error = None
|
|
self.ignore_pause = False
|
|
|
|
# Mapping of VM UUID -> tree model rows to
|
|
@@ -207,13 +206,13 @@
|
|
# Select first list entry
|
|
vmlist = self.window.get_widget("vm-list")
|
|
if len(vmlist.get_model()) == 0:
|
|
- self.startup_error = _("Could not populate a default connection. "
|
|
- "Make sure the appropriate virtualization "
|
|
- "packages are installed (kvm, qemu, etc.) "
|
|
- "and that libvirtd has been restarted to "
|
|
- "notice the changes.\n\n"
|
|
- "A hypervisor connection can be manually "
|
|
- "added via \nFile->Add Connection")
|
|
+ msg = _("Could not detect a default hypervisor. Make\n"
|
|
+ "sure the appropriate virtualization packages\n"
|
|
+ "are installed (kvm, qemu, libvirt, etc.), and\n"
|
|
+ "that libvirtd is running.\n\n"
|
|
+ "A hypervisor connection can be manually added\n"
|
|
+ "via File->Add Connection")
|
|
+ self.set_startup_error(msg)
|
|
else:
|
|
vmlist.get_selection().select_iter(vmlist.get_model().get_iter_first())
|
|
|
|
@@ -229,10 +228,6 @@
|
|
|
|
self.engine.increment_window_counter()
|
|
|
|
- if self.startup_error:
|
|
- self.err.val_err(_("Error determining default hypervisor."),
|
|
- self.startup_error, _("Startup Error"))
|
|
- self.startup_error = None
|
|
|
|
def close(self, src=None, src2=None):
|
|
if self.is_visible():
|
|
@@ -246,6 +241,9 @@
|
|
return 1
|
|
return 0
|
|
|
|
+ def set_startup_error(self, msg):
|
|
+ self.window.get_widget("vm-notebook").set_current_page(1)
|
|
+ self.window.get_widget("startup-error-label").set_text(msg)
|
|
|
|
################
|
|
# Init methods #
|
|
@@ -430,6 +428,7 @@
|
|
|
|
def init_vmlist(self):
|
|
vmlist = self.window.get_widget("vm-list")
|
|
+ self.window.get_widget("vm-notebook").set_show_tabs(False)
|
|
|
|
# Handle, name, markup, status, status icon, key/uuid, hint, is conn,
|
|
# is conn connected, is vm, is vm running, fg color
|
|
@@ -905,6 +904,9 @@
|
|
return _iter
|
|
|
|
def _add_connection(self, engine, conn):
|
|
+ # Make sure error page isn't showing
|
|
+ self.window.get_widget("vm-notebook").set_current_page(0)
|
|
+
|
|
if self.rows.has_key(conn.get_uri()):
|
|
return
|
|
|
|
diff -r da1c16209466 -r a52c2654d7db src/vmm-manager.glade
|
|
--- a/src/vmm-manager.glade Tue Mar 02 12:18:48 2010 -0500
|
|
+++ b/src/vmm-manager.glade Tue Mar 02 20:35:54 2010 -0500
|
|
@@ -342,23 +342,59 @@
|
|
</packing>
|
|
</child>
|
|
<child>
|
|
- <widget class="GtkScrolledWindow" id="scrolledwindow1">
|
|
+ <widget class="GtkNotebook" id="vm-notebook">
|
|
<property name="visible">True</property>
|
|
- <property name="can_focus">False</property>
|
|
- <property name="hscrollbar_policy">automatic</property>
|
|
- <property name="vscrollbar_policy">automatic</property>
|
|
- <property name="shadow_type">in</property>
|
|
+ <property name="can_focus">True</property>
|
|
<child>
|
|
- <widget class="GtkTreeView" id="vm-list">
|
|
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
|
|
<property name="visible">True</property>
|
|
<property name="can_focus">True</property>
|
|
- <signal name="button_press_event" handler="on_vm_list_button_press_event"/>
|
|
- <signal name="row_expanded" handler="on_vm_list_row_expanded"/>
|
|
- <signal name="key_press_event" handler="on_vm_list_key_press_event"/>
|
|
- <signal name="row_collapsed" handler="on_vm_list_row_collapsed"/>
|
|
- <signal name="row_activated" handler="on_vm_list_row_activated"/>
|
|
+ <property name="hscrollbar_policy">automatic</property>
|
|
+ <property name="vscrollbar_policy">automatic</property>
|
|
+ <property name="shadow_type">in</property>
|
|
+ <child>
|
|
+ <widget class="GtkTreeView" id="vm-list">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="can_focus">True</property>
|
|
+ <signal name="button_press_event" handler="on_vm_list_button_press_event"/>
|
|
+ <signal name="row_expanded" handler="on_vm_list_row_expanded"/>
|
|
+ <signal name="key_press_event" handler="on_vm_list_key_press_event"/>
|
|
+ <signal name="row_collapsed" handler="on_vm_list_row_collapsed"/>
|
|
+ <signal name="row_activated" handler="on_vm_list_row_activated"/>
|
|
+ </widget>
|
|
+ </child>
|
|
</widget>
|
|
</child>
|
|
+ <child>
|
|
+ <widget class="GtkLabel" id="label1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label">manager</property>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="tab_fill">False</property>
|
|
+ <property name="type">tab</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+ <child>
|
|
+ <widget class="GtkLabel" id="startup-error-label">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label">error</property>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="position">1</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+ <child>
|
|
+ <widget class="GtkLabel" id="label2">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label">error</property>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="position">1</property>
|
|
+ <property name="tab_fill">False</property>
|
|
+ <property name="type">tab</property>
|
|
+ </packing>
|
|
+ </child>
|
|
</widget>
|
|
<packing>
|
|
<property name="position">1</property>
|
|
# HG changeset patch
|
|
# User Cole Robinson <crobinso@redhat.com>
|
|
# Date 1267550328 18000
|
|
# Node ID da1c162094663d6ffa474d6b2a05130277ec01dc
|
|
# Parent 7473bf514f915b537ba0d29550c6741fb5b72cac
|
|
engine: Remove redundant function
|
|
|
|
diff -r 7473bf514f91 -r da1c16209466 src/virtManager/engine.py
|
|
--- a/src/virtManager/engine.py Tue Mar 02 11:56:04 2010 -0500
|
|
+++ b/src/virtManager/engine.py Tue Mar 02 12:18:48 2010 -0500
|
|
@@ -137,9 +137,6 @@
|
|
self.connect_to_uri(uri)
|
|
|
|
def connect_to_uri(self, uri, readOnly=None, autoconnect=False):
|
|
- return self._connect_to_uri(None, uri, readOnly, autoconnect)
|
|
-
|
|
- def _connect_to_uri(self, connect, uri, readOnly, autoconnect):
|
|
self.windowConnect = None
|
|
|
|
try:
|
|
@@ -316,7 +313,7 @@
|
|
def show_connect(self):
|
|
if self.windowConnect == None:
|
|
self.windowConnect = vmmConnect(self.get_config(), self)
|
|
- self.windowConnect.connect("completed", self._connect_to_uri)
|
|
+ self.windowConnect.connect("completed", self.connect_to_uri)
|
|
self.windowConnect.connect("cancelled", self._connect_cancelled)
|
|
self.windowConnect.show()
|
|
|
|
# HG changeset patch
|
|
# User Cole Robinson <crobinso@redhat.com>
|
|
# Date 1267653530 18000
|
|
# Node ID 437cb7da4c9741ebbbf2baca7e90f3699eb2756d
|
|
# Parent 711c94d23f4c81e5997dfbeac6a30ae556b38c82
|
|
PackageKit integration for first start hypervisor detection
|
|
|
|
Check to make sure the expected local packages are installed for
|
|
the default connection (KVM).
|
|
|
|
diff -r 711c94d23f4c -r 437cb7da4c97 src/virt-manager.py.in
|
|
--- a/src/virt-manager.py.in Wed Mar 03 16:55:00 2010 -0500
|
|
+++ b/src/virt-manager.py.in Wed Mar 03 16:58:50 2010 -0500
|
|
@@ -203,17 +203,6 @@
|
|
|
|
return optParser.parse_args()
|
|
|
|
-def default_uri():
|
|
- tryuri = None
|
|
- if os.path.exists("/var/lib/xend") and os.path.exists("/proc/xen"):
|
|
- tryuri = "xen:///"
|
|
- elif (os.path.exists("/usr/bin/qemu") or
|
|
- os.path.exists("/usr/bin/qemu-kvm") or
|
|
- os.path.exists("/usr/bin/kvm")):
|
|
- tryuri = "qemu:///system"
|
|
-
|
|
- return tryuri
|
|
-
|
|
def launch_specific_window(engine, show, uri, uuid):
|
|
if not engine.wait_for_open(uri):
|
|
# Connection failed, don't attempt to continue
|
|
@@ -238,15 +227,10 @@
|
|
args=(engine, show, uri, uuid),
|
|
name="Launching '%s' window" % show)
|
|
thread.start()
|
|
+
|
|
elif show=='summary' or uri:
|
|
engine.connect_to_uri(uri)
|
|
else:
|
|
- if engine.config.get_connections() is None \
|
|
- or len(engine.config.get_connections()) == 0:
|
|
-
|
|
- tryuri = default_uri()
|
|
- if tryuri is not None:
|
|
- engine.add_connection(tryuri, autoconnect=True)
|
|
engine.show_manager()
|
|
|
|
if not no_conn_auto:
|
|
diff -r 711c94d23f4c -r 437cb7da4c97 src/virtManager/engine.py
|
|
--- a/src/virtManager/engine.py Wed Mar 03 16:55:00 2010 -0500
|
|
+++ b/src/virtManager/engine.py Wed Mar 03 16:58:50 2010 -0500
|
|
@@ -24,9 +24,11 @@
|
|
import logging
|
|
import traceback
|
|
import threading
|
|
+import os
|
|
|
|
import libvirt
|
|
import virtinst
|
|
+import dbus
|
|
|
|
from virtManager.about import vmmAbout
|
|
from virtManager.halhelper import vmmHalHelper
|
|
@@ -44,6 +46,149 @@
|
|
from virtManager.systray import vmmSystray
|
|
import virtManager.util as util
|
|
|
|
+
|
|
+# List of packages to look for via packagekit at first startup.
|
|
+# If this list is empty, no attempt to contact packagekit is made
|
|
+LIBVIRT_DAEMON = "libvirt"
|
|
+PACKAGEKIT_PACKAGES = [LIBVIRT_DAEMON, "qemu-system-x86"]
|
|
+
|
|
+
|
|
+def default_uri():
|
|
+ tryuri = None
|
|
+ if os.path.exists("/var/lib/xend") and os.path.exists("/proc/xen"):
|
|
+ tryuri = "xen:///"
|
|
+ elif (os.path.exists("/usr/bin/qemu") or
|
|
+ os.path.exists("/usr/bin/qemu-kvm") or
|
|
+ os.path.exists("/usr/bin/kvm")):
|
|
+ tryuri = "qemu:///system"
|
|
+
|
|
+ return tryuri
|
|
+
|
|
+#############################
|
|
+# PackageKit lookup helpers #
|
|
+#############################
|
|
+
|
|
+def check_packagekit(config, errbox):
|
|
+ """
|
|
+ Returns None when we determine nothing useful.
|
|
+ Returns (success, did we just install libvirt) otherwise.
|
|
+ """
|
|
+ if not PACKAGEKIT_PACKAGES:
|
|
+ return
|
|
+
|
|
+ logging.debug("Asking PackageKit what's installed locally.")
|
|
+ try:
|
|
+ session = dbus.SystemBus()
|
|
+
|
|
+ pk_control = dbus.Interface(
|
|
+ session.get_object("org.freedesktop.PackageKit",
|
|
+ "/org/freedesktop/PackageKit"),
|
|
+ "org.freedesktop.PackageKit")
|
|
+ except Exception:
|
|
+ logging.exception("Couldn't connect to packagekit")
|
|
+ return
|
|
+
|
|
+ found = []
|
|
+ progWin = vmmAsyncJob(config, _do_async_search,
|
|
+ [session, pk_control],
|
|
+ _("Searching for available hypervisors..."),
|
|
+ run_main=False)
|
|
+ progWin.run()
|
|
+ error, ignore = progWin.get_error()
|
|
+ if error:
|
|
+ return
|
|
+
|
|
+ found = progWin.get_data()
|
|
+
|
|
+ not_found = filter(lambda x: x not in found, PACKAGEKIT_PACKAGES)
|
|
+ logging.debug("Missing packages: %s" % not_found)
|
|
+
|
|
+ do_install = not_found
|
|
+ if not do_install:
|
|
+ if not not_found:
|
|
+ # Got everything we wanted, try to connect
|
|
+ logging.debug("All packages found locally.")
|
|
+ return (True, False)
|
|
+
|
|
+ else:
|
|
+ logging.debug("No packages are available for install.")
|
|
+ return
|
|
+
|
|
+ msg = (_("The following packages are not installed:\n%s\n\n"
|
|
+ "These are required to create KVM guests locally.\n"
|
|
+ "Would you like to install them now?") %
|
|
+ reduce(lambda x, y: x + "\n" + y, do_install, ""))
|
|
+
|
|
+ ret = errbox.yes_no(_("Packages required for KVM usage"), msg)
|
|
+
|
|
+ if not ret:
|
|
+ logging.debug("Package install declined.")
|
|
+ return
|
|
+
|
|
+ try:
|
|
+ packagekit_install(do_install)
|
|
+ except Exception, e:
|
|
+ errbox.show_err(_("Error talking to PackageKit: %s") % str(e),
|
|
+ "".join(traceback.format_exc()))
|
|
+ return
|
|
+
|
|
+ return (True, LIBVIRT_DAEMON in do_install)
|
|
+
|
|
+def _do_async_search(session, pk_control, asyncjob):
|
|
+ found = []
|
|
+ try:
|
|
+ for name in PACKAGEKIT_PACKAGES:
|
|
+ ret_found = packagekit_search(session, pk_control, name)
|
|
+ found += ret_found
|
|
+
|
|
+ except Exception, e:
|
|
+ logging.exception("Error searching for installed packages")
|
|
+ asyncjob.set_error(str(e), "".join(traceback.format_exc()))
|
|
+
|
|
+ asyncjob.set_data(found)
|
|
+
|
|
+def packagekit_install(package_list):
|
|
+ session = dbus.SessionBus()
|
|
+
|
|
+ pk_control = dbus.Interface(
|
|
+ session.get_object("org.freedesktop.PackageKit",
|
|
+ "/org/freedesktop/PackageKit"),
|
|
+ "org.freedesktop.PackageKit.Modify")
|
|
+
|
|
+ logging.debug("Installing packages: %s" % package_list)
|
|
+ pk_control.InstallPackageNames(0, package_list, "hide-confirm-search")
|
|
+
|
|
+def packagekit_search(session, pk_control, package_name):
|
|
+ tid = pk_control.GetTid()
|
|
+ pk_trans = dbus.Interface(
|
|
+ session.get_object("org.freedesktop.PackageKit", tid),
|
|
+ "org.freedesktop.PackageKit.Transaction")
|
|
+
|
|
+ found = []
|
|
+ def package(info, package_id, summary):
|
|
+ found_name = str(package_id.split(";")[0])
|
|
+ if found_name in PACKAGEKIT_PACKAGES:
|
|
+ found.append(found_name)
|
|
+
|
|
+ def error(code, details):
|
|
+ raise RuntimeError("PackageKit search failure: %s %s" %
|
|
+ (code, details))
|
|
+
|
|
+ def finished(ignore, runtime):
|
|
+ gtk.main_quit()
|
|
+
|
|
+ pk_trans.connect_to_signal('Finished', finished)
|
|
+ pk_trans.connect_to_signal('ErrorCode', error)
|
|
+ pk_trans.connect_to_signal('Package', package)
|
|
+ pk_trans.SearchNames("installed", [package_name])
|
|
+
|
|
+ # Call main() so this function is synchronous
|
|
+ gtk.main()
|
|
+
|
|
+ return found
|
|
+
|
|
+
|
|
+
|
|
class vmmEngine(gobject.GObject):
|
|
__gsignals__ = {
|
|
"connection-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
@@ -96,6 +241,7 @@
|
|
self.load_stored_uris()
|
|
self.tick()
|
|
|
|
+
|
|
def init_systray(self):
|
|
if self.systray:
|
|
return
|
|
@@ -123,6 +269,60 @@
|
|
self.hal_helper = vmmHalHelper()
|
|
return self.hal_helper
|
|
|
|
+
|
|
+ # First run helpers
|
|
+
|
|
+ def add_default_connection(self):
|
|
+ # Only add default if no connections are currently known
|
|
+ if self.config.get_connections():
|
|
+ return
|
|
+
|
|
+ # Manager fail message
|
|
+ msg = _("Could not detect a default hypervisor. Make\n"
|
|
+ "sure the appropriate virtualization packages\n"
|
|
+ "are installed (kvm, qemu, libvirt, etc.), and\n"
|
|
+ "that libvirtd is running.\n\n"
|
|
+ "A hypervisor connection can be manually\n"
|
|
+ "added via File->Add Connection")
|
|
+
|
|
+ manager = self.get_manager()
|
|
+ logging.debug("Determining default libvirt URI")
|
|
+
|
|
+ ret = None
|
|
+ did_install_libvirt = False
|
|
+ try:
|
|
+ ret = check_packagekit(self.config, self.err)
|
|
+ except:
|
|
+ logging.exception("Error talking to PackageKit")
|
|
+
|
|
+ if ret:
|
|
+ # We found the default packages via packagekit: use default URI
|
|
+ ignore, did_install_libvirt = ret
|
|
+ tryuri = "qemu:///system"
|
|
+
|
|
+ else:
|
|
+ tryuri = default_uri()
|
|
+
|
|
+ if tryuri is None:
|
|
+ manager.set_startup_error(msg)
|
|
+ return
|
|
+
|
|
+ if did_install_libvirt:
|
|
+ warnmsg = _(
|
|
+ "Libvirt was just installed, so the 'libvirtd' service will\n"
|
|
+ "will need to be started. This can be done with one \n"
|
|
+ "of the following:\n\n"
|
|
+ "- From GNOME menus: System->Administration->Services\n"
|
|
+ "- From the terminal: su -c 'service libvirtd restart'\n"
|
|
+ "- Restart your computer\n\n"
|
|
+ "virt-manager will connect to libvirt on the next application\n"
|
|
+ "start up.")
|
|
+ self.err.ok(_("Libvirt service must be started"), warnmsg)
|
|
+
|
|
+ self.connect_to_uri(tryuri, autoconnect=True,
|
|
+ do_start=not did_install_libvirt)
|
|
+
|
|
+
|
|
def load_stored_uris(self):
|
|
uris = self.config.get_connections()
|
|
if uris != None:
|
|
@@ -136,7 +336,8 @@
|
|
if conn.get_autoconnect():
|
|
self.connect_to_uri(uri)
|
|
|
|
- def connect_to_uri(self, uri, readOnly=None, autoconnect=False):
|
|
+ def connect_to_uri(self, uri, readOnly=None, autoconnect=False,
|
|
+ do_start=True):
|
|
self.windowConnect = None
|
|
|
|
try:
|
|
@@ -146,7 +347,8 @@
|
|
conn = self.add_connection(uri, readOnly, autoconnect)
|
|
|
|
self.show_manager()
|
|
- conn.open()
|
|
+ if do_start:
|
|
+ conn.open()
|
|
return conn
|
|
except Exception:
|
|
return None
|
|
diff -r 711c94d23f4c -r 437cb7da4c97 src/virtManager/error.py
|
|
--- a/src/virtManager/error.py Wed Mar 03 16:55:00 2010 -0500
|
|
+++ b/src/virtManager/error.py Wed Mar 03 16:58:50 2010 -0500
|
|
@@ -145,6 +145,9 @@
|
|
def ok_cancel(self, text1, text2=None):
|
|
return self._show_warning(gtk.BUTTONS_OK_CANCEL, text1, text2)
|
|
|
|
+ def ok(self, text1, text2=None):
|
|
+ return self._show_warning(gtk.BUTTONS_OK, text1, text2)
|
|
+
|
|
def warn_chkbox(self, text1, text2=None, chktext=None, buttons=None):
|
|
chkbox = vmmCheckDialog(self.get_transient_for(),
|
|
gtk.MESSAGE_WARNING, buttons)
|
|
diff -r 711c94d23f4c -r 437cb7da4c97 src/virtManager/manager.py
|
|
--- a/src/virtManager/manager.py Wed Mar 03 16:55:00 2010 -0500
|
|
+++ b/src/virtManager/manager.py Wed Mar 03 16:58:50 2010 -0500
|
|
@@ -21,6 +21,7 @@
|
|
import gobject
|
|
import gtk
|
|
import gtk.glade
|
|
+
|
|
import logging
|
|
import traceback
|
|
|
|
@@ -205,16 +206,12 @@
|
|
|
|
# Select first list entry
|
|
vmlist = self.window.get_widget("vm-list")
|
|
- if len(vmlist.get_model()) == 0:
|
|
- msg = _("Could not detect a default hypervisor. Make\n"
|
|
- "sure the appropriate virtualization packages\n"
|
|
- "are installed (kvm, qemu, libvirt, etc.), and\n"
|
|
- "that libvirtd is running.\n\n"
|
|
- "A hypervisor connection can be manually added\n"
|
|
- "via File->Add Connection")
|
|
- self.set_startup_error(msg)
|
|
- else:
|
|
- vmlist.get_selection().select_iter(vmlist.get_model().get_iter_first())
|
|
+ if len(vmlist.get_model()) != 0:
|
|
+ vmlist.get_selection().select_iter(
|
|
+ vmlist.get_model().get_iter_first())
|
|
+
|
|
+ # Queue up the default connection detector
|
|
+ gobject.idle_add(self.engine.add_default_connection)
|
|
|
|
##################
|
|
# Common methods #
|
|
@@ -228,7 +225,6 @@
|
|
|
|
self.engine.increment_window_counter()
|
|
|
|
-
|
|
def close(self, src=None, src2=None):
|
|
if self.is_visible():
|
|
win = self.window.get_widget("vmm-manager")
|