Add basic SmartCardDevice support

This patch allows to add and list smartcard devices in host or
passthrough & spicevmc mode.

It doesn't provide all the various smartcard combination
options, but it's good enough for Spice usage.

(crobinso: various small tweaks)
This commit is contained in:
Marc-André Lureau 2011-06-23 17:42:03 +02:00 committed by Cole Robinson
parent cfbc5e58f5
commit 9c600597c8
6 changed files with 275 additions and 3 deletions

View File

@ -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 #

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -2204,11 +2204,85 @@ access in the guest.</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">10</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="page5-box">
<property name="visible">True</property>
<property name="border_width">1</property>
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="spacing">12</property>
<child>
<widget class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Please indicate what smartcard device mode to connect to the virtual machine.</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment4">
<property name="visible">True</property>
<property name="left_padding">24</property>
<child>
<widget class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="n_columns">2</property>
<property name="column_spacing">12</property>
<property name="row_spacing">12</property>
<child>
<widget class="GtkComboBox" id="smartcard-mode">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">_Mode:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">smartcard-mode</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="position">5</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label14">
<property name="visible">True</property>

View File

@ -5492,6 +5492,106 @@ I/O:</property>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox58">
<property name="visible">True</property>
<child>
<widget class="GtkFrame" id="frame13">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<widget class="GtkAlignment" id="alignment159">
<property name="visible">True</property>
<property name="top_padding">3</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkTable" id="table36">
<property name="visible">True</property>
<property name="border_width">3</property>
<property name="n_columns">2</property>
<property name="column_spacing">8</property>
<property name="row_spacing">4</property>
<child>
<widget class="GtkLabel" id="label452">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">M_ode:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">smartcard-mode-combo</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox11">
<property name="visible">True</property>
<child>
<widget class="GtkComboBox" id="smartcard-mode-combo">
<property name="visible">True</property>
<signal name="changed" handler="on_smartcard_mode_combo_changed"/>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="smartcard-mode-label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label">insert smartcard mode</property>
<property name="selectable">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_padding">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label451">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Smartcard Device&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="position">9</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label440">
<property name="visible">True</property>
<property name="label">snd</property>
</widget>
<packing>
<property name="position">9</property>
<property name="tab_fill">False</property>
<property name="type">tab</property>
</packing>
</child>
</widget>
</child>
</widget>