[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
[et-mgmt-tools] [PATCH] virt-manager: Support serial and parallel devices in 'Add Hardware'
- From: Cole Robinson <crobinso redhat com>
- To: Fedora/Linux Management Tools <et-mgmt-tools redhat com>
- Subject: [et-mgmt-tools] [PATCH] virt-manager: Support serial and parallel devices in 'Add Hardware'
- Date: Thu, 09 Jul 2009 15:27:00 -0400
The attached patch implements attaching serial and parallel devices via the
'Add Hardware' wizard in virt-manager. A couple screenshots:
http://fedorapeople.org/~crobinso/virt-manager/vmm-add-char1.png
http://fedorapeople.org/~crobinso/virt-manager/vmm-add-char2.png
The options change quite a bit depending on which device type is selected: the
associated fields and activated accordingly. The box on the right provides
some documentation about the selected field. I snipped the actual UI diff from
the patch since it is pretty large.
Questions or comments appreciated.
- Cole
# HG changeset patch
# User Cole Robinson <crobinso redhat com>
# Date 1247164914 14400
# Node ID 6ba8a10d6f8f446464f2de4b566813c35c443c10
# Parent a39662e0da71d8108a767ca6f69f7d4ee3013d6d
Support adding serial and parallel devices via 'Add Hardware'
diff -r a39662e0da71 -r 6ba8a10d6f8f src/virtManager/addhardware.py
--- a/src/virtManager/addhardware.py Thu Jul 09 14:35:55 2009 -0400
+++ b/src/virtManager/addhardware.py Thu Jul 09 14:41:54 2009 -0400
@@ -18,14 +18,17 @@
# MA 02110-1301 USA.
#
+import os
+import logging
+import traceback
+
import gobject
import gtk
import gtk.gdk
import gtk.glade
+
import virtinst
-import os
-import logging
-import traceback
+from virtinst import VirtualCharDevice, VirtualDevice
import virtManager.util as vmmutil
from virtManager.asyncjob import vmmAsyncJob
@@ -45,7 +48,18 @@
PAGE_GRAPHICS = 4
PAGE_SOUND = 5
PAGE_HOSTDEV = 6
-PAGE_SUMMARY = 7
+PAGE_CHAR = 7
+PAGE_SUMMARY = 8
+
+char_widget_mappings = {
+ "source_path" : "char-path",
+ "source_mode" : "char-mode",
+ "source_host" : "char-host",
+ "source_port" : "char-port",
+ "bind_port": "char-bind-port",
+ "bind_host": "char-bind-host",
+ "protocol" : "char-use-telnet",
+}
class vmmAddHardware(gobject.GObject):
__gsignals__ = {
@@ -56,7 +70,6 @@
self.__gobject_init__()
self.config = config
self.vm = vm
- self._dev = None
self.window = gtk.glade.XML(config.get_glade_dir() + "/vmm-add-hardware.glade", "vmm-add-hardware", domain="virt-manager")
self.topwin = self.window.get_widget("vmm-add-hardware")
self.err = vmmErrorDialog(self.topwin,
@@ -67,6 +80,8 @@
self.storage_browser = None
self._browse_cb_id = None
+ self._dev = None
+
self.topwin.hide()
self.window.signal_autoconnect({
"on_create_pages_switch_page" : self.page_changed,
@@ -85,11 +100,42 @@
"on_graphics_port_auto_toggled": self.change_port_auto,
"on_graphics_keymap_toggled": self.change_keymap,
"on_host_device_type_changed": self.change_host_device_type,
+ "on_char_device_type_changed": self.change_char_device_type,
"on_create_help_clicked": self.show_help,
+
+ # Char dev info signals
+ "char_device_type_focus": (self.update_doc, "char_type"),
+ "char_path_focus_in": (self.update_doc, "source_path"),
+ "char_mode_changed": (self.update_doc_changed, "source_mode"),
+ "char_mode_focus" : (self.update_doc, "source_mode"),
+ "char_host_focus_in": (self.update_doc, "source_host"),
+ "char_bind_host_focus_in": (self.update_doc, "bind_host"),
+ "char_telnet_focus_in": (self.update_doc, "protocol"),
})
self.set_initial_state()
+ def update_doc(self, ignore1, ignore2, param):
+ doc = self._build_doc_str(param)
+ self.window.get_widget("char-info").set_markup(doc)
+
+ def update_doc_changed(self, ignore1, param):
+ # Wrapper for update_doc and 'changed' signal
+ self.update_doc(None, None, param)
+
+ def _build_doc_str(self, param, docstr=None):
+ doc = ""
+ doctmpl = "<i>%s</i>"
+
+ if docstr:
+ doc = doctmpl % (docstr)
+ elif self._dev:
+ devclass = self._dev.__class__
+ if hasattr(devclass, param):
+ doc = doctmpl % (getattr(devclass, param).__doc__)
+
+ return doc
+
def show(self):
self.reset_state()
self.topwin.show()
@@ -195,6 +241,32 @@
host_dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
+ char_devtype = self.window.get_widget("char-device-type")
+ # Type name, desc
+ char_devtype_model = gtk.ListStore(str, str)
+ char_devtype.set_model(char_devtype_model)
+ text = gtk.CellRendererText()
+ char_devtype.pack_start(text, True)
+ char_devtype.add_attribute(text, 'text', 1)
+ char_devtype_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
+ for t in VirtualCharDevice.char_types:
+ desc = VirtualCharDevice.get_char_type_desc(t)
+ char_devtype_model.append([t, desc + " (%s)" % t])
+
+ char_mode = self.window.get_widget("char-mode")
+ # Mode name, desc
+ char_mode_model = gtk.ListStore(str, str)
+ char_mode.set_model(char_mode_model)
+ text = gtk.CellRendererText()
+ char_mode.pack_start(text, True)
+ char_mode.add_attribute(text, 'text', 1)
+ char_mode_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
+ for t in VirtualCharDevice.char_modes:
+ desc = VirtualCharDevice.get_char_mode_desc(t)
+ char_mode_model.append([t, desc + " (%s)" % t])
+
+ self.window.get_widget("char-info-box").modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("grey"))
+
def reset_state(self):
notebook = self.window.get_widget("create-pages")
notebook.set_current_page(0)
@@ -283,6 +355,17 @@
# Set available HW options
+ # Char parameters
+ self.window.get_widget("char-device-type").set_active(0)
+ self.window.get_widget("char-path").set_text("")
+ self.window.get_widget("char-host").set_text("127.0.0.1")
+ self.window.get_widget("char-port").get_adjustment().value = 4555
+ self.window.get_widget("char-bind-host").set_text("127.0.0.1")
+ self.window.get_widget("char-bind-port").get_adjustment().value = 4556
+ self.window.get_widget("char-use-telnet").set_active(False)
+
+ # Available HW options
+
# FIXME: All of these needs to have better transparency.
# All options should be listed, but disabled with a tooltip if
# it can't be used.
@@ -304,6 +387,10 @@
if self.vm.is_hvm():
model.append(["Sound", gtk.STOCK_MEDIA_PLAY, PAGE_SOUND])
+ if self.vm.is_hvm():
+ model.append(["Serial", gtk.STOCK_CONNECT, PAGE_CHAR])
+ model.append(["Parallel", gtk.STOCK_CONNECT, PAGE_CHAR])
+
if self.vm.get_connection().is_nodedev_capable():
model.append(["Physical Host Device", None, PAGE_HOSTDEV])
@@ -467,6 +554,11 @@
return devbox.get_model()[devbox.get_active()]
def page_changed(self, notebook, page, page_number):
+ if page_number == PAGE_CHAR:
+ devtype = self.window.get_widget("char-device-type")
+ self.change_char_device_type(devtype)
+ self.set_page_char_type()
+
if page_number != PAGE_SUMMARY:
return
@@ -570,6 +662,35 @@
]
title = _("Sound")
+ elif hwpage == PAGE_CHAR:
+ mode = None
+
+ info_list = [
+ (_("Type:"), VirtualCharDevice.get_char_type_desc(self._dev.char_type)),
+ ]
+
+ if hasattr(self._dev, "source_mode"):
+ mode = self._dev.source_mode.capitalize()
+ if hasattr(self._dev, "source_path"):
+ path = self._dev.source_path
+ label = "%sPath:" % (mode and mode + " " or "")
+ info_list.append((label, path))
+
+ if hasattr(self._dev, "source_host"):
+ host = "%s:%s" % (self._dev.source_host, self._dev.source_port)
+ label = "%sHost:" % (mode and mode + " " or "")
+ info_list.append((label, host))
+
+ if hasattr(self._dev, "bind_host"):
+ bind_host = "%s:%s" % (self._dev.bind_host,
+ self._dev.bind_port)
+ info_list.append(("Bind Host:", bind_host))
+ if hasattr(self._dev, "protocol"):
+ proto = self._dev.protocol
+ info_list.append((_("Protocol:"), proto))
+
+ title = self.get_char_type().capitalize()
+
elif hwpage == PAGE_HOSTDEV:
info_list = [
(_("Type:"), self.get_config_host_device_type_info()[0]),
@@ -600,7 +721,8 @@
PAGE_INPUT: self.add_input,
PAGE_GRAPHICS: self.add_graphics,
PAGE_SOUND: self.add_sound,
- PAGE_HOSTDEV: self.add_hostdev }
+ PAGE_HOSTDEV: self.add_hostdev,
+ PAGE_CHAR: self.add_device}
try:
func = func_dict[hw]
@@ -660,7 +782,10 @@
else:
return (error, details)
- def add_device(self, xml):
+ def add_device(self, xml=None):
+ if not xml:
+ xml = self._dev.get_xml_config()
+
logging.debug("Adding device:\n" + xml)
attach_err = False
@@ -841,6 +966,42 @@
subtype, subcap)
devbox.set_active(0)
+ def get_char_type(self):
+ hw_list = self.window.get_widget("hardware-type")
+ if hw_list.get_active() < 0:
+ label = "serial"
+ else:
+ label = hw_list.get_model()[hw_list.get_active()][0]
+
+ if label.lower() == "parallel":
+ return VirtualDevice.VIRTUAL_DEV_PARALLEL
+ return VirtualDevice.VIRTUAL_DEV_SERIAL
+
+ def set_page_char_type(self):
+ char_type = self.get_char_type().capitalize()
+ self.window.get_widget("char-title-label").set_markup(
+ """<span weight="heavy" size="xx-large" foreground="#FFF">%s Device</span>""" % char_type)
+
+ def change_char_device_type(self, src):
+ self.update_doc(None, None, "char_type")
+
+ chartype = self.get_char_type()
+ devtype = src.get_model()[src.get_active()][0]
+ conn = self.vm.get_connection().vmm
+
+ self._dev = VirtualCharDevice.get_dev_instance(conn,
+ chartype,
+ devtype)
+
+ for param_name, widget_name in char_widget_mappings.items():
+ make_visible = hasattr(self._dev, param_name)
+ self.window.get_widget(widget_name).set_sensitive(make_visible)
+
+ has_mode = hasattr(self._dev, "source_mode")
+
+ if has_mode and self.window.get_widget("char-mode").get_active() == -1:
+ self.window.get_widget("char-mode").set_active(0)
+
def validate(self, page_num):
if page_num == PAGE_INTRO:
if self.get_config_hardware_type() == None:
@@ -987,6 +1148,48 @@
return self.err.val_err(_("Host device parameter error",
str(e)))
+ elif page_num == PAGE_CHAR:
+ chartype = self.get_char_type()
+ devbox = self.window.get_widget("char-device-type")
+ devtype = devbox.get_model()[devbox.get_active()][0]
+ conn = self.vm.get_connection().vmm
+
+ devclass = VirtualCharDevice.get_dev_instance(conn, chartype,
+ devtype)
+
+ source_path = self.window.get_widget("char-path").get_text()
+ source_host = self.window.get_widget("char-host").get_text()
+ bind_host = self.window.get_widget("char-bind-host").get_text()
+ source_port = self.window.get_widget("char-port").get_adjustment().value
+ bind_port = self.window.get_widget("char-bind-port").get_adjustment().value
+
+ if self.window.get_widget("char-use-telnet").get_active():
+ protocol = VirtualCharDevice.CHAR_PROTOCOL_TELNET
+ else:
+ protocol = VirtualCharDevice.CHAR_PROTOCOL_RAW
+
+ value_mappings = {
+ "source_path" : source_path,
+ "source_host" : source_host,
+ "source_port" : source_port,
+ "bind_port": bind_port,
+ "bind_host": bind_host,
+ "protocol": protocol,
+ }
+
+ try:
+ self._dev = devclass
+
+ for param_name, val in value_mappings.items():
+ if hasattr(self._dev, param_name):
+ setattr(self._dev, param_name, val)
+
+ # Dump XML for sanity checking
+ self._dev.get_xml_config()
+ except Exception, e:
+ return self.err.val_err(_("%s device parameter error.") %
+ chartype.capitalize(), str(e))
+
return True
def populate_network_model(self, model):
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]