virt-manager/virtManager/packageutils.py

248 lines
8.1 KiB
Python
Raw Normal View History

#
# Copyright (C) 2012 Red Hat, Inc.
# Copyright (C) 2012 Cole Robinson <crobinso@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
# pylint: disable=E0611
from gi.repository import Gio
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 17:24:56 +04:00
from gi.repository import Gtk
# pylint: enable=E0611
import logging
import time
import traceback
from virtManager.asyncjob import vmmAsyncJob
#############################
# PackageKit lookup helpers #
#############################
def check_packagekit(errbox, packages, ishv):
"""
Returns None when we determine nothing useful.
Returns (success, did we just install libvirt) otherwise.
"""
if not packages:
logging.debug("No PackageKit packages to search for.")
return
logging.debug("Asking PackageKit what's installed locally.")
try:
bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
pk_control = Gio.DBusProxy.new_sync(bus, 0, None,
"org.freedesktop.PackageKit",
"/org/freedesktop/PackageKit",
"org.freedesktop.PackageKit", None)
except Exception:
logging.exception("Couldn't connect to packagekit")
return
if ishv:
msg = _("Searching for available hypervisors...")
else:
msg = _("Checking for installed package '%s'") % packages[0]
cancellable = Gio.Cancellable()
progWin = vmmAsyncJob(_do_async_search,
[bus, pk_control, packages, cancellable], msg, msg,
errbox.get_parent(), async=False,
cancel_cb=[_cancel_search, cancellable])
error, ignore = progWin.run()
if error:
return
found = progWin.get_extra_data()
not_found = [x for x in packages if x not in found]
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 []
else:
logging.debug("No packages are available for install.")
return
missing = reduce(lambda x, y: x + "\n" + y, do_install, "")
if ishv:
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?") % missing)
title = _("Packages required for KVM usage")
else:
msg = _("The following packages are not installed:\n%s\n\n"
"Would you like to install them now?" % missing)
title = _("Recommended package installs")
ret = errbox.yes_no(title, 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))
return
return do_install
def _cancel_search(asyncjob, cancellable):
cancellable.cancel()
asyncjob.job_cancelled = True
def _do_async_search(asyncjob, bus, pk_control, packages, cancellable):
found = []
try:
for name in packages:
ret_found = packagekit_search(bus, pk_control, name, packages,
cancellable)
found += ret_found
except Exception, e:
if cancellable.is_cancelled():
logging.debug("Package search cancelled by user")
asyncjob.set_error("Package search cancelled by user")
else:
logging.exception("Error searching for installed packages")
asyncjob.set_error(str(e), "".join(traceback.format_exc()))
asyncjob.set_extra_data(found)
def packagekit_install(package_list):
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
pk_control = Gio.DBusProxy.new_sync(bus, 0, None,
"org.freedesktop.PackageKit",
"/org/freedesktop/PackageKit",
"org.freedesktop.PackageKit.Modify", None)
# Set 2 hour timeout
timeout = 1000 * 60 * 60 * 2
logging.debug("Installing packages: %s", package_list)
pk_control.InstallPackageNames("(uass)", 0,
package_list, "hide-confirm-search",
timeout=timeout)
def packagekit_search(bus, pk_control, package_name, packages, cancellable):
tid = pk_control.CreateTransaction()
pk_trans = Gio.DBusProxy.new_sync(bus, 0, None,
"org.freedesktop.PackageKit", tid,
"org.freedesktop.PackageKit.Transaction",
cancellable)
found = []
def package(info, package_id, summary):
ignore = info
ignore = summary
found_name = str(package_id.split(";")[0])
if found_name in packages:
found.append(found_name)
def error(code, details):
raise RuntimeError("PackageKit search failure: %s %s" %
(code, details))
def finished(ignore, runtime_ignore):
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 17:24:56 +04:00
Gtk.main_quit()
def signal_cb(proxy, sender, signal, args):
ignore = proxy
sender = proxy
if signal == "Finished":
finished(*args)
elif signal == "ErrorCode":
error(*args)
elif signal == "Package":
package(*args)
pk_trans.connect("g-signal", signal_cb)
pk_trans.SearchNames("(tas)", 2 ** 2, [package_name])
# Call main() so this function is synchronous
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 17:24:56 +04:00
Gtk.main()
return found
###################
# Service helpers #
###################
def start_libvirtd():
"""
Connect to systemd and start libvirtd if required
"""
logging.debug("Trying to start libvirtd through systemd")
unitname = "libvirtd.service"
try:
bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
except:
logging.exception("Error getting system bus handle")
return
try:
systemd = Gio.DBusProxy.new_sync(bus, 0, None,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager", None)
except:
logging.exception("Couldn't connect to systemd")
return
try:
unitpath = systemd.GetUnit("(s)", unitname)
unit = Gio.DBusProxy.new_sync(bus, 0, None,
"org.freedesktop.systemd1", unitpath,
"org.freedesktop.systemd1.Unit", None)
state = unit.get_cached_property("ActiveState")
logging.debug("libvirtd state=%s", state)
if str(state).lower().strip("'") == "active":
logging.debug("libvirtd already active, not starting")
return True
except:
logging.exception("Failed to lookup libvirtd status")
return
# Connect to system-config-services and offer to start
try:
logging.debug("libvirtd not running, asking system-config-services "
"to start it")
scs = Gio.DBusProxy.new_sync(bus, 0, None,
"org.fedoraproject.Config.Services",
"/org/fedoraproject/Config/Services/systemd1",
"org.freedesktop.systemd1.Manager", None)
scs.StartUnit("(ss)", unitname, "replace")
time.sleep(2)
logging.debug("Starting libvirtd appeared to succeed")
return True
except:
logging.exception("Failed to talk to system-config-services")