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
+
+