[virt-tools-list] [virt-manager PATCH 3/3] Add logic for GUI support for TPM passthrough

Stefan Berger stefanb at linux.vnet.ibm.com
Mon Jun 24 21:58:08 UTC 2013


Add the code woking 'behind' the GUI.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
---
 virtManager/addhardware.py | 69 +++++++++++++++++++++++++++++++++++++++++++++-
 virtManager/details.py     | 59 +++++++++++++++++++++++++++++++++++++--
 virtManager/domain.py      | 10 +++++++
 virtManager/uihelpers.py   | 29 +++++++++++++++++++
 4 files changed, 163 insertions(+), 4 deletions(-)

diff --git a/virtManager/addhardware.py b/virtManager/addhardware.py
index 62d69e7..7b44cee 100644
--- a/virtManager/addhardware.py
+++ b/virtManager/addhardware.py
@@ -30,7 +30,7 @@ import virtinst
 from virtinst import (VirtualCharDevice,
                       VirtualVideoDevice, VirtualWatchdog,
                       VirtualFilesystem, VirtualSmartCardDevice,
-                      VirtualRedirDevice)
+                      VirtualRedirDevice, VirtualTPMDevice)
 from virtinst.VirtualController import VirtualControllerSCSI
 
 import virtManager.util as util
@@ -52,6 +52,7 @@ PAGE_WATCHDOG = 9
 PAGE_FILESYSTEM = 10
 PAGE_SMARTCARD = 11
 PAGE_USBREDIR = 12
+PAGE_TPM = 13
 
 char_widget_mappings = {
     "source_path" : "char-path",
@@ -65,6 +66,10 @@ char_widget_mappings = {
 }
 
 
+tpm_widget_mappings = {
+    "device_path" : "tpm-device-path",
+}
+
 class vmmAddHardware(vmmGObjectUI):
     def __init__(self, vm):
         vmmGObjectUI.__init__(self, "vmm-add-hardware.ui", "vmm-add-hardware")
@@ -95,6 +100,8 @@ class vmmAddHardware(vmmGObjectUI):
 
             "on_char_device_type_changed": self.change_char_device_type,
 
+            "on_tpm_device_type_changed": self.change_tpm_device_type,
+
             "on_fs_type_combo_changed": self.change_fs_type,
             "on_fs_driver_combo_changed": self.change_fs_driver,
             "on_fs_source_browse_clicked": self.browse_fs_source,
@@ -347,6 +354,10 @@ class vmmAddHardware(vmmGObjectUI):
         combo = self.widget("usbredir-list")
         uihelpers.build_redir_type_combo(self.vm, combo)
 
+        # TPM widgets
+        combo = self.widget("tpm-type")
+        uihelpers.build_tpm_type_combo(self.vm, combo)
+
         # Available HW options
         is_local = not self.conn.is_remote()
         is_storage_capable = self.conn.is_storage_capable()
@@ -413,6 +424,8 @@ class vmmAddHardware(vmmGObjectUI):
                       True, None)
         add_hw_option("USB Redirection", "device_usb", PAGE_USBREDIR,
                       True, None)
+        add_hw_option("TPM", "device_cpu", PAGE_TPM,
+                      True, None)
 
     def reset_state(self):
         # Storage init
@@ -808,6 +821,12 @@ class vmmAddHardware(vmmGObjectUI):
         typebox = self.widget("usbredir-list")
         return typebox.get_model()[typebox.get_active()][0]
 
+    # TPM getters
+    def get_config_tpm_type(self):
+        type = self.widget("tpm-type")
+        typestr = type.get_model().get_value(type.get_active_iter(), 0)
+        return typestr
+
     ################
     # UI listeners #
     ################
@@ -1006,6 +1025,8 @@ class vmmAddHardware(vmmGObjectUI):
             return _("Smartcard")
         if page == PAGE_USBREDIR:
             return _("USB Redirection")
+        if page == PAGE_TPM:
+            return _("TPM")
 
         if page == PAGE_CHAR:
             return self.get_char_type().capitalize() + " Device"
@@ -1020,6 +1041,29 @@ class vmmAddHardware(vmmGObjectUI):
                   """foreground="#FFF">%s</span>""") % title
         self.widget("page-title-label").set_markup(markup)
 
+    def change_tpm_device_type(self, src):
+        idx = src.get_active()
+        if idx < 0:
+            return
+
+        devtype = src.get_model()[src.get_active()][0]
+        conn = self.conn.vmm
+
+        self._dev = VirtualTPMDevice.get_dev_instance(conn,
+                                                      devtype)
+
+        show_something = False
+        for param_name, widget_name in tpm_widget_mappings.items():
+            make_visible = self._dev.supports_property(param_name)
+            if make_visible:
+                show_something = True
+
+            self.widget(widget_name).set_property("visible", make_visible)
+            self.widget(widget_name + "-label").set_property("visible",
+                                                             make_visible)
+
+        self.widget("tpm-param-box").set_property("visible", show_something)
+
     def change_char_device_type(self, src):
         self._update_doc("char_type")
         idx = src.get_active()
@@ -1229,6 +1273,8 @@ class vmmAddHardware(vmmGObjectUI):
             return self.validate_page_smartcard()
         elif page_num == PAGE_USBREDIR:
             return self.validate_page_usbredir()
+        elif page_num == PAGE_TPM:
+            return self.validate_page_tpm()
 
     def validate_page_storage(self):
         bus, device = self.get_config_disk_target()
@@ -1577,6 +1623,27 @@ class vmmAddHardware(vmmGObjectUI):
             return self.err.val_err(_("USB redirected device parameter error"),
                                     str(e))
 
+    def validate_page_tpm(self):
+        conn = self.conn.vmm
+        type = self.get_config_tpm_type()
+
+        device_path = self.widget("tpm-device-path").get_text()
+
+        value_mappings = {
+            "device_path" : device_path,
+        }
+
+        try:
+            self._dev = VirtualTPMDevice.get_dev_instance(conn, type)
+
+            for param_name, val in value_mappings.items():
+                if self._dev.supports_property(param_name):
+                    setattr(self._dev, param_name, val)
+
+            # Dump XML for sanity checking
+            self._dev.get_xml_config()
+        except Exception, e:
+            return self.err.val_err(_("TPM device parameter error"), e)
 
     ####################
     # Unsorted helpers #
diff --git a/virtManager/details.py b/virtManager/details.py
index b2d496e..dcbdc83 100644
--- a/virtManager/details.py
+++ b/virtManager/details.py
@@ -43,7 +43,7 @@ import virtinst
 
 
 # Parameters that can be editted in the details window
-EDIT_TOTAL = 37
+EDIT_TOTAL = 38
 (EDIT_NAME,
 EDIT_ACPI,
 EDIT_APIC,
@@ -91,7 +91,9 @@ EDIT_VIDEO_MODEL,
 EDIT_WATCHDOG_MODEL,
 EDIT_WATCHDOG_ACTION,
 
-EDIT_CONTROLLER_MODEL
+EDIT_CONTROLLER_MODEL,
+
+EDIT_TPM_TYPE,
 ) = range(EDIT_TOTAL)
 
 
@@ -121,13 +123,14 @@ HW_LIST_TYPE_CONTROLLER = 14
 HW_LIST_TYPE_FILESYSTEM = 15
 HW_LIST_TYPE_SMARTCARD = 16
 HW_LIST_TYPE_REDIRDEV = 17
+HW_LIST_TYPE_TPM = 18
 
 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_SMARTCARD,
-                HW_LIST_TYPE_REDIRDEV]
+                HW_LIST_TYPE_REDIRDEV, HW_LIST_TYPE_TPM]
 
 # Boot device columns
 BOOT_DEV_TYPE = 0
@@ -499,6 +502,9 @@ class vmmDetails(vmmGObjectUI):
             "on_smartcard_mode_combo_changed": lambda *x: self.enable_apply(x,
                                                 EDIT_SMARTCARD_MODE),
 
+            "on_tpm_type_combo_changed": (self.enable_apply,
+                                          EDIT_TPM_TYPE),
+
             "on_config_apply_clicked": self.config_apply,
             "on_config_cancel_clicked": self.config_cancel,
 
@@ -1333,6 +1339,8 @@ class vmmDetails(vmmGObjectUI):
                 self.refresh_smartcard_page()
             elif pagetype == HW_LIST_TYPE_REDIRDEV:
                 self.refresh_redir_page()
+            elif pagetype == HW_LIST_TYPE_TPM:
+                self.refresh_tpm_page()
             else:
                 pagetype = -1
         except Exception, e:
@@ -2034,6 +2042,8 @@ class vmmDetails(vmmGObjectUI):
                 ret = self.config_smartcard_apply(key)
             elif pagetype is HW_LIST_TYPE_CONTROLLER:
                 ret = self.config_controller_apply(key)
+            elif pagetype is HW_LIST_TYPE_TPM:
+                ret = self.config_tpm_apply(key)
             else:
                 ret = False
         except Exception, e:
@@ -2346,6 +2356,18 @@ class vmmDetails(vmmGObjectUI):
 
         return self._change_config_helper(df, da, hf, ha)
 
+    # TPM options
+    def config_tpm_apply(self, dev_id_info):
+        df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
+        ignore = add_hotplug
+
+        if self.editted(EDIT_TPM_TYPE):
+            type = self.get_combo_label_value("tpm-type")
+            if type:
+                add_define(self.vm.define_tpm_type, dev_id_info, type)
+
+        return self._change_config_helper(df, da, hf, ha)
+
     # Network options
     def config_network_apply(self, dev_id_info):
         df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
@@ -3182,6 +3204,32 @@ class vmmDetails(vmmGObjectUI):
         self.widget("redir-type-label").set_text(rd.type)
         self.widget("redir-type-combo").hide()
 
+    def refresh_tpm_page(self):
+        tpmdev = self.get_hw_selection(HW_LIST_COL_DEVICE)
+        if not tpmdev:
+            return
+
+        def show_ui(param, val=None):
+            widgetname = "tpm-" + param.replace("_", "-")
+            labelname = widgetname + "-label"
+            doshow = tpmdev.supports_property(param)
+
+            if not val and doshow:
+                val = getattr(tpmdev, param)
+
+            self.widget(widgetname).set_property("visible", doshow)
+            self.widget(labelname).set_property("visible", doshow)
+            self.widget(widgetname).set_text(val or "-")
+
+        tpm_type = tpmdev.virtual_device_type.capitalize()
+
+        dev_type = tpmdev.type
+
+        self.widget("tpm-dev-type").set_text(dev_type)
+
+        # Device type specific properties, only show if apply to the cur dev
+        show_ui("device_path")
+
     def refresh_char_page(self):
         chardev = self.get_hw_selection(HW_LIST_COL_DEVICE)
         if not chardev:
@@ -3618,6 +3666,11 @@ class vmmDetails(vmmGObjectUI):
             update_hwlist(HW_LIST_TYPE_SMARTCARD, sc,
                           _("Smartcard"), "device_serial")
 
+        # Populate list of TPM devices
+        for tpm in self.vm.get_tpm_devices():
+            update_hwlist(HW_LIST_TYPE_TPM, tpm,
+                          _("TPM"), "device_cpu")
+
         devs = range(len(hw_list_model))
         devs.reverse()
         for i in devs:
diff --git a/virtManager/domain.py b/virtManager/domain.py
index bd3d964..7ead272 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -55,6 +55,7 @@ def compare_device(origdev, newdev, idx):
         "filesystem" : ["target" , "vmmindex"],
         "smartcard" : ["mode" , "vmmindex"],
         "redirdev" : ["bus" , "type", "vmmindex"],
+        "tpm"       : ["type" , "vmmindex"],
     }
 
     if id(origdev) == id(newdev):
@@ -824,6 +825,13 @@ class vmmDomain(vmmLibvirtObject):
 
         return self._redefine_device(change, devobj)
 
+    # TPM define methods
+
+    def define_tpm_type(self, devobj, newtype):
+        def change(editdev):
+            editdev.type = newtype
+        return self._redefine_device(change, devobj)
+
 
 
     ####################
@@ -1079,6 +1087,8 @@ class vmmDomain(vmmLibvirtObject):
         return self._build_device_list("smartcard")
     def get_redirdev_devices(self):
         return self._build_device_list("redirdev")
+    def get_tpm_devices(self):
+        return self._build_device_list("tpm")
 
     def get_disk_devices(self, refresh_if_necc=True, inactive=False):
         devs = self._build_device_list("disk", refresh_if_necc, inactive)
diff --git a/virtManager/uihelpers.py b/virtManager/uihelpers.py
index ba69ee9..464c933 100644
--- a/virtManager/uihelpers.py
+++ b/virtManager/uihelpers.py
@@ -311,6 +311,35 @@ def populate_redir_type_combo(vm, combo):
     model.append(["tcp", "TCP", True])
 
 
+def build_tpm_type_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.SortType.ASCENDING)
+
+    populate_tpm_type_combo(vm, combo)
+
+    idx = -1
+    for rowid in range(len(combo.get_model())):
+        idx = 0
+        row = combo.get_model()[rowid]
+        if row[0] == virtinst.VirtualTPMDevice.TYPE_DEFAULT:
+            idx = rowid
+            break
+    combo.set_active(idx)
+
+def populate_tpm_type_combo(vm, combo):
+    ignore = vm
+    types = combo.get_model()
+    types.clear()
+
+    # [xml value, label]
+    types.append(["passthrough", "Passthrough device (passthrough)"])
+
+
+
 def build_netmodel_combo(vm, combo):
     dev_model = Gtk.ListStore(str, str)
     combo.set_model(dev_model)
-- 
1.8.1.4




More information about the virt-tools-list mailing list