Allow using node device APIs for CDROM enumeration.

One piece of info libvirt doesn't provide for us in the media label name,
other than that we have feature parity.
This commit is contained in:
Cole Robinson 2009-11-30 16:16:43 -05:00
parent 5d9d6a6fc4
commit 51c9dce24b
4 changed files with 144 additions and 24 deletions

View File

@ -36,6 +36,7 @@ from virtManager.network import vmmNetwork
from virtManager.storagepool import vmmStoragePool
from virtManager.interface import vmmInterface
from virtManager.netdev import vmmNetDevice
from virtManager.mediadev import vmmMediaDevice
class vmmConnection(gobject.GObject):
__gsignals__ = {
@ -148,6 +149,7 @@ class vmmConnection(gobject.GObject):
self.optical_initialized = False
self.optical_error = ""
self.optical_use_libvirt = False
#################
# Init routines #
@ -205,7 +207,16 @@ class vmmConnection(gobject.GObject):
logging.debug("Using HAL for netdev enumeration")
def _init_optical(self):
if self.get_hal_helper():
if self.is_nodedev_capable():
try:
self.connect("nodedev-added", self._nodedev_optical_added)
self.connect("nodedev-removed", self._nodedev_optical_removed)
self.optical_use_libvirt = True
except Exception, e:
self.optical_error = _("Could build optical interface "
"list via libvirt: %s") % str(e)
elif self.get_hal_helper():
hal_helper = self.get_hal_helper()
if self.is_remote():
@ -228,6 +239,9 @@ class vmmConnection(gobject.GObject):
self.optical_initialized = True
if self.optical_error:
logging.debug(self.optical_error)
else:
if self.optical_use_libvirt:
logging.debug("Using libvirt API for optical enumeration")
else:
logging.debug("Using HAL for optical enumeration")
@ -289,6 +303,9 @@ class vmmConnection(gobject.GObject):
elif name == "optical-added":
for dev in self.opticaldevs.values():
self.emit("optical-added", dev)
elif name == "nodedev-added":
for key in self.nodedevs.keys():
self.emit("nodedev-added", self.get_uri(), key)
return handle_id
@ -558,6 +575,8 @@ class vmmConnection(gobject.GObject):
return self.pools[uuid]
def get_interface(self, name):
return self.interfaces[name]
def get_nodedev(self, name):
return self.nodedevs[name]
def get_devices(self, devtype=None, devcap=None):
retdevs = []
for vdev in self.nodedevs.values():
@ -645,6 +664,13 @@ class vmmConnection(gobject.GObject):
# Update listeners #
####################
def _remove_optical(self, key):
del(self.opticaldevs[key])
self.emit("optical-removed", key)
def _add_optical(self, key, dev):
self.opticaldevs[key] = dev
self.emit("optical-added", dev)
def _haldev_removed(self, ignore, hal_path):
# Physical net device
for name, obj in self.netdevs.items():
@ -653,10 +679,8 @@ class vmmConnection(gobject.GObject):
return
for key, obj in self.opticaldevs.items():
if obj.get_key() == hal_path:
del(self.opticaldevs[key])
print "optical-removed %s" % hal_path
self.emit("optical-removed", hal_path)
if key == hal_path:
self._remove_optical(key)
def _netdev_added(self, ignore, netdev):
name = netdev.get_name()
@ -670,8 +694,24 @@ class vmmConnection(gobject.GObject):
if self.opticaldevs.has_key(key):
return
self.opticaldevs[key] = dev
self.emit("optical-added", dev)
self._add_optical(key, dev)
def _nodedev_optical_added(self, ignore1, ignore2, name):
if self.opticaldevs.has_key(name):
return
vobj = self.get_nodedev(name)
mediadev = vmmMediaDevice.mediadev_from_nodedev(self, vobj)
if not mediadev:
return
self._add_optical(name, mediadev)
def _nodedev_optical_removed(self, ignore1, ignore2, name):
if not self.opticaldevs.has_key(name):
return
self._remove_optical(name)
######################################
# Connection closing/opening methods #

View File

@ -164,7 +164,8 @@ class vmmHalHelper(gobject.GObject):
self.emit("device-removed", str(path))
def add_optical_dev(self, devpath, halpath, media_label, media_hal_path):
obj = vmmMediaDevice(devpath, halpath, media_label, media_hal_path)
obj = vmmMediaDevice(devpath, halpath, bool(media_label),
media_label, media_hal_path)
obj.set_hal_media_signals(self)
self.emit("optical-added", obj)

View File

@ -19,6 +19,11 @@
#
import gobject
import logging
import virtinst
MEDIA_TIMEOUT = 3
class vmmMediaDevice(gobject.GObject):
__gsignals__ = {
@ -28,14 +33,40 @@ class vmmMediaDevice(gobject.GObject):
gobject.TYPE_NONE, []),
}
def __init__(self, path, key, media_label, media_key):
@staticmethod
def mediadev_from_nodedev(conn, nodedev):
if nodedev.device_type != "storage":
return None
if nodedev.drive_type != "cdrom":
return None
path = nodedev.block
key = nodedev.name
has_media = nodedev.media_available
media_label = None
media_key = None
nodedev_obj = conn.vmm.nodeDeviceLookupByName(key)
obj = vmmMediaDevice(path, key, has_media, media_label, media_key,
nodedev_obj)
obj.enable_poll_for_media()
return obj
def __init__(self, path, key, has_media, media_label, media_key,
nodedev_obj = None):
self.__gobject_init__()
self.path = path
self.key = key
self._has_media = has_media
self.media_label = media_label
self.media_key = media_key
self.nodedev_obj = nodedev_obj
self.poll_signal = None
def get_path(self):
return self.path
@ -43,23 +74,27 @@ class vmmMediaDevice(gobject.GObject):
return self.key
def has_media(self):
return self.has_media
return self._has_media
def get_media_label(self):
return self.media_label
def get_media_key(self):
return self.media_key
def set_media(self, media_label, media_key):
def set_media(self, has_media, media_label, media_key):
self._has_media = has_media
self.media_label = media_label
self.media_key = media_key
def clear_media(self):
self.set_media(None, None)
self.set_media(None, None, None)
def pretty_label(self):
media_label = self.get_media_label()
if not media_label:
has_media = self.has_media()
if not has_media:
media_label = _("No media present")
else:
media_label = _("Media Unknown")
return "%s (%s)" % (media_label, self.get_path())
@ -75,7 +110,7 @@ class vmmMediaDevice(gobject.GObject):
if devpath != self.get_path():
return
self.set_media(media_label, media_key)
self.set_media(True, media_label, media_key)
self.emit("media-added")
def hal_media_removed(self, ignore, media_hal_path):
@ -86,4 +121,46 @@ class vmmMediaDevice(gobject.GObject):
self.emit("media-removed")
#########################################
# Nodedev API polling for media updates #
#########################################
def enable_poll_for_media(self):
if self.poll_signal:
return
self.poll_signal = gobject.timeout_add(MEDIA_TIMEOUT * 1000,
self._poll_for_media)
def disable_poll_for_media(self):
self.poll_signal = None
def _poll_for_media(self):
if not self.poll_signal:
return False
if not self.nodedev_obj:
return False
try:
xml = self.nodedev_obj.XMLDesc(0)
except:
# Assume the device was removed
return False
try:
vobj = virtinst.NodeDeviceParser.parse(xml)
has_media = vobj.media_available
except:
logging.exception("Node device CDROM polling failed")
return False
if has_media != self.has_media():
self.set_media(has_media, None, None)
if has_media:
self.emit("media-added")
else:
self.emit("media-removed")
return True
gobject.type_register(vmmMediaDevice)

View File

@ -32,7 +32,6 @@ OPTICAL_LABEL = 1
OPTICAL_IS_MEDIA_PRESENT = 2
OPTICAL_DEV_KEY = 3
OPTICAL_MEDIA_KEY = 4
OPTICAL_MEDIADEV = 5
##############################################################
# Initialize an error object to use for validation functions #
@ -253,7 +252,7 @@ def generate_macaddr(conn):
def init_optical_combo(widget, empty_sensitive=False):
# [Device path, pretty label, has_media?, device key, media key,
# vmmMediaDevice]
model = gtk.ListStore(str, str, bool, str, str, object)
model = gtk.ListStore(str, str, bool, str, str)
widget.set_model(model)
model.clear()
@ -276,11 +275,10 @@ def populate_optical_combo(conn, widget):
return sigs
def set_row_from_object(row):
obj = row[OPTICAL_MEDIADEV]
def set_row_from_object(row, obj):
row[OPTICAL_DEV_PATH] = obj.get_path()
row[OPTICAL_LABEL] = obj.pretty_label()
row[OPTICAL_IS_MEDIA_PRESENT] = bool(obj.get_media_label())
row[OPTICAL_IS_MEDIA_PRESENT] = obj.has_media()
row[OPTICAL_DEV_KEY] = obj.get_key()
row[OPTICAL_MEDIA_KEY] = obj.get_media_key()
@ -310,10 +308,12 @@ def optical_added(ignore_helper, newobj, widget):
newobj.connect("media-removed", optical_media_changed, widget)
# Brand new device
row = [None, None, None, None, None, newobj]
set_row_from_object(row)
row = [None, None, None, None, None]
set_row_from_object(row, newobj)
model.append(row)
optical_set_default_selection(widget)
def optical_media_changed(newobj, widget):
model = widget.get_model()
active = widget.get_active()
@ -324,7 +324,7 @@ def optical_media_changed(newobj, widget):
# selection, select the new media.
for row in model:
if row[OPTICAL_DEV_PATH] == newobj.get_path():
set_row_from_object(row)
set_row_from_object(row, newobj)
has_media = row[OPTICAL_IS_MEDIA_PRESENT]
if has_media and active == -1:
@ -334,6 +334,8 @@ def optical_media_changed(newobj, widget):
idx = idx + 1
optical_set_default_selection(widget)
def optical_set_default_selection(widget):
# Set the first active cdrom device as selected, otherwise none
model = widget.get_model()