Ver código fonte

Add handling for virt_mode including PVH mode

HW42 6 anos atrás
pai
commit
ebc7426cab
2 arquivos alterados com 224 adições e 3 exclusões
  1. 109 0
      qubesmanager/settings.py
  2. 115 3
      ui/settingsdlg.ui

+ 109 - 0
qubesmanager/settings.py

@@ -28,6 +28,7 @@ import collections
 import copy
 import os
 import os.path
+import re
 import subprocess
 import sys
 import threading
@@ -462,6 +463,7 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
                 self.kernel, self.vm, 'kernel',
                 self.vm.app.default_kernel,
                 allow_default=True, allow_none=True)
+            self.kernel.currentIndexChanged.connect(self.kernel_changed)
         else:
             self.kernel_groupbox.setVisible(False)
 
@@ -479,6 +481,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
                     (lambda vm: vm.klass == 'DispVM'),
                     allow_default=True, allow_none=True)
 
+        self.update_virt_mode_list()
+
     def __apply_advanced_tab__(self):
         msg = []
 
@@ -518,12 +522,105 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
         except Exception as ex:
             msg.append(str(ex))
 
+        try:
+            if self.virt_mode.currentIndex() != self.virt_mode_idx:
+                self.vm.virt_mode = self.selected_virt_mode()
+                self.anything_changed = True
+        except Exception as ex:
+            msg.append(str(ex))
+
         return msg
 
     def boot_from_cdrom_button_pressed(self):
         self.save_and_apply()
         subprocess.check_call(['qubes-vm-boot-from-device', self.vm.name])
 
+    def selected_virt_mode(self):
+        return self.virt_mode_list[self.virt_mode.currentIndex()]
+
+    def virt_mode_changed(self, new_idx):
+        self.update_pv_warning()
+        self.update_pvh_dont_support_devs()
+        self.update_pvh_kernel_version_warning()
+
+    def update_pv_warning(self):
+        if self.selected_virt_mode() == 'pv':
+            self.pv_warning.show()
+        else:
+            self.pv_warning.hide()
+
+    def update_virt_mode_list(self):
+        choices = ['hvm', 'pv']
+
+        if hasattr(self, 'dev_list'):
+            devs_attached = self.dev_list.selected_list.count() != 0
+        else:
+            devs_attached = len(list(self.vm.devices['pci'].persistent())) != 0
+
+        if devs_attached:
+            self.pvh_mode_hidden.show()
+        else:
+            choices.insert(0, 'pvh')
+            self.pvh_mode_hidden.hide()
+
+        if hasattr(self, 'virt_mode_list'):
+            old_mode = self.selected_virt_mode()
+            self.virt_mode.currentIndexChanged.disconnect()
+        else:
+            old_mode = None
+
+        self.virt_mode.clear()
+
+        # XXX: Hardcoded default value.
+        self.virt_mode_list, self.virt_mode_idx = utils.prepare_choice(
+                self.virt_mode, self.vm, 'virt_mode', choices, 'hvm',
+                allow_default=True)
+
+        if old_mode is not None:
+            self.virt_mode.setCurrentIndex(self.virt_mode_list.index(old_mode))
+
+        self.virt_mode.currentIndexChanged.connect(self.virt_mode_changed)
+
+        self.update_pv_warning()
+        self.update_pvh_kernel_version_warning()
+
+    def update_pvh_kernel_version_warning(self):
+        if self.selected_virt_mode() != 'pvh':
+            self.pvh_kernel_version_warning.hide()
+            return
+
+        kernel = self.kernel_list[self.kernel.currentIndex()]
+
+        if self.pvh_kernel_version_ok(kernel):
+            self.pvh_kernel_version_warning.hide()
+        else:
+            self.pvh_kernel_version_warning.show()
+
+    def kernel_changed(self):
+        self.update_pvh_kernel_version_warning()
+
+    def pvh_kernel_version_ok(self, name):
+        # There are nearly no limitaions on kernel names (only file system and
+        # general qvm-prefs rules). So we just look if we see something which
+        # looks like a version number. It's just a warning to help the user
+        # anyways.
+
+        if name is None:
+            return False
+
+        if name is qubesadmin.DEFAULT:
+            name = self.vm.app.default_kernel
+
+        m = re.search('(\d+)\.(\d+)', name)
+
+        if m is None:
+            return False
+
+        x = int(m.group(1))
+        y = int(m.group(2))
+
+        return (x, y) >= (4, 11)
+
     ######## devices tab
     def __init_devices_tab__(self):
         self.dev_list = multiselectwidget.MultiSelectWidget(self)
@@ -566,6 +663,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
             self.dev_list.setEnabled(True)
             self.turn_off_vm_to_modify_devs.setVisible(False)
 
+        self.update_pvh_dont_support_devs()
+
 
     def __apply_devices_tab__(self):
         msg = []
@@ -621,6 +720,16 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
                 self.dmm_warning_adv.hide()
                 self.dmm_warning_dev.hide()
 
+        self.update_virt_mode_list()
+
+    def update_pvh_dont_support_devs(self):
+        if self.selected_virt_mode() == 'pvh':
+            self.dev_list.setEnabled(False)
+            self.pvh_dont_support_devs.setVisible(True)
+        else:
+            self.dev_list.setEnabled(True)
+            self.pvh_dont_support_devs.setVisible(False)
+
     ######## applications tab
 
     def refresh_apps_in_vm(self, t_monitor):

+ 115 - 3
ui/settingsdlg.ui

@@ -409,7 +409,7 @@
               <property name="fieldGrowthPolicy">
                <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
               </property>
-              <item row="0" column="0">
+              <item row="0" column="0" rowspan="2">
                <widget class="QLabel" name="label_19">
                 <property name="text">
                  <string>Kernel:</string>
@@ -422,14 +422,31 @@
               <item row="0" column="1">
                <widget class="QComboBox" name="kernel"/>
               </item>
-              <item row="1" column="0">
+              <item row="1" column="1">
+               <widget class="QLabel" name="pvh_kernel_version_warning">
+                <property name="font">
+                 <font>
+                  <weight>75</weight>
+                  <italic>true</italic>
+                  <bold>true</bold>
+                 </font>
+                </property>
+                <property name="text">
+                 <string>PVH mode requires Linux 4.11 or newer.</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="0">
                <widget class="QLabel" name="label_20">
                 <property name="text">
                  <string>Kernel opts:</string>
                 </property>
                </widget>
               </item>
-              <item row="1" column="1">
+              <item row="2" column="1">
                <widget class="QLabel" name="kernel_opts">
                 <property name="font">
                  <font>
@@ -447,6 +464,87 @@
            </item>
           </layout>
          </item>
+         <item row="2" column="1" rowspan="2" colspan="2">
+          <layout class="QVBoxLayout" name="verticalLayout_7">
+           <property name="sizeConstraint">
+            <enum>QLayout::SetDefaultConstraint</enum>
+           </property>
+           <property name="bottomMargin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QGroupBox" name="virt_groupbox">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="title">
+              <string>Virtualization</string>
+             </property>
+             <layout class="QFormLayout" name="formLayout_10">
+              <property name="fieldGrowthPolicy">
+               <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+              </property>
+              <item row="0" column="0" rowspan="3">
+               <widget class="QLabel" name="label_27">
+                <property name="text">
+                 <string>Mode:</string>
+                </property>
+                <property name="buddy">
+                 <cstring>virt_mode</cstring>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="QComboBox" name="virt_mode"/>
+              </item>
+              <item row="1" column="1">
+               <widget class="QLabel" name="pv_warning">
+                <property name="font">
+                 <font>
+                  <weight>75</weight>
+                  <italic>true</italic>
+                  <bold>true</bold>
+                 </font>
+                </property>
+                <property name="styleSheet">
+                 <string notr="true">color:rgb(255, 0, 0)</string>
+                </property>
+                <property name="text">
+                 <string>Using PV mode exposes more hypervisor attack surface!</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="1">
+               <widget class="QLabel" name="pvh_mode_hidden">
+                <property name="font">
+                 <font>
+                  <weight>75</weight>
+                  <italic>true</italic>
+                  <bold>true</bold>
+                 </font>
+                </property>
+                <property name="text">
+                 <string>PVH mode is hidden since it doesn't support PCI passthrough.</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </item>
+          </layout>
+         </item>
          <item row="2" column="0">
           <widget class="QGroupBox" name="other_groupbox">
            <property name="title">
@@ -894,6 +992,20 @@
              </property>
             </widget>
            </item>
+           <item>
+            <widget class="QLabel" name="pvh_dont_support_devs">
+             <property name="font">
+              <font>
+               <weight>75</weight>
+               <italic>true</italic>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="text">
+              <string>Currently PVH VMs don't support PCI passthrough. Select another virtualization mode if you want to add PCI devices</string>
+             </property>
+            </widget>
+           </item>
           </layout>
          </item>
         </layout>