diff --git a/src/virtManager/addhardware.py b/src/virtManager/addhardware.py index c5a091532..1209bf406 100644 --- a/src/virtManager/addhardware.py +++ b/src/virtManager/addhardware.py @@ -24,8 +24,9 @@ import traceback import gtk import virtinst -from virtinst import (VirtualCharDevice, VirtualDevice, VirtualVideoDevice, - VirtualWatchdog, VirtualFilesystem) +from virtinst import (VirtualCharDevice, VirtualDevice, + VirtualVideoDevice, VirtualWatchdog, + VirtualFilesystem, VirtualSmartCardDevice) import virtManager.util as util import virtManager.uihelpers as uihelpers @@ -45,6 +46,7 @@ PAGE_CHAR = 7 PAGE_VIDEO = 8 PAGE_WATCHDOG = 9 PAGE_FILESYSTEM = 10 +PAGE_SMARTCARD = 11 char_widget_mappings = { "source_path" : "char-path", @@ -329,6 +331,10 @@ class vmmAddHardware(vmmGObjectUI): simple_store_set("fs-mode-combo", VirtualFilesystem.MOUNT_MODES) self.show_pair_combo("fs-type", self.conn.is_openvz()) + # Smartcard widgets + combo = self.window.get_widget("smartcard-mode") + uihelpers.build_smartcard_mode_combo(self.vm, combo) + # Available HW options is_local = not self.conn.is_remote() is_storage_capable = self.conn.is_storage_capable() @@ -391,6 +397,8 @@ class vmmAddHardware(vmmGObjectUI): self.vm.get_hv_type()), _("Not supported for this hypervisor/libvirt " "combination.")) + add_hw_option("Smartcard", "device_serial", PAGE_SMARTCARD, + True, None) def reset_state(self): # Storage init @@ -717,6 +725,12 @@ class vmmAddHardware(vmmGObjectUI): return combo.get_model()[combo.get_active()][0] + # Smartcard getters + def get_config_smartcard_mode(self): + mode = self.window.get_widget("smartcard-mode") + modestr = mode.get_model().get_value(mode.get_active_iter(), 0) + return modestr + ################ # UI listeners # ################ @@ -900,6 +914,8 @@ class vmmAddHardware(vmmGObjectUI): return _("Watchdog Device") if page == PAGE_FILESYSTEM: return _("Filesystem Passthrough") + if page == PAGE_SMARTCARD: + return _("Smartcard") if page == PAGE_CHAR: return self.get_char_type().capitalize() + " Device" @@ -1071,6 +1087,8 @@ class vmmAddHardware(vmmGObjectUI): 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() def validate_page_storage(self): bus, device = self.get_config_disk_target() @@ -1328,6 +1346,16 @@ class vmmAddHardware(vmmGObjectUI): return self.err.val_err(_("Filesystem parameter error"), str(e)) + def validate_page_smartcard(self): + conn = self.conn.vmm + mode = self.get_config_smartcard_mode() + + try: + self._dev = VirtualSmartCardDevice(conn, mode) + except Exception, e: + return self.err.val_err(_("Video device parameter error"), + str(e)) + #################### # Unsorted helpers # diff --git a/src/virtManager/details.py b/src/virtManager/details.py index e3d7c4ac2..0f6ecfb1a 100644 --- a/src/virtManager/details.py +++ b/src/virtManager/details.py @@ -61,12 +61,13 @@ HW_LIST_TYPE_VIDEO = 12 HW_LIST_TYPE_WATCHDOG = 13 HW_LIST_TYPE_CONTROLLER = 14 HW_LIST_TYPE_FILESYSTEM = 15 +HW_LIST_TYPE_SMARTCARD = 16 remove_pages = [HW_LIST_TYPE_NIC, HW_LIST_TYPE_INPUT, HW_LIST_TYPE_GRAPHICS, HW_LIST_TYPE_SOUND, HW_LIST_TYPE_CHAR, HW_LIST_TYPE_HOSTDEV, HW_LIST_TYPE_DISK, HW_LIST_TYPE_VIDEO, HW_LIST_TYPE_WATCHDOG, HW_LIST_TYPE_CONTROLLER, - HW_LIST_TYPE_FILESYSTEM] + HW_LIST_TYPE_FILESYSTEM, HW_LIST_TYPE_SMARTCARD] # Boot device columns BOOT_DEV_TYPE = 0 @@ -360,6 +361,8 @@ class vmmDetails(vmmGObjectUI): "on_watchdog_model_combo_changed": self.config_enable_apply, "on_watchdog_action_combo_changed": self.config_enable_apply, + "on_smartcard_mode_combo_changed": self.config_enable_apply, + "on_config_apply_clicked": self.config_apply, "on_details_help_activate": self.show_help, @@ -776,6 +779,10 @@ class vmmDetails(vmmGObjectUI): uihelpers.build_watchdogaction_combo(self.vm, combo, no_default=no_default) + # Smartcard mode + sc_mode = self.window.get_widget("smartcard-mode-combo") + uihelpers.build_smartcard_mode_combo(self.vm, sc_mode) + # Helper function to handle the combo/label pattern used for # video model, sound model, network model, etc. def set_combo_label(self, prefix, value, model_idx=0, label="", @@ -1023,6 +1030,8 @@ class vmmDetails(vmmGObjectUI): self.refresh_controller_page() elif pagetype == HW_LIST_TYPE_FILESYSTEM: self.refresh_filesystem_page() + elif pagetype == HW_LIST_TYPE_SMARTCARD: + self.refresh_smartcard_page() else: pagetype = -1 except Exception, e: @@ -1630,6 +1639,8 @@ class vmmDetails(vmmGObjectUI): ret = self.config_video_apply(key) elif pagetype is HW_LIST_TYPE_WATCHDOG: ret = self.config_watchdog_apply(key) + elif pagetype is HW_LIST_TYPE_SMARTCARD: + ret = self.config_smartcard_apply(key) else: ret = False except Exception, e: @@ -1842,6 +1853,13 @@ class vmmDetails(vmmGObjectUI): return self._change_config_helper(self.vm.define_sound_model, (dev_id_info, model)) + # Smartcard options + def config_smartcard_apply(self, dev_id_info): + model = self.get_combo_label_value("smartcard-mode") + if model: + return self._change_config_helper(self.vm.define_smartcard_mode, + (dev_id_info, model)) + # Network options def config_network_apply(self, dev_id_info): net_list = self.window.get_widget("network-source-combo") @@ -2542,6 +2560,13 @@ class vmmDetails(vmmGObjectUI): self.set_combo_label("sound-model", sound.model) + def refresh_smartcard_page(self): + sc = self.get_hw_selection(HW_LIST_COL_DEVICE) + if not sc: + return + + self.set_combo_label("smartcard-mode", sc.mode) + def refresh_char_page(self): chardev = self.get_hw_selection(HW_LIST_COL_DEVICE) if not chardev: @@ -2912,6 +2937,11 @@ class vmmDetails(vmmGObjectUI): _("Filesystem %s") % target, gtk.STOCK_DIRECTORY) + # Populate list of smartcard devices + for sc in self.vm.get_smartcard_devices(): + update_hwlist(HW_LIST_TYPE_SMARTCARD, sc, + _("Smartcard"), "device_serial") + devs = range(len(hw_list_model)) devs.reverse() for i in devs: diff --git a/src/virtManager/domain.py b/src/virtManager/domain.py index 1e6826371..5f97bf6da 100644 --- a/src/virtManager/domain.py +++ b/src/virtManager/domain.py @@ -47,6 +47,7 @@ def compare_device(origdev, newdev, idx): "controller" : ["type", "index"], "channel" : ["char_type", "target_name"], "filesystem" : ["target" , "vmmindex"], + "smartcard" : ["mode" , "vmmindex"], } if id(origdev) == id(newdev): @@ -633,6 +634,13 @@ class vmmDomain(vmmLibvirtObject): editdev.action = newval return self._redefine_device(change, devobj) + # Smartcard define methods + + def define_smartcard_mode(self, devobj, newmodel): + def change(editdev): + editdev.mode = newmodel + return self._redefine_device(change, devobj) + #################### # Hotplug routines # @@ -890,6 +898,8 @@ class vmmDomain(vmmLibvirtObject): return self._build_device_list("controller") def get_filesystem_devices(self): return self._build_device_list("filesystem") + def get_smartcard_devices(self): + return self._build_device_list("smartcard") def get_disk_devices(self, refresh_if_necc=True, inactive=False): devs = self._build_device_list("disk", refresh_if_necc, inactive) diff --git a/src/virtManager/uihelpers.py b/src/virtManager/uihelpers.py index 1dc482fe1..ea87faae9 100644 --- a/src/virtManager/uihelpers.py +++ b/src/virtManager/uihelpers.py @@ -214,6 +214,36 @@ def populate_source_mode_combo(vm, combo): model.append(["private", "Private"]) model.append(["passthrough", "Passthrough"]) +def build_smartcard_mode_combo(vm, combo): + dev_model = gtk.ListStore(str, str) + combo.set_model(dev_model) + text = gtk.CellRendererText() + combo.pack_start(text, True) + combo.add_attribute(text, 'text', 1) + dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING) + + 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) + +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"]) +# TODO +# model.append(["host-certificates", "Host Certificates"]) + def build_netmodel_combo(vm, combo): dev_model = gtk.ListStore(str, str) combo.set_model(dev_model) diff --git a/src/vmm-add-hardware.glade b/src/vmm-add-hardware.glade index e5d8dabac..8d8258d17 100644 --- a/src/vmm-add-hardware.glade +++ b/src/vmm-add-hardware.glade @@ -2204,11 +2204,85 @@ access in the guest. 1 + 10 + + + True + 1 + + + True + 12 + + + True + 0 + Please indicate what smartcard device mode to connect to the virtual machine. + True + True + + + False + False + 0 + + + + + True + 24 + + + True + 2 + 12 + 12 + + + True + + + 1 + 2 + GTK_FILL + + + + + True + 1 + _Mode: + True + smartcard-mode + + + GTK_FILL + + + + + + + + False + 1 + + + + + 0 + + + + + 5 + + True diff --git a/src/vmm-details.glade b/src/vmm-details.glade index 2d69c27d6..d5353a487 100644 --- a/src/vmm-details.glade +++ b/src/vmm-details.glade @@ -5492,6 +5492,106 @@ I/O: tab + + + True + + + True + 0 + none + + + True + 3 + 12 + + + True + 3 + 2 + 8 + 4 + + + True + 0 + M_ode: + True + smartcard-mode-combo + + + GTK_FILL + + + + + + True + + + True + + + + 0 + + + + + True + 0 + insert smartcard mode + True + + + 1 + + + + + 1 + 2 + GTK_FILL + + 1 + + + + + + + + + True + <b>Smartcard Device</b> + True + + + label_item + + + + + 0 + + + + + 9 + + + + + True + snd + + + 9 + False + tab + +