From bbc65216dbc9385f65850956dd854cf9e3ba8251 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Thu, 2 Jul 2009 12:43:08 -0400 Subject: [PATCH] Refactor OpticalHelper functionality. Add helper functions to properly set up the cdrom combo widgets. Separate the dbus polling from UI editting: eventually we will get some of this info from libvirt hostdev APIs, and this will help. --- src/virtManager/choosecd.py | 38 +++--- src/virtManager/create.py | 13 +- src/virtManager/opticalhelper.py | 197 ++++++++++++++++++++----------- 3 files changed, 149 insertions(+), 99 deletions(-) diff --git a/src/virtManager/choosecd.py b/src/virtManager/choosecd.py index 42aee6da..7aefd553 100644 --- a/src/virtManager/choosecd.py +++ b/src/virtManager/choosecd.py @@ -23,7 +23,7 @@ import logging import virtinst -from virtManager.opticalhelper import vmmOpticalDriveHelper +import virtManager.opticalhelper from virtManager.storagebrowse import vmmStorageBrowser from virtManager.error import vmmErrorDialog @@ -58,17 +58,7 @@ class vmmChooseCD(gobject.GObject): self.window.get_widget("iso-image").set_active(True) - # set up the list for the cd-path widget - cd_list = self.window.get_widget("cd-path") - # Fields are raw device path, volume label, flag indicating - # whether volume is present or not, and HAL path - cd_model = gtk.ListStore(str, str, bool, str) - cd_list.set_model(cd_model) - text = gtk.CellRendererText() - cd_list.pack_start(text, True) - cd_list.add_attribute(text, 'text', 1) - cd_list.add_attribute(text, 'sensitive', 2) - + self.initialize_opt_media() self.reset_state() def close(self,ignore1=None,ignore2=None): @@ -92,35 +82,37 @@ class vmmChooseCD(gobject.GObject): else: self.window.get_widget("physical-media").set_sensitive(True) self.window.get_widget("iso-file-chooser").set_sensitive(True) - self.populate_opt_media() - self.window.get_widget("cd-path").set_active(0) def ok(self,ignore1=None, ignore2=None): + path = None + if self.window.get_widget("iso-image").get_active(): path = self.window.get_widget("iso-path").get_text() else: cd = self.window.get_widget("cd-path") + idx = cd.get_active() model = cd.get_model() - path = model.get_value(cd.get_active_iter(), 0) + if idx != -1: + path = model[idx][virtManager.opticalhelper.OPTICAL_PATH] - if path == "" or path == None: - return self.err.val_err(_("Invalid Media Path"), \ + if path == "" or path == None: + return self.err.val_err(_("Invalid Media Path"), _("A media path must be specified.")) try: + dev=virtinst.VirtualDisk.DEVICE_CDROM disk = virtinst.VirtualDisk(path=path, - device=virtinst.VirtualDisk.DEVICE_CDROM, + device=dev, readOnly=True, conn=self.conn.vmm) except Exception, e: return self.err.val_err(_("Invalid Media Path"), str(e)) + self.emit("cdrom-chosen", disk.type, disk.path, self.dev_id_info) self.cancel() def media_toggled(self, ignore1=None, ignore2=None): if self.window.get_widget("physical-media").get_active(): - self.populate_opt_media() - self.window.get_widget("cd-path").set_active(0) self.window.get_widget("cd-path").set_sensitive(True) self.window.get_widget("iso-path").set_sensitive(False) self.window.get_widget("iso-file-chooser").set_sensitive(False) @@ -135,10 +127,10 @@ class vmmChooseCD(gobject.GObject): def browse_fv_iso_location(self, ignore1=None, ignore2=None): self._browse_file(_("Locate ISO Image")) - def populate_opt_media(self): + def initialize_opt_media(self): try: - optical_helper = vmmOpticalDriveHelper(self.window.get_widget("cd-path")) - optical_helper.populate_opt_media() + widget = self.window.get_widget("cd-path") + virtManager.opticalhelper.init_optical_combo(widget) self.window.get_widget("physical-media").set_sensitive(True) except Exception, e: logging.error("Unable to create optical-helper widget: '%s'", e) diff --git a/src/virtManager/create.py b/src/virtManager/create.py index 0faec923..c8752bf7 100644 --- a/src/virtManager/create.py +++ b/src/virtManager/create.py @@ -31,11 +31,11 @@ import logging import virtinst from virtinst import VirtualNetworkInterface +import virtManager.opticalhelper from virtManager import util from virtManager.error import vmmErrorDialog from virtManager.asyncjob import vmmAsyncJob from virtManager.createmeter import vmmCreateMeter -from virtManager.opticalhelper import vmmOpticalDriveHelper from virtManager.storagebrowse import vmmStorageBrowser OS_GENERIC = "generic" @@ -220,17 +220,10 @@ class vmmCreate(gobject.GObject): # Physical CD-ROM model cd_list = self.window.get_widget("install-local-cdrom-combo") cd_radio = self.window.get_widget("install-local-cdrom") - # Fields are raw device path, volume label, flag indicating - # whether volume is present or not, and HAL path - cd_model = gtk.ListStore(str, str, bool, str) - cd_list.set_model(cd_model) - text = gtk.CellRendererText() - cd_list.pack_start(text, True) - cd_list.add_attribute(text, 'text', 1) - cd_list.add_attribute(text, 'sensitive', 2) + # FIXME: We should disable all this if on a remote connection try: - vmmOpticalDriveHelper(cd_list) + virtManager.opticalhelper.init_optical_combo(cd_list) except Exception, e: logging.error("Unable to create optical-helper widget: '%s'", e) cd_radio.set_sensitive(False) diff --git a/src/virtManager/opticalhelper.py b/src/virtManager/opticalhelper.py index 507dbee3..b0e6fd16 100644 --- a/src/virtManager/opticalhelper.py +++ b/src/virtManager/opticalhelper.py @@ -20,38 +20,140 @@ import gobject import dbus import logging +import gtk + +OPTICAL_PATH = 0 +OPTICAL_LABEL = 1 +OPTICAL_IS_MEDIA_PRESENT = 2 +OPTICAL_HAL_PATH = 3 + +def init_optical_combo(widget, empty_sensitive=False): + # These fields should match up with vmmOpticalHelper.device_info + model = gtk.ListStore(str, str, bool, str) + widget.set_model(model) + model.clear() + + text = gtk.CellRendererText() + widget.pack_start(text, True) + widget.add_attribute(text, 'text', 1) + if not empty_sensitive: + widget.add_attribute(text, 'sensitive', 2) + + helper = vmmOpticalDriveHelper() + helper.connect("optical-added", optical_added, widget) + helper.connect("optical-removed", optical_removed, widget) + for row in helper.get_device_info(): + model.append(row) + + widget.set_active(-1) + set_default_selection(widget) + +def optical_removed(ignore_helper, halpath, widget): + model = widget.get_model() + active = widget.get_active() + idx = 0 + # Search for the row containing matching HAL volume path + # and update (clear) it, de-activating it if its currently + # selected + for row in model: + if row[OPTICAL_HAL_PATH] == halpath: + row[OPTICAL_LABEL] = display_label(row[OPTICAL_PATH], None) + row[OPTICAL_IS_MEDIA_PRESENT] = False + row[OPTICAL_HAL_PATH] = None + if idx == active: + widget.set_active(-1) + idx = idx + 1 + + set_default_selection(widget) + +def optical_added(ignore_helper, newrow, widget): + model = widget.get_model() + active = widget.get_active() + idx = 0 + + # Search for the row with matching device node and + # fill in info about inserted media. If model has no current + # selection, select the new media. + for row in model: + if row[OPTICAL_PATH] == newrow[OPTICAL_PATH]: + for i in range(0, len(row)): + row[i] = newrow[i] + if active == -1: + widget.set_active(idx) + idx = idx + 1 + +def set_default_selection(widget): + # Set the first active cdrom device as selected, otherwise none + model = widget.get_model() + idx = 0 + active = widget.get_active() + + if active != -1: + # already a selection, don't change it + return + + for row in model: + if row[OPTICAL_IS_MEDIA_PRESENT] == True: + widget.set_active(idx) + return + idx += 1 + + widget.set_active(-1) + +def display_label(devnode, media_label): + if not media_label: + media_label = _("No media present") + return "%s (%s)" % (media_label, devnode) class vmmOpticalDriveHelper(gobject.GObject): - __gsignals__ = {} + __gsignals__ = { + "optical-added" : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + [object]), + "optical-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + [str]), + } - def __init__(self, widget): + + def __init__(self): self.__gobject_init__() - self.widget = widget - self.model = self.widget.get_model() + + self.bus = None + self.hal_iface = None + + # List of lists, containing all relevant device info. Sublist is: + # [ HAL device name, + # Pretty label to show, + # Is media present?, + # Filesystem path, e.g. /dev/sr0 ] + self.device_info = [] + + self._dbus_connect() + self.populate_opt_media() + + def get_device_info(self): + return self.device_info + + def _dbus_connect(self): try: - # Get a connection to the SYSTEM bus self.bus = dbus.SystemBus() - # Get a handle to the HAL service hal_object = self.bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') self.hal_iface = dbus.Interface(hal_object, 'org.freedesktop.Hal.Manager') - self.populate_opt_media() except Exception, e: logging.error("Unable to connect to HAL to list cdrom " "volumes: '%s'", e) - self.bus = None - self.hal_iface = None raise - def populate_opt_media(self): - # get a list of optical devices with data discs in, for FV installs - volinfo = {} - self.model.clear() # Track device add/removes so we can detect newly inserted CD media self.hal_iface.connect_to_signal("DeviceAdded", self._device_added) self.hal_iface.connect_to_signal("DeviceRemoved", self._device_removed) + + def populate_opt_media(self): + volinfo = {} + self.device_info = [] + # Find info about all current present media for path in self.hal_iface.FindDeviceByCapability("volume"): label, devnode = self._fetch_device_info(path) @@ -75,70 +177,33 @@ class vmmOpticalDriveHelper(gobject.GObject): label, path = None, None present = False - self.model.append([devnode, self._display_label(devnode, label), - present, path]) + row = [] + row.insert(OPTICAL_PATH, str(devnode)) + row.insert(OPTICAL_LABEL, display_label(devnode, label)) + row.insert(OPTICAL_IS_MEDIA_PRESENT, present) + row.insert(OPTICAL_HAL_PATH, str(path)) - self.set_default_selection() - - def set_default_selection(self): - # Set the first active cdrom device as selected, otherwise none - idx = 0 - active = self.widget.get_active() - - if active != -1: - # already a selection, don't change it - return - - for row in self.model: - if row[2] == True: - self.widget.set_active(idx) - return - idx += 1 - - self.widget.set_active(-1) + self.device_info.append(row) def _device_added(self, path): - active = self.widget.get_active() - idx = 0 label, devnode = self._fetch_device_info(path) if not devnode: # Not an applicable device return - # Search for the row with matching device node and - # fill in info about inserted media. If model has no current - # selection, select the new media. - for row in self.model: - if row[0] == devnode: - row[1] = self._display_label(devnode, label) - row[2] = True - row[3] = path - if active == -1: - self.widget.set_active(idx) - idx = idx + 1 + row = [] + row.insert(OPTICAL_PATH, str(devnode)) + row.insert(OPTICAL_LABEL, display_label(devnode, label)) + row.insert(OPTICAL_IS_MEDIA_PRESENT, True) + row.insert(OPTICAL_HAL_PATH, str(path)) + + logging.debug("Optical device added: %s" % row) + self.emit("optical-added", row) def _device_removed(self, path): - active = self.widget.get_active() - idx = 0 - # Search for the row containing matching HAL volume path - # and update (clear) it, de-activating it if its currently - # selected - for row in self.model: - if row[3] == path: - row[1] = self._display_label(row[0], None) - row[2] = False - row[3] = None - if idx == active: - self.widget.set_active(-1) - idx = idx + 1 - - self.set_default_selection() - - def _display_label(self, devnode, label): - if not label: - label = _("No media present") - return "%s (%s)" % (label, devnode) + logging.debug("Optical device removed: %s" % path) + self.emit("optical-removed", path) def _fetch_device_info(self, path): label = None