mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-12-23 17:34:21 +03:00
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:
parent
cfbc5e58f5
commit
9c600597c8
@ -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 #
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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"><b>Smartcard Device</b></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>
|
||||
|
Loading…
Reference in New Issue
Block a user