PackageKit integration for first start hypervisor detection
Check to make sure the expected local packages are installed for the default connection (KVM).
This commit is contained in:
parent
51dd50d254
commit
d24ce72160
|
@ -203,17 +203,6 @@ def parse_commandline():
|
|||
|
||||
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 @@ def show_engine(engine, show, uri, uuid, no_conn_auto):
|
|||
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:
|
||||
|
|
|
@ -24,9 +24,11 @@ import gtk
|
|||
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.error import vmmErrorDialog
|
|||
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 @@ class vmmEngine(gobject.GObject):
|
|||
self.load_stored_uris()
|
||||
self.tick()
|
||||
|
||||
|
||||
def init_systray(self):
|
||||
if self.systray:
|
||||
return
|
||||
|
@ -123,6 +269,60 @@ class vmmEngine(gobject.GObject):
|
|||
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 @@ class vmmEngine(gobject.GObject):
|
|||
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 @@ class vmmEngine(gobject.GObject):
|
|||
conn = self.add_connection(uri, readOnly, autoconnect)
|
||||
|
||||
self.show_manager()
|
||||
conn.open()
|
||||
if do_start:
|
||||
conn.open()
|
||||
return conn
|
||||
except Exception:
|
||||
return None
|
||||
|
|
|
@ -145,6 +145,9 @@ class vmmErrorDialog (gtk.MessageDialog):
|
|||
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)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
import gobject
|
||||
import gtk
|
||||
import gtk.glade
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
|
@ -205,16 +206,12 @@ class vmmManager(gobject.GObject):
|
|||
|
||||
# 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
|
||||
util.safe_idle_add(self.engine.add_default_connection)
|
||||
|
||||
##################
|
||||
# Common methods #
|
||||
|
@ -228,7 +225,6 @@ class vmmManager(gobject.GObject):
|
|||
|
||||
self.engine.increment_window_counter()
|
||||
|
||||
|
||||
def close(self, src=None, src2=None):
|
||||
if self.is_visible():
|
||||
win = self.window.get_widget("vmm-manager")
|
||||
|
|
Loading…
Reference in New Issue