[virt-tools-list] [PATCH] wip: add basic SmartCardDevice support

Marc-André Lureau marcandre.lureau at gmail.com
Thu Jun 23 15:42:03 UTC 2011


From: Marc-André Lureau <marcandre.lureau at redhat.com>

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.

(The patch requires python-virtinst support sent earlier)
---
 src/virtManager/addhardware.py |   29 +++++++++++-
 src/virtManager/details.py     |   32 ++++++++++++-
 src/virtManager/domain.py      |   10 ++++
 src/virtManager/uihelpers.py   |   22 +++++++++
 src/vmm-add-hardware.glade     |   74 +++++++++++++++++++++++++++++
 src/vmm-details.glade          |  100 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 265 insertions(+), 2 deletions(-)

diff --git a/src/virtManager/addhardware.py b/src/virtManager/addhardware.py
index ea96356..fe3bcee 100644
--- a/src/virtManager/addhardware.py
+++ b/src/virtManager/addhardware.py
@@ -25,7 +25,7 @@ import gtk
 
 import virtinst
 from virtinst import (VirtualCharDevice, VirtualDevice, VirtualVideoDevice,
-                      VirtualWatchdog, VirtualFilesystem)
+                      VirtualWatchdog, VirtualFilesystem, VirtualSmartCardDevice)
 
 import virtManager.util as util
 import virtManager.uihelpers as uihelpers
@@ -45,6 +45,7 @@ PAGE_CHAR = 7
 PAGE_VIDEO = 8
 PAGE_WATCHDOG = 9
 PAGE_FILESYSTEM = 10
+PAGE_SMARTCARD = 11
 
 char_widget_mappings = {
     "source_path" : "char-path",
@@ -345,6 +346,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()
@@ -407,6 +412,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
@@ -733,6 +740,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 #
     ################
@@ -909,6 +922,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"
@@ -1083,6 +1098,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()
@@ -1340,6 +1357,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 9a0d562..763050e 100644
--- a/src/virtManager/details.py
+++ b/src/virtManager/details.py
@@ -62,12 +62,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
@@ -369,6 +370,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,
@@ -802,6 +805,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:
@@ -1638,6 +1647,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:
@@ -1850,6 +1861,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")
@@ -2550,6 +2568,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:
@@ -2920,6 +2945,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: %s" % sc.mode), "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 674ebcd..eb5299a 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 #
@@ -899,6 +907,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 1dc482f..4abcf50 100644
--- a/src/virtManager/uihelpers.py
+++ b/src/virtManager/uihelpers.py
@@ -214,6 +214,28 @@ 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)
+    combo.set_active(0)
+
+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 5eb218c..dcac618 100644
--- a/src/vmm-add-hardware.glade
+++ b/src/vmm-add-hardware.glade
@@ -2181,12 +2181,86 @@ and default action should be used.</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>
                             <property name="label">fs</property>
diff --git a/src/vmm-details.glade b/src/vmm-details.glade
index 2d69c27..218639c 100644
--- a/src/vmm-details.glade
+++ b/src/vmm-details.glade
@@ -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">Smartcard 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>
-- 
1.7.5.2




More information about the virt-tools-list mailing list