mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
Support adding serial and parallel devices via 'Add Hardware'
This commit is contained in:
parent
1224f90699
commit
b34fd724d3
@ -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_INPUT = 3
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
"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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
|
||||
# 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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
]
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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 @@ class vmmAddHardware(gobject.GObject):
|
||||
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:
|
||||
@ -982,6 +1143,48 @@ class vmmAddHardware(gobject.GObject):
|
||||
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):
|
||||
|
Loading…
Reference in New Issue
Block a user