virt-manager/virt-manager-0.8.3-check-packagekit.patch
Cole Robinson a6a15d4ac1 Fix using a manual 'default' pool (bz 557020) Don't force grab focus when
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)
2010-03-22 15:34:19 +00:00

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