# # Copyright (C) 2006-2007, 2012-2014 Red Hat, Inc. # Copyright (C) 2006 Hugh O. Brock # # 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. # import logging import traceback import collections from gi.repository import Gtk from gi.repository import Gdk import virtinst from virtinst import (VirtualChannelDevice, VirtualParallelDevice, VirtualSerialDevice, VirtualConsoleDevice, VirtualVideoDevice, VirtualWatchdog, VirtualSmartCardDevice, VirtualRedirDevice, VirtualTPMDevice, VirtualPanicDevice) from virtinst import VirtualController from virtManager import uiutil from virtManager.fsdetails import vmmFSDetails from virtManager.gfxdetails import vmmGraphicsDetails from virtManager.netlist import vmmNetworkList from virtManager.asyncjob import vmmAsyncJob from virtManager.storagebrowse import vmmStorageBrowser from virtManager.baseclass import vmmGObjectUI from virtManager.addstorage import vmmAddStorage (PAGE_ERROR, PAGE_DISK, PAGE_CONTROLLER, PAGE_NETWORK, PAGE_INPUT, PAGE_GRAPHICS, PAGE_SOUND, PAGE_HOSTDEV, PAGE_CHAR, PAGE_VIDEO, PAGE_WATCHDOG, PAGE_FILESYSTEM, PAGE_SMARTCARD, PAGE_USBREDIR, PAGE_TPM, PAGE_RNG, PAGE_PANIC, ) = range(0, 17) class vmmAddHardware(vmmGObjectUI): def __init__(self, vm, is_customize_dialog): vmmGObjectUI.__init__(self, "addhardware.ui", "vmm-add-hardware") self.vm = vm self.conn = vm.conn self.is_customize_dialog = is_customize_dialog self.storage_browser = None self._dev = None self.gfxdetails = vmmGraphicsDetails( self.vm, self.builder, self.topwin) self.widget("graphics-align").add(self.gfxdetails.top_box) self.fsDetails = vmmFSDetails(self.vm, self.builder, self.topwin) self.widget("fs-box").add(self.fsDetails.top_box) self.netlist = vmmNetworkList(self.conn, self.builder, self.topwin) self.widget("network-source-label-align").add(self.netlist.top_label) self.widget("network-source-ui-align").add(self.netlist.top_box) self.widget("network-vport-align").add(self.netlist.top_vport) self.addstorage = vmmAddStorage(self.conn, self.builder, self.topwin) self.widget("config-storage-align").add(self.addstorage.top_box) self.addstorage.connect("browse-clicked", self._browse_storage_cb) self.addstorage.connect("storage-toggled", self.toggle_storage_select) self.builder.connect_signals({ "on_create_cancel_clicked" : self.close, "on_vmm_create_delete_event" : self.close, "on_create_finish_clicked" : self.finish, "on_hw_list_changed": self.hw_selected, "on_config_storage_bustype_changed": self.populate_disk_device, "on_config_storage_devtype_changed": self.change_storage_devtype, "on_mac_address_clicked" : self.change_macaddr_use, "on_char_device_type_changed": self.change_char_device_type, "on_char_target_name_changed": self.change_char_target_name, "on_char_auto_socket_toggled": self.change_char_auto_socket, "on_tpm_device_type_changed": self.change_tpm_device_type, "on_usbredir_type_changed": self.change_usbredir_type, "on_rng_type_changed": self.change_rng, "on_rng_backend_mode_changed": self.change_rng, "on_rng_backend_type_changed": self.change_rng, "on_controller_type_changed": self.populate_controller_model, }) self.bind_escape_key_close() self.set_initial_state() def show(self, parent): logging.debug("Showing addhw") self.reset_state() self.topwin.set_transient_for(parent) self.topwin.present() self.conn.schedule_priority_tick(pollnet=True, pollpool=True, polliface=True, pollnodedev=True, pollmedia=True) def close(self, ignore1=None, ignore2=None): logging.debug("Closing addhw") self.topwin.hide() if self.storage_browser: self.storage_browser.close() return 1 def _cleanup(self): self.vm = None self.conn = None self._dev = None if self.storage_browser: self.storage_browser.cleanup() self.storage_browser = None self.gfxdetails.cleanup() self.gfxdetails = None self.fsDetails.cleanup() self.fsDetails = None self.netlist.cleanup() self.netlist = None self.addstorage.cleanup() self.addstorage = None def is_visible(self): return self.topwin.get_visible() ########################## # Initialization methods # ########################## def set_initial_state(self): notebook = self.widget("create-pages") notebook.set_show_tabs(False) blue = Gdk.color_parse("#0072A8") self.widget("page-title-box").modify_bg(Gtk.StateType.NORMAL, blue) # Name, icon name, page number, is sensitive, tooltip, icon size, # device type (serial/parallel)... model = Gtk.ListStore(str, str, int, bool, str, str) hw_list = self.widget("hw-list") hw_list.set_model(model) hw_col = Gtk.TreeViewColumn("Hardware") hw_col.set_spacing(6) hw_col.set_min_width(165) icon = Gtk.CellRendererPixbuf() icon.set_property("stock-size", Gtk.IconSize.BUTTON) text = Gtk.CellRendererText() text.set_property("xpad", 6) hw_col.pack_start(icon, False) hw_col.pack_start(text, True) hw_col.add_attribute(icon, 'icon-name', 1) hw_col.add_attribute(text, 'text', 0) hw_col.add_attribute(text, 'sensitive', 3) hw_list.append_column(hw_col) # Network model list netmodel_list = self.widget("net-model") self.build_network_model_combo(self.vm, netmodel_list) # Disk bus type widget = self.widget("config-storage-bustype") # [bus, label] model = Gtk.ListStore(str, str) widget.set_model(model) uiutil.set_combo_text_column(widget, 1) # Disk device type target_list = self.widget("config-storage-devtype") # [device, icon, label] target_model = Gtk.ListStore(str, str, str) target_list.set_model(target_model) icon = Gtk.CellRendererPixbuf() icon.set_property("stock-size", Gtk.IconSize.BUTTON) target_list.pack_start(icon, False) target_list.add_attribute(icon, 'icon-name', 1) text = Gtk.CellRendererText() text.set_property("xpad", 6) target_list.pack_start(text, True) target_list.add_attribute(text, 'text', 2) # Disk cache mode cache_list = self.widget("config-storage-cache") self.build_disk_cache_combo(self.vm, cache_list) # Disk format mode self.populate_disk_format_combo_wrapper(True) # Input device type input_list = self.widget("input-type") input_model = Gtk.ListStore(str, str, str) input_list.set_model(input_model) uiutil.set_combo_text_column(input_list, 0) # Sound model list sound_list = self.widget("sound-model") self.build_sound_combo(self.vm, sound_list) # Host device list # model = [ Description, nodedev name ] host_dev = self.widget("host-device") host_dev_model = Gtk.ListStore(str, str, str, object) host_dev.set_model(host_dev_model) host_col = Gtk.TreeViewColumn() text = Gtk.CellRendererText() host_col.pack_start(text, True) host_col.add_attribute(text, 'text', 0) host_dev_model.set_sort_column_id(0, Gtk.SortType.ASCENDING) host_dev.append_column(host_col) # Video device video_dev = self.widget("video-model") self.build_video_combo(self.vm, video_dev) # Character dev mode char_mode = self.widget("char-mode") # Mode name, desc char_mode_model = Gtk.ListStore(str, str) char_mode.set_model(char_mode_model) uiutil.set_combo_text_column(char_mode, 1) char_mode_model.set_sort_column_id(0, Gtk.SortType.ASCENDING) for t in VirtualSerialDevice.MODES: desc = VirtualSerialDevice.pretty_mode(t) char_mode_model.append([t, desc + " (%s)" % t]) # Char target type lst = self.widget("char-target-type") model = Gtk.ListStore(str, str) lst.set_model(model) uiutil.set_combo_text_column(lst, 1) if self.conn.is_qemu(): model.append(["virtio", "virtio"]) else: model.append([None, "default"]) # Char target name lst = self.widget("char-target-name") model = Gtk.ListStore(str) lst.set_model(model) uiutil.set_combo_text_column(lst, 0) for n in VirtualChannelDevice.CHANNEL_NAMES: model.append([n]) # Char device type lst = self.widget("char-device-type") model = Gtk.ListStore(str, str) lst.set_model(model) uiutil.set_combo_text_column(lst, 1) # Watchdog widgets combo = self.widget("watchdog-model") self.build_watchdogmodel_combo(self.vm, combo) combo = self.widget("watchdog-action") self.build_watchdogaction_combo(self.vm, combo) # Smartcard widgets combo = self.widget("smartcard-mode") self.build_smartcard_mode_combo(self.vm, combo) # Usbredir widgets combo = self.widget("usbredir-list") self.build_redir_type_combo(self.vm, combo) # TPM widgets combo = self.widget("tpm-type") self.build_tpm_type_combo(self.vm, combo) # RNG widgets combo = self.widget("rng-type") self.build_rng_type_combo(combo) combo = self.widget("rng-backend-type") self.build_rng_backend_type_combo(combo) combo = self.widget("rng-backend-mode") self.build_rng_backend_mode_combo(combo) # Panic widgets combo = self.widget("panic-type") self.build_panic_address_type(combo) # Controller widgets combo = self.widget("controller-type") target_model = Gtk.ListStore(str, str) combo.set_model(target_model) uiutil.set_combo_text_column(combo, 1) combo = self.widget("controller-model") target_model = Gtk.ListStore(str, str) combo.set_model(target_model) uiutil.set_combo_text_column(combo, 1) # FIXME: we should deal with controller model combo.set_visible(False) self.widget("controller-model-label").set_visible(False) # Available HW options is_local = not self.conn.is_remote() is_storage_capable = self.conn.is_storage_capable() have_storage = (is_local or is_storage_capable) storage_tooltip = None if not have_storage: storage_tooltip = _("Connection does not support storage" " management.") hwlist = self.widget("hw-list") model = hwlist.get_model() model.clear() def add_hw_option(name, icon, page, sensitive, errortxt, devtype=None): model.append([name, icon, page, sensitive, errortxt, devtype]) add_hw_option("Storage", "drive-harddisk", PAGE_DISK, have_storage, have_storage and storage_tooltip or None) add_hw_option("Controller", "device_pci", PAGE_CONTROLLER, True, None) add_hw_option("Network", "network-idle", PAGE_NETWORK, True, None) add_hw_option("Input", "input-mouse", PAGE_INPUT, self.vm.is_hvm(), _("Not supported for this guest type.")) add_hw_option("Graphics", "video-display", PAGE_GRAPHICS, True, None) add_hw_option("Sound", "audio-card", PAGE_SOUND, self.vm.is_hvm(), _("Not supported for this guest type.")) add_hw_option("Serial", Gtk.STOCK_CONNECT, PAGE_CHAR, self.vm.is_hvm(), _("Not supported for this guest type."), "serial") add_hw_option("Parallel", Gtk.STOCK_CONNECT, PAGE_CHAR, self.vm.is_hvm(), _("Not supported for this guest type."), "parallel") add_hw_option("Console", Gtk.STOCK_CONNECT, PAGE_CHAR, True, None, "console") add_hw_option("Channel", Gtk.STOCK_CONNECT, PAGE_CHAR, self.vm.is_hvm(), _("Not supported for this guest type."), "channel") add_hw_option("USB Host Device", "system-run", PAGE_HOSTDEV, self.conn.is_nodedev_capable(), _("Connection does not support host device enumeration"), "usb") add_hw_option("PCI Host Device", "system-run", PAGE_HOSTDEV, self.conn.is_nodedev_capable(), _("Connection does not support host device enumeration"), "pci") add_hw_option("Video", "video-display", PAGE_VIDEO, True, _("Libvirt version does not support video devices.")) add_hw_option("Watchdog", "device_pci", PAGE_WATCHDOG, self.vm.is_hvm(), _("Not supported for this guest type.")) add_hw_option("Filesystem", Gtk.STOCK_DIRECTORY, PAGE_FILESYSTEM, self.conn.check_support( self.conn.SUPPORT_CONN_FILESYSTEM) and not self.vm.stable_defaults(), _("Not supported for this hypervisor/libvirt " "combination.")) add_hw_option("Smartcard", "device_serial", PAGE_SMARTCARD, True, None) add_hw_option("USB Redirection", "device_usb", PAGE_USBREDIR, True, None) add_hw_option("TPM", "device_cpu", PAGE_TPM, True, None) add_hw_option("RNG", "system-run", PAGE_RNG, True, None) add_hw_option("Panic Notifier", "system-run", PAGE_PANIC, self.conn.check_support(self.conn.SUPPORT_CONN_PANIC_DEVICE), _("Not supported for this hypervisor/libvirt combination.")) def reset_state(self): # Storage init self.populate_disk_format_combo_wrapper(True) self.populate_disk_bus() self.addstorage.reset_state() # Network init newmac = virtinst.VirtualNetworkInterface.generate_mac( self.conn.get_backend()) self.widget("mac-address").set_active(bool(newmac)) self.widget("create-mac-address").set_text(newmac) self.change_macaddr_use() self.netlist.reset_state() netmodel = self.widget("net-model") self.populate_network_model_combo(self.vm, netmodel) netmodel.set_active(0) # Input device init input_box = self.widget("input-type") self.populate_input_model(input_box.get_model()) input_box.set_active(0) # Graphics init self.gfxdetails.reset_state() # Sound init sound_box = self.widget("sound-model") sound_box.set_active(0) # Char parameters self.widget("char-device-type").set_active(0) self.widget("char-target-type").set_active(0) self.widget("char-target-name").set_active(0) self.widget("char-path").set_text("") self.widget("char-channel").set_text("") self.widget("char-host").set_text("127.0.0.1") self.widget("char-port").set_value(4555) self.widget("char-bind-host").set_text("127.0.0.1") self.widget("char-bind-port").set_value(4556) self.widget("char-use-telnet").set_active(False) self.widget("char-auto-socket").set_active(True) # FS params self.fsDetails.reset_state() # Video params self.populate_video_combo(self.vm, self.widget("video-model")) # TPM params self.widget("tpm-device-path").set_text("/dev/tpm0") # Hide all notebook pages, so the wizard isn't as big as the largest # page notebook = self.widget("create-pages") for page in range(notebook.get_n_pages()): widget = notebook.get_nth_page(page) widget.hide() # RNG params self.widget("rng-device").set_text("/dev/random") for i in ["rng-bind-host", "rng-connect-host"]: self.widget(i).set_text("localhost") for i in ["rng-bind-service", "rng-connect-service"]: self.widget(i).set_text("708") # Panic device params self.widget("panic-iobase").set_text("0x505") # Controller device params self.populate_controller_type() self.set_hw_selection(0) ##################### # Shared UI helpers # ##################### @staticmethod def populate_video_combo(vm, combo, no_default=None): model = combo.get_model() has_spice = bool([g for g in vm.get_graphics_devices() if g.type == g.TYPE_SPICE]) has_qxl = bool([v for v in vm.get_video_devices() if v.model == "qxl"]) model.clear() tmpdev = virtinst.VirtualVideoDevice(vm.conn.get_backend()) for m in tmpdev.MODELS: if vm.stable_defaults(): if m == "qxl" and not has_spice and not has_qxl: # Only list QXL video option when VM has SPICE video continue if m == tmpdev.MODEL_DEFAULT and no_default: continue model.append([m, tmpdev.pretty_model(m)]) if len(model) > 0: combo.set_active(0) @staticmethod def build_video_combo(vm, combo, no_default=None): model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) combo.get_model().set_sort_column_id(1, Gtk.SortType.ASCENDING) vmmAddHardware.populate_video_combo(vm, combo, no_default) @staticmethod def build_sound_combo(vm, combo, no_default=False): model = Gtk.ListStore(str) combo.set_model(model) uiutil.set_combo_text_column(combo, 0) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) stable_defaults = vm.stable_defaults() stable_soundmodels = ["ich6", "ac97"] for m in virtinst.VirtualAudio.MODELS: if m == virtinst.VirtualAudio.MODEL_DEFAULT and no_default: continue if (stable_defaults and m not in stable_soundmodels): continue model.append([m]) if len(model) > 0: combo.set_active(0) @staticmethod def build_watchdogmodel_combo(vm, combo, no_default=False): ignore = vm model = Gtk.ListStore(str) combo.set_model(model) uiutil.set_combo_text_column(combo, 0) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) for m in virtinst.VirtualWatchdog.MODELS: if m == virtinst.VirtualAudio.MODEL_DEFAULT and no_default: continue model.append([m]) if len(model) > 0: combo.set_active(0) @staticmethod def build_watchdogaction_combo(vm, combo, no_default=False): ignore = vm model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) for m in virtinst.VirtualWatchdog.ACTIONS: if m == virtinst.VirtualWatchdog.ACTION_DEFAULT and no_default: continue model.append([m, virtinst.VirtualWatchdog.get_action_desc(m)]) if len(model) > 0: combo.set_active(0) @staticmethod def populate_network_model_combo(vm, combo): model = combo.get_model() model.clear() # [xml value, label] model.append([None, _("Hypervisor default")]) if vm.is_hvm(): mod_list = ["rtl8139", "ne2k_pci", "pcnet", "e1000"] if vm.get_hv_type() in ["kvm", "qemu", "test"]: mod_list.append("virtio") if (vm.get_hv_type() == "kvm" and vm.get_machtype() == "pseries"): mod_list.append("spapr-vlan") if vm.get_hv_type() in ["xen", "test"]: mod_list.append("netfront") mod_list.sort() for m in mod_list: model.append([m, m]) @staticmethod def build_network_model_combo(vm, combo): model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) vmmAddHardware.populate_network_model_combo(vm, combo) combo.set_active(0) @staticmethod def populate_smartcard_mode_combo(vm, combo): ignore = vm model = combo.get_model() model.clear() # [xml value, label] model.append(["passthrough", "Passthrough"]) model.append(["host", "Host"]) @staticmethod def build_smartcard_mode_combo(vm, combo): model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) vmmAddHardware.populate_smartcard_mode_combo(vm, combo) idx = -1 for rowid in range(len(combo.get_model())): idx = 0 row = combo.get_model()[rowid] if row[0] == virtinst.VirtualSmartCardDevice.MODE_DEFAULT: idx = rowid break combo.set_active(idx) @staticmethod def populate_redir_type_combo(vm, combo): ignore = vm model = combo.get_model() model.clear() # [xml value, label, conn details] model.append(["spicevmc", "Spice channel", False]) model.append(["tcp", "TCP", True]) @staticmethod def build_redir_type_combo(vm, combo): model = Gtk.ListStore(str, str, bool) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) vmmAddHardware.populate_redir_type_combo(vm, combo) combo.set_active(0) @staticmethod def populate_tpm_type_combo(vm, combo): ignore = vm types = combo.get_model() types.clear() # [xml value, label] for t in virtinst.VirtualTPMDevice.TYPES: types.append([t, virtinst.VirtualTPMDevice.get_pretty_type(t)]) @staticmethod def build_tpm_type_combo(vm, combo): model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) vmmAddHardware.populate_tpm_type_combo(vm, combo) idx = -1 for rowid in range(len(combo.get_model())): idx = 0 row = combo.get_model()[rowid] if row[0] == virtinst.VirtualTPMDevice.TYPE_DEFAULT: idx = rowid break combo.set_active(idx) @staticmethod def build_disk_cache_combo(vm, combo): ignore = vm model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) combo.set_active(-1) for m in virtinst.VirtualDisk.cache_types: model.append([m, m]) _iter = model.insert(0, [None, "default"]) combo.set_active_iter(_iter) @staticmethod def build_disk_io_combo(vm, combo, no_default=False): ignore = vm model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) combo.set_active(-1) for m in virtinst.VirtualDisk.io_modes: model.append([m, m]) if not no_default: model.append([None, "default"]) combo.set_active(0) @staticmethod def build_disk_bus_combo(vm, combo, no_default=False): ignore = vm model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) model.set_sort_column_id(1, Gtk.SortType.ASCENDING) if not no_default: model.append([None, "default"]) combo.set_active(-1) @staticmethod def populate_disk_format_combo(vm, combo, create): model = Gtk.ListStore(str) combo.set_model(model) uiutil.set_combo_text_column(combo, 0) formats = ["raw", "qcow2", "qed"] no_create_formats = [] if not vm.stable_defaults(): formats.append("vmdk") no_create_formats.append("vdi") for m in formats: model.append([m]) if not create: for m in no_create_formats: model.append([m]) if create: fmt = vm.conn.get_default_storage_format() combo.set_active(0) for row in model: if row[0] == fmt: combo.set_active_iter(row.iter) break @staticmethod def populate_controller_model_combo(combo, controller_type, widget_name, add_default=False): model = combo.get_model() model.clear() if controller_type == virtinst.VirtualController.TYPE_USB: model.append(["default", "Default"]) model.append(["ich9-ehci1", "USB 2"]) model.append(["nec-xhci", "USB 3"]) if widget_name is not None: widget_name.set_sensitive(False) elif controller_type == virtinst.VirtualController.TYPE_SCSI: model.append(["default", "Default"]) model.append(["virtio-scsi", "VirtIO SCSI"]) else: if add_default: model.append([None, "Default"]) combo.set_sensitive(False) if widget_name is not None: widget_name.set_sensitive(True) ######################### # UI population methods # ######################### def populate_disk_bus(self): widget = self.widget("config-storage-bustype") model = widget.get_model() model.clear() if self.vm.is_hvm(): model.append(["ide", "IDE"]) model.append(["fdc", "Floppy"]) if not self.vm.stable_defaults(): model.append(["scsi", "SCSI"]) model.append(["usb", "USB"]) if self.vm.get_hv_type() in ["qemu", "kvm", "test"]: model.append(["sata", "SATA"]) model.append(["sd", "SD"]) model.append(["virtio", "VirtIO"]) model.append(["virtio-scsi", "VirtIO SCSI"]) if self.conn.is_xen() or self.conn.is_test_conn(): model.append(["xen", "Xen"]) if len(model) > 0: widget.set_active(0) def populate_disk_device(self, src): ignore = src bus = self.get_config_disk_bus() devlist = self.widget("config-storage-devtype") model = devlist.get_model() model.clear() disk_buses = ["ide", "sata", "scsi", "sd", "usb", "virtio", "virtio-scsi", "xen"] floppy_buses = ["fdc"] cdrom_buses = ["ide", "scsi"] lun_buses = ["virtio-scsi"] if bus in disk_buses: model.append([virtinst.VirtualDisk.DEVICE_DISK, "drive-harddisk", _("Disk device")]) if bus in floppy_buses: model.append([virtinst.VirtualDisk.DEVICE_FLOPPY, "media-floppy", _("Floppy device")]) if bus in cdrom_buses: model.append([virtinst.VirtualDisk.DEVICE_CDROM, "media-cdrom", _("CDROM device")]) if bus in lun_buses: model.append([virtinst.VirtualDisk.DEVICE_LUN, "drive-harddisk", _("LUN device")]) if len(model) > 0: devlist.set_active(0) def populate_input_model(self, model): model.clear() model.append([_("EvTouch USB Graphics Tablet"), "tablet", "usb"]) model.append([_("Generic USB Mouse"), "mouse", "usb"]) def populate_host_device_model(self, devtype, devcap, subtype, subcap): devlist = self.widget("host-device") model = devlist.get_model() model.clear() subdevs = [] if subtype: subdevs = self.conn.get_nodedevs(subtype, subcap) devs = self.conn.get_nodedevs(devtype, devcap) for dev in devs: prettyname = dev.pretty_name() for subdev in subdevs: if dev.name == subdev.parent: prettyname += " (%s)" % subdev.pretty_name() model.append([prettyname, dev.name, devtype, dev]) if len(model) == 0: model.append([_("No Devices Available"), None, None, None]) uiutil.set_list_selection(devlist, 0) def populate_disk_format_combo_wrapper(self, create): format_list = self.widget("config-storage-format") self.populate_disk_format_combo(self.vm, format_list, create) if not create: format_list.get_child().set_text("") def populate_controller_type(self): widget = self.widget("controller-type") model = widget.get_model() model.clear() for t in VirtualController.TYPES: if t == VirtualController.TYPE_PCI: continue model.append([t, VirtualController.pretty_type(t)]) if len(model) > 0: widget.set_active(0) def populate_controller_model(self, src): ignore = src controller_type = self.get_config_controller_type() modellist = self.widget("controller-model") modellist.set_sensitive(True) self.populate_controller_model_combo(modellist, controller_type, None, True) if len(modellist.get_model()) > 0: modellist.set_active(0) ######################## # get_config_* methods # ######################## def build_combo_with_values(self, combo, values, default=None): dev_model = Gtk.ListStore(str, str) combo.set_model(dev_model) uiutil.set_combo_text_column(combo, 1) dev_model.set_sort_column_id(0, Gtk.SortType.ASCENDING) types = combo.get_model() types.clear() # [xml value, label] for t in values: types.append(t[0:2]) if default: idx = -1 for rowid in range(len(combo.get_model())): idx = 0 row = combo.get_model()[rowid] if row[0] == default: idx = rowid break combo.set_active(idx) def build_rng_type_combo(self, combo): types = [] for t in virtinst.VirtualRNGDevice.TYPES: types.append([t, virtinst.VirtualRNGDevice.get_pretty_type(t)]) self.build_combo_with_values(combo, types, virtinst.VirtualRNGDevice.TYPE_RANDOM) def build_rng_backend_type_combo(self, combo): default = virtinst.VirtualRNGDevice.BACKEND_TYPE_TCP types = [] for t in virtinst.VirtualRNGDevice.BACKEND_TYPES: pprint = virtinst.VirtualRNGDevice.get_pretty_backend_type(t) types.append([t, pprint]) self.build_combo_with_values(combo, types, default) def build_rng_backend_mode_combo(self, combo): default = virtinst.VirtualRNGDevice.BACKEND_MODE_CONNECT types = [] for t in virtinst.VirtualRNGDevice.BACKEND_MODES: pprint = virtinst.VirtualRNGDevice.get_pretty_backend_type(t) types.append([t, pprint]) self.build_combo_with_values(combo, types, default) def build_panic_address_type(self, combo): types = [] for t in virtinst.VirtualPanicDevice.TYPES: types.append([t, virtinst.VirtualPanicDevice.get_pretty_type(t)]) self.build_combo_with_values(combo, types, virtinst.VirtualPanicDevice.ADDRESS_TYPE_ISA) def get_config_hardware_type(self): row = self.get_hw_selection() if not row: return None return row[2] # Disk getters def get_config_disk_bus(self): return uiutil.get_list_selection( self.widget("config-storage-bustype"), 0) def get_config_disk_device(self): return uiutil.get_list_selection( self.widget("config-storage-devtype"), 0) def get_config_disk_cache(self): return uiutil.get_list_selection( self.widget("config-storage-cache"), 0) def get_config_disk_format(self): fmt = self.widget("config-storage-format") return fmt.get_child().get_text() # Input getters def get_config_input(self): row = uiutil.get_list_selection(self.widget("input-type"), None) return row[1], row[2] # Network getters def get_config_net_model(self): return uiutil.get_list_selection(self.widget("net-model"), 0) def get_config_macaddr(self): macaddr = None if self.widget("mac-address").get_active(): macaddr = self.widget("create-mac-address").get_text() return macaddr # Sound getters def get_config_sound_model(self): return uiutil.get_list_selection(self.widget("sound-model"), 0) # Host device getters def get_config_host_device_type_info(self): pci_info = ["PCI Device", "pci", None, "net", "80203"] usb_info = ["USB Device", "usb_device", None, None, None] row = self.get_hw_selection() if row and row[5] == "pci": return pci_info return usb_info def get_config_host_device_info(self): return uiutil.get_list_selection(self.widget("host-device"), None) # Video Getters def get_config_video_model(self): return uiutil.get_list_selection(self.widget("video-model"), 0) # Watchdog getters def get_config_watchdog_model(self): return uiutil.get_list_selection(self.widget("watchdog-model"), 0) def get_config_watchdog_action(self): return uiutil.get_list_selection(self.widget("watchdog-action"), 0) # Smartcard getters def get_config_smartcard_mode(self): return uiutil.get_list_selection(self.widget("smartcard-mode"), 0) # USB redir getters def get_config_usbredir_host(self): host = self.widget("usbredir-host") service = self.widget("usbredir-service") if not host.get_visible(): return None, None return host.get_text(), int(service.get_value()) def get_config_usbredir_type(self): return uiutil.get_list_selection(self.widget("usbredir-list"), 0) # TPM getters def get_config_tpm_type(self): return uiutil.get_list_selection(self.widget("tpm-type"), 0) # RNG getters def get_config_rng_type(self): return uiutil.get_list_selection(self.widget("rng-type"), 0) def get_config_rng_device(self): if self.get_config_rng_type() == virtinst.VirtualRNGDevice.TYPE_RANDOM: return self.widget("rng-device").get_text() return None def get_config_rng_host(self, is_connect=False): connect_mode = virtinst.VirtualRNGDevice.BACKEND_MODE_CONNECT in \ self.get_config_rng_backend_mode() is_udp = self.get_config_rng_backend_type() == \ virtinst.VirtualRNGDevice.BACKEND_TYPE_UDP if connect_mode == is_connect or is_udp: widget_name = "rng-connect-host" if is_connect else "rng-bind-host" return self.widget(widget_name).get_text() return None def get_config_rng_service(self, is_connect=False): connect_mode = virtinst.VirtualRNGDevice.BACKEND_MODE_CONNECT in \ self.get_config_rng_backend_mode() is_udp = self.get_config_rng_backend_type() == \ virtinst.VirtualRNGDevice.BACKEND_TYPE_UDP if connect_mode == is_connect or is_udp: if is_connect: widget_name = "rng-connect-service" else: widget_name = "rng-bind-service" return self.widget(widget_name).get_text() return None def get_config_rng_backend_type(self): return uiutil.get_list_selection(self.widget("rng-backend-type"), 0) def get_config_rng_backend_mode(self): return uiutil.get_list_selection(self.widget("rng-backend-mode"), 0) # CONTROLLER getters def get_config_controller_type(self): return uiutil.get_list_selection(self.widget("controller-type"), 0) def get_config_controller_model(self): return uiutil.get_list_selection(self.widget("controller-model"), 0) ################ # UI listeners # ################ def set_hw_selection(self, page): uiutil.set_list_selection(self.widget("hw-list"), page) def get_hw_selection(self): return uiutil.get_list_selection(self.widget("hw-list"), None) def update_char_device_type_model(self): stable_blacklist = ["pipe", "udp"] # Char device type char_devtype = self.widget("char-device-type") char_devtype_model = char_devtype.get_model() char_devtype_model.clear() char_class = self.get_char_type() # Type name, desc for t in char_class.TYPES: if (t in stable_blacklist and self.vm.stable_defaults()): continue desc = char_class.pretty_type(t) row = [t, desc + " (%s)" % t] char_devtype_model.append(row) char_devtype.set_active(0) def hw_selected(self, src=None): ignore = src self._dev = None notebook = self.widget("create-pages") row = self.get_hw_selection() if not row: self.set_hw_selection(0) return page = row[2] sens = row[3] msg = row[4] or "" self.widget("create-finish").set_sensitive(sens) if not sens: page = PAGE_ERROR self.widget("hardware-info").set_text(msg) if page == PAGE_CHAR: self.update_char_device_type_model() self.widget("char-device-type").emit("changed") self.widget("char-target-name").emit("changed") if page == PAGE_HOSTDEV: (ignore, devtype, devcap, subtype, subcap) = self.get_config_host_device_type_info() self.populate_host_device_model(devtype, devcap, subtype, subcap) self.set_page_title(page) notebook.get_nth_page(page).show() notebook.set_current_page(page) # Storage listeners def toggle_storage_select(self, ignore, src): act = src.get_active() self.populate_disk_format_combo_wrapper(not act) def change_storage_devtype(self, ignore): devtype = self.get_config_disk_device() allow_create = devtype not in ["cdrom", "floppy"] self.addstorage.widget("config-storage-create-box").set_sensitive( allow_create) if not allow_create: self.addstorage.widget("config-storage-select").set_active(True) # Network listeners def change_macaddr_use(self, ignore=None): if self.widget("mac-address").get_active(): self.widget("create-mac-address").set_sensitive(True) else: self.widget("create-mac-address").set_sensitive(False) # Char device listeners def get_char_type(self): row = self.get_hw_selection() label = "serial" if row: label = row[5] if label == "parallel": return VirtualParallelDevice elif label == "channel": return VirtualChannelDevice elif label == "console": return VirtualConsoleDevice return VirtualSerialDevice def dev_to_title(self, page): if page == PAGE_ERROR: return _("Error") if page == PAGE_DISK: return _("Storage") if page == PAGE_CONTROLLER: return _("Controller") if page == PAGE_NETWORK: return _("Network") if page == PAGE_INPUT: return _("Input") if page == PAGE_GRAPHICS: return _("Graphics") if page == PAGE_SOUND: return _("Sound") if page == PAGE_VIDEO: return _("Video Device") if page == PAGE_WATCHDOG: return _("Watchdog Device") if page == PAGE_FILESYSTEM: return _("Filesystem Passthrough") if page == PAGE_SMARTCARD: return _("Smartcard") if page == PAGE_USBREDIR: return _("USB Redirection") if page == PAGE_TPM: return _("TPM") if page == PAGE_RNG: return _("Random Number Generator") if page == PAGE_PANIC: return _("Panic Notifier") if page == PAGE_CHAR: char_class = self.get_char_type() return char_class.virtual_device_type.capitalize() + " Device" if page == PAGE_HOSTDEV: return self.get_config_host_device_type_info()[0] raise RuntimeError("Unknown page %s" % page) def set_page_title(self, page): title = self.dev_to_title(page) markup = "%s" % title self.widget("page-title-label").set_markup(markup) def change_tpm_device_type(self, src): devtype = uiutil.get_list_selection(src, 0) if devtype is None: return tpm_widget_mappings = { "device_path" : "tpm-device-path", } self._dev = VirtualTPMDevice(self.conn.get_backend()) self._dev.type = devtype for param_name, widget_name in tpm_widget_mappings.items(): make_visible = self._dev.supports_property(param_name) uiutil.set_grid_row_visible(self.widget(widget_name + "-label"), make_visible) def change_char_auto_socket(self, src): if not src.get_visible(): return doshow = not src.get_active() uiutil.set_grid_row_visible(self.widget("char-path-label"), doshow) uiutil.set_grid_row_visible(self.widget("char-mode-label"), doshow) def change_char_target_name(self, src): if not src.get_visible(): return text = src.get_child().get_text() settype = None if text == VirtualChannelDevice.CHANNEL_NAME_SPICE: settype = "spicevmc" elif text == VirtualChannelDevice.CHANNEL_NAME_SPICE_WEBDAV: settype = "spiceport" self.widget("char-channel").set_text(text) elif (text == VirtualChannelDevice.CHANNEL_NAME_QEMUGA or text == VirtualChannelDevice.CHANNEL_NAME_LIBGUESTFS): settype = "unix" uiutil.set_row_selection(self.widget("char-device-type"), settype) def change_char_device_type(self, src): devtype = uiutil.get_list_selection(src, 0) if devtype is None: return char_widget_mappings = { "source_path" : "char-path", "source_channel" : "char-channel", "source_mode" : "char-mode", "source_host" : "char-host", "bind_host" : "char-bind-host", "protocol" : "char-use-telnet", } char_class = self.get_char_type() ischan = char_class.virtual_device_type == "channel" iscon = char_class.virtual_device_type == "console" show_auto = (devtype == "unix" and ischan and self.conn.check_support(self.conn.SUPPORT_CONN_AUTOSOCKET)) self._dev = char_class(self.conn.get_backend()) self._dev.type = devtype for param_name, widget_name in char_widget_mappings.items(): make_visible = self._dev.supports_property(param_name) uiutil.set_grid_row_visible(self.widget(widget_name + "-label"), make_visible) uiutil.set_grid_row_visible( self.widget("char-target-name-label"), ischan) uiutil.set_grid_row_visible( self.widget("char-target-type-label"), iscon) uiutil.set_grid_row_visible( self.widget("char-auto-socket-label"), show_auto) self.widget("char-auto-socket").emit("toggled") has_mode = self._dev.supports_property("source_mode") if has_mode and self.widget("char-mode").get_active() == -1: self.widget("char-mode").set_active(0) def change_usbredir_type(self, src): showhost = uiutil.get_list_selection(src, 2) if showhost is None: return uiutil.set_grid_row_visible(self.widget("usbredir-host-box"), showhost) def change_rng(self, ignore1): model = self.get_config_rng_type() if model is None: return is_egd = model == virtinst.VirtualRNGDevice.TYPE_EGD uiutil.set_grid_row_visible(self.widget("rng-device"), not is_egd) uiutil.set_grid_row_visible(self.widget("rng-backend-type"), is_egd) backend_type = self.get_config_rng_backend_type() backend_mode = self.get_config_rng_backend_mode() udp = backend_type == virtinst.VirtualRNGDevice.BACKEND_TYPE_UDP bind = backend_mode == virtinst.VirtualRNGDevice.BACKEND_MODE_BIND v = is_egd and (udp or bind) uiutil.set_grid_row_visible(self.widget("rng-bind-host-box"), v) v = is_egd and (udp or not bind) uiutil.set_grid_row_visible(self.widget("rng-connect-host-box"), v) v = is_egd and not udp uiutil.set_grid_row_visible(self.widget("rng-backend-mode"), v) ###################### # Add device methods # ###################### def setup_device(self, asyncjob): logging.debug("Running setup for device=%s", self._dev) self._dev.setup(meter=asyncjob.get_meter()) logging.debug("Setup complete") def add_device(self): self._dev.get_xml_config() logging.debug("Adding device:\n" + self._dev.get_xml_config()) controller = getattr(self._dev, "vmm_controller", None) if controller is not None: logging.debug("Adding controller:\n%s", controller.get_xml_config()) # Hotplug device attach_err = False try: if controller is not None: self.vm.attach_device(controller) self.vm.attach_device(self._dev) except Exception, e: logging.debug("Device could not be hotplugged: %s", str(e)) attach_err = (str(e), "".join(traceback.format_exc())) if attach_err: res = self.err.show_err( _("Are you sure you want to add this device?"), details=(attach_err[0] + "\n\n" + attach_err[1]), text2=( _("This device could not be attached to the running machine. " "Would you like to make the device available after the " "next guest shutdown?")), dialog_type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.YES_NO, modal=True) if not res: return False # Alter persistent config try: if controller is not None: self.vm.add_device(controller) self.vm.add_device(self._dev) except Exception, e: self.err.show_err(_("Error adding device: %s" % str(e))) return True return False def _finish_cb(self, error, details): failure = True if not error: try: failure = self.add_device() except Exception, e: failure = True error = _("Unable to add device: %s") % str(e) details = "".join(traceback.format_exc()) if error is not None: self.err.show_err(error, details=details) self.topwin.set_sensitive(True) self.topwin.get_window().set_cursor( Gdk.Cursor.new(Gdk.CursorType.TOP_LEFT_ARROW)) self._dev = None if not failure: self.close() def finish(self, ignore=None): notebook = self.widget("create-pages") try: if self.validate(notebook.get_current_page()) is False: return except Exception, e: self.err.show_err(_("Uncaught error validating hardware " "input: %s") % str(e)) return self.topwin.set_sensitive(False) self.topwin.get_window().set_cursor( Gdk.Cursor.new(Gdk.CursorType.WATCH)) progWin = vmmAsyncJob(self.setup_device, [], self._finish_cb, [], _("Creating device"), _("Depending on the device, this may take " "a few minutes to complete."), self.topwin) progWin.run() ########################### # Page validation methods # ########################### def _validate(self, page_num): if page_num == PAGE_ERROR: self._dev = None return True elif page_num == PAGE_DISK: return self.validate_page_storage() elif page_num == PAGE_CONTROLLER: return self.validate_page_controller() elif page_num == PAGE_NETWORK: return self.validate_page_network() elif page_num == PAGE_INPUT: return self.validate_page_input() elif page_num == PAGE_GRAPHICS: return self.validate_page_graphics() elif page_num == PAGE_SOUND: return self.validate_page_sound() elif page_num == PAGE_HOSTDEV: return self.validate_page_hostdev() elif page_num == PAGE_CHAR: return self.validate_page_char() elif page_num == PAGE_VIDEO: return self.validate_page_video() elif page_num == PAGE_WATCHDOG: return self.validate_page_watchdog() elif page_num == PAGE_FILESYSTEM: return self.validate_page_filesystem() elif page_num == PAGE_SMARTCARD: return self.validate_page_smartcard() elif page_num == PAGE_USBREDIR: return self.validate_page_usbredir() elif page_num == PAGE_TPM: return self.validate_page_tpm() elif page_num == PAGE_RNG: return self.validate_page_rng() elif page_num == PAGE_PANIC: return self.validate_page_panic() def validate(self, page_num): ret = self._validate(page_num) if ret is not False and self._dev: self._dev.set_defaults(self.vm.get_xmlobj()) self._dev.validate() return ret def _set_disk_controller(self, disk, controller_model, used_disks): # Add a SCSI controller with model virtio-scsi if needed disk.vmm_controller = None if controller_model != "virtio-scsi": return None # Get SCSI controllers controllers = self.vm.get_controller_devices() ctrls_scsi = [x for x in controllers if (x.type == VirtualController.TYPE_SCSI)] # Create possible new controller controller = VirtualController(self.conn.get_backend()) controller.type = "scsi" controller.model = controller_model # And set its index controller.index = 0 if ctrls_scsi: controller.index = max([x.index for x in ctrls_scsi]) + 1 # Take only virtio-scsi ones ctrls_scsi = [x for x in ctrls_scsi if x.model == controller_model] # Save occupied places per controller occupied = collections.defaultdict(int) for d in used_disks: if d.get_target_prefix() == disk.get_target_prefix(): num = virtinst.VirtualDisk.target_to_num(d.target) occupied[num / 7] += 1 for c in ctrls_scsi: if occupied[c.index] < 7: controller = c break else: disk.vmm_controller = controller return controller.index def validate_page_storage(self): bus = self.get_config_disk_bus() device = self.get_config_disk_device() cache = self.get_config_disk_cache() fmt = self.get_config_disk_format() controller_model = None if bus == "virtio-scsi": bus = "scsi" controller_model = "virtio-scsi" collidelist = [d.path for d in self.vm.get_disk_devices()] disk = self.addstorage.validate_storage(self.vm.get_name(), collidelist=collidelist, device=device, fmt=fmt) if disk in [True, False]: return disk try: used = [] disk.bus = bus if cache: disk.driver_cache = cache # Generate target disks = [] if not self.is_customize_dialog: disks = (self.vm.get_disk_devices() + self.vm.get_disk_devices(inactive=True)) for d in disks: if d.target not in used: used.append(d.target) prefer_ctrl = self._set_disk_controller( disk, controller_model, disks) if not self.is_customize_dialog: disk.generate_target(used, prefer_ctrl) except Exception, e: return self.err.val_err(_("Storage parameter error."), e) if self.addstorage.validate_disk_object(disk) is False: return False self._dev = disk return True def validate_page_network(self): nettype = self.netlist.get_network_selection()[0] mac = self.get_config_macaddr() model = self.get_config_net_model() if not nettype: return self.err.val_err(_("Network selection error."), _("A network source must be selected.")) if not mac: return self.err.val_err(_("Invalid MAC address"), _("A MAC address must be entered.")) ret = self.netlist.validate_network(mac, model) if ret is False: return False self._dev = ret def validate_page_input(self): inp_type, inp_bus = self.get_config_input() dev = virtinst.VirtualInputDevice(self.conn.get_backend()) dev.type = inp_type dev.bus = inp_bus self._dev = dev def validate_page_graphics(self): try: (gtype, port, tlsport, addr, passwd, keymap) = self.gfxdetails.get_values() self._dev = virtinst.VirtualGraphics(self.conn.get_backend()) self._dev.type = gtype self._dev.port = port self._dev.passwd = passwd self._dev.listen = addr self._dev.tlsPort = tlsport if keymap: self._dev.keymap = keymap except ValueError, e: self.err.val_err(_("Graphics device parameter error"), e) def validate_page_sound(self): smodel = self.get_config_sound_model() try: self._dev = virtinst.VirtualAudio(self.conn.get_backend()) self._dev.model = smodel except Exception, e: return self.err.val_err(_("Sound device parameter error"), e) def validate_page_hostdev(self): row = self.get_config_host_device_info() is_dup = False if row is None: return self.err.val_err(_("Physical Device Required"), _("A device must be selected.")) devtype = row[2] nodedev = row[3] if devtype == "usb_device": vendor = nodedev.vendor_id product = nodedev.product_id count = self.conn.get_nodedevs_number(devtype, vendor, product) if not count: raise RuntimeError(_("Could not find USB device " "(vendorId: %s, productId: %s) " % (vendor, product))) if count > 1: is_dup = True try: dev = virtinst.VirtualHostDevice(self.conn.get_backend()) dev.set_from_nodedev(nodedev, use_full_usb=is_dup) self._dev = dev except Exception, e: return self.err.val_err(_("Host device parameter error"), e) def validate_page_char(self): charclass = self.get_char_type() modebox = self.widget("char-mode") devbox = self.widget("char-device-type") typebox = self.widget("char-target-type") devtype = uiutil.get_list_selection(devbox, 0) conn = self.conn.get_backend() devclass = charclass(conn) devclass.type = devtype source_path = self.widget("char-path").get_text() source_channel = self.widget("char-channel").get_text() source_mode = uiutil.get_list_selection(modebox, 0) source_host = self.widget("char-host").get_text() bind_host = self.widget("char-bind-host").get_text() source_port = self.widget("char-port").get_value() bind_port = self.widget("char-bind-port").get_value() target_name = self.widget("char-target-name").get_child().get_text() target_type = uiutil.get_list_selection(typebox, 0) if self.widget("char-use-telnet").get_active(): protocol = VirtualSerialDevice.PROTOCOL_TELNET else: protocol = VirtualSerialDevice.PROTOCOL_RAW if not self.widget("char-target-name").get_visible(): target_name = None if not typebox.get_visible(): target_type = None if (self.widget("char-auto-socket").get_visible() and self.widget("char-auto-socket").get_active()): source_path = None source_mode = "bind" value_mappings = { "source_path" : source_path, "source_channel" : source_channel, "source_mode" : source_mode, "source_host" : source_host, "source_port" : source_port, "bind_port": bind_port, "bind_host": bind_host, "protocol": protocol, "target_name": target_name, "target_type": target_type, } try: self._dev = devclass for param_name, val in value_mappings.items(): if self._dev.supports_property(param_name) and val is not None: 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") % charclass.virtual_device_type.capitalize(), e) def validate_page_video(self): conn = self.conn.get_backend() model = self.get_config_video_model() try: self._dev = VirtualVideoDevice(conn) self._dev.model = model except Exception, e: return self.err.val_err(_("Video device parameter error"), e) def validate_page_watchdog(self): conn = self.conn.get_backend() model = self.get_config_watchdog_model() action = self.get_config_watchdog_action() try: self._dev = VirtualWatchdog(conn) self._dev.model = model self._dev.action = action except Exception, e: return self.err.val_err(_("Watchdog parameter error"), e) def validate_page_filesystem(self): if self.fsDetails.validate_page_filesystem() is False: return False self._dev = self.fsDetails.get_dev() def validate_page_smartcard(self): conn = self.conn.get_backend() mode = self.get_config_smartcard_mode() try: self._dev = VirtualSmartCardDevice(conn) self._dev.mode = mode except Exception, e: return self.err.val_err(_("Smartcard device parameter error"), e) def validate_page_usbredir(self): conn = self.conn.get_backend() stype = self.get_config_usbredir_type() host, service = self.get_config_usbredir_host() try: self._dev = VirtualRedirDevice(conn) self._dev.type = stype if host: self._dev.host = host if service: self._dev.service = service except Exception, e: return self.err.val_err(_("USB redirected device parameter error"), str(e)) def validate_page_tpm(self): conn = self.conn.get_backend() typ = self.get_config_tpm_type() device_path = self.widget("tpm-device-path").get_text() value_mappings = { "device_path" : device_path, } try: self._dev = VirtualTPMDevice(conn) self._dev.type = typ for param_name, val in value_mappings.items(): if self._dev.supports_property(param_name): setattr(self._dev, param_name, val) except Exception, e: return self.err.val_err(_("TPM device parameter error"), e) def validate_page_panic(self): conn = self.conn.get_backend() iobase = self.widget("panic-iobase").get_text() value_mappings = { "iobase" : iobase, } try: self._dev = VirtualPanicDevice(conn) if not iobase: iobase = self._dev.IOBASE_DEFAULT for param_name, val in value_mappings.items(): setattr(self._dev, param_name, val) except Exception, e: return self.err.val_err(_("Panic device parameter error"), e) def validate_page_controller(self): conn = self.conn.get_backend() controller_type = self.get_config_controller_type() self._dev = VirtualController(conn) controllers = self.vm.get_controller_devices() controller_num = [x for x in controllers if (x.type == controller_type)] if len(controller_num) > 0: index_new = max([x.index for x in controller_num]) + 1 self._dev.index = index_new self._dev.type = controller_type def validate_page_rng(self): conn = virtinst.VirtualRNGDevice.BACKEND_MODE_CONNECT in \ self.get_config_rng_backend_mode() model = self.get_config_rng_type() is_udp = self.get_config_rng_backend_type() == \ virtinst.VirtualRNGDevice.BACKEND_TYPE_UDP if model == virtinst.VirtualRNGDevice.TYPE_RANDOM: if not self.get_config_rng_device(): return self.err.val_err(_("RNG selection error."), _("A device must be specified.")) elif model == virtinst.VirtualRNGDevice.TYPE_EGD: conn = self.get_config_rng_backend_mode() == \ virtinst.VirtualRNGDevice.BACKEND_MODE_CONNECT if is_udp: if not self.get_config_rng_host(is_connect=conn) or \ not self.get_config_rng_host(is_connect=not conn): return self.err.val_err(_("RNG selection error."), _("Please specify both bind and connect host")) if not int(self.get_config_rng_service(is_connect=conn)) or \ not int(self.get_config_rng_service(is_connect=not conn)): return self.err.val_err(_("RNG selection error."), _("Please specify both bind and connect service")) else: if not self.get_config_rng_host(is_connect=conn): return self.err.val_err(_("RNG selection error."), _("The EGD host must be specified.")) if not int(self.get_config_rng_service(is_connect=conn)): return self.err.val_err(_("RNG selection error."), _("The EGD service must be specified.")) else: return self.err.val_err(_("RNG selection error."), _("Invalid RNG type.")) value_mappings = { "backend_type" : self.get_config_rng_backend_type(), "backend_source_mode" : self.get_config_rng_backend_mode(), "connect_host" : self.get_config_rng_host(is_connect=True), "connect_service" : self.get_config_rng_service(is_connect=True), "bind_host" : self.get_config_rng_host(), "bind_service" : self.get_config_rng_service(), "device" : self.get_config_rng_device(), } try: self._dev = virtinst.VirtualRNGDevice(conn) self._dev.type = self.get_config_rng_type() for param_name, val in value_mappings.items(): if self._dev.supports_property(param_name): setattr(self._dev, param_name, val) except Exception, e: return self.err.val_err(_("RNG device parameter error"), e) #################### # Unsorted helpers # #################### def _browse_storage_cb(self, ignore, widget): self._browse_file(widget) def _browse_file(self, textent, isdir=False): def set_storage_cb(src, path): if path: textent.set_text(path) conn = self.conn reason = (isdir and self.config.CONFIG_DIR_FS or self.config.CONFIG_DIR_IMAGE) if self.storage_browser is None: self.storage_browser = vmmStorageBrowser(conn) self.storage_browser.stable_defaults = self.vm.stable_defaults() self.storage_browser.set_finish_cb(set_storage_cb) self.storage_browser.set_browse_reason(reason) self.storage_browser.show(self.topwin, conn)