Преглед на файлове

Added 'configure no strict reset for PCI devices' button

The button is in 'devices' tab of VM settings; it allows the user to
select which devices should have 'no-strict-reset' enabled and tells
the user not to change this setting if there are no errors.

fixes QubesOS/qubes-issues#3205
Marta Marczykowska-Górecka преди 6 години
родител
ревизия
801014f2e5
променени са 3 файла, в които са добавени 163 реда и са изтрити 17 реда
  1. 11 10
      qubesmanager/device_list.py
  2. 37 7
      qubesmanager/settings.py
  3. 115 0
      ui/devicelist.ui

+ 11 - 10
qubesmanager/device_list.py

@@ -22,12 +22,13 @@ from PyQt4 import QtGui, QtCore  # pylint: disable=import-error
 
 
 class PCIDeviceListWindow(ui_devicelist.Ui_Dialog, QtGui.QDialog):
-    def __init__(self, vm, qapp, dev_list, parent=None):
+    def __init__(self, vm, qapp, dev_list, no_strict_reset_list, parent=None):
         super(PCIDeviceListWindow, self).__init__(parent)
 
         self.vm = vm
         self.qapp = qapp
         self.dev_list = dev_list
+        self.no_strict_reset_list = no_strict_reset_list
 
         self.setupUi(self)
 
@@ -36,26 +37,26 @@ class PCIDeviceListWindow(ui_devicelist.Ui_Dialog, QtGui.QDialog):
         self.connect(
             self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
 
+        self.ident_list = {}
         self.fill_device_list()
 
     def fill_device_list(self):
         self.device_list.clear()
 
-        pci_devices = [ass.ident.replace('_', ':')
-                       for ass in self.vm.devices['pci'].assignments()]
-
         for i in range(self.dev_list.selected_list.count()):
             text = self.dev_list.selected_list.item(i).text()
             ident = self.dev_list.selected_list.item(i).ident
-            if ident in pci_devices:
-                self.device_list.addItem(text)
+            self.device_list.addItem(text)
+            self.ident_list[text] = ident
+            if ident in self.no_strict_reset_list:
+                self.device_list.setItemSelected(
+                    self.device_list.item(i), True)
 
     def reject(self):
         self.done(0)
 
     def save_and_apply(self):
+        self.no_strict_reset_list.clear()
+        self.no_strict_reset_list.extend([self.ident_list[item.text()] for item
+                                          in self.device_list.selectedItems()])
         self.done(0)
-
-    def show(self):
-        super(PCIDeviceListWindow, self).show()
-        self.fill_device_list()

+ 37 - 7
qubesmanager/settings.py

@@ -126,6 +126,9 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
                      self.devices_selection_changed)
         self.no_strict_reset_button.clicked.connect(
             self.strict_reset_button_pressed)
+        self.current_strict_reset_list = []
+        self.new_strict_reset_list = []
+        self.define_strict_reset_devices()
 
         ####### services tab
         self.__init_services_tab__()
@@ -664,6 +667,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
         if self.vm.is_running():
             self.dev_list.setEnabled(False)
             self.turn_off_vm_to_modify_devs.setVisible(True)
+            self.no_strict_reset_button.setEnabled(False)
         else:
             self.dev_list.setEnabled(True)
             self.turn_off_vm_to_modify_devs.setVisible(False)
@@ -671,8 +675,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
     def __apply_devices_tab__(self):
         msg = []
 
-        no_strict_reset = self.no_pci_strict_reset.isChecked()
-
         try:
             old = [ass.ident.replace('_', ':')
                    for ass in self.vm.devices['pci'].persistent()]
@@ -682,13 +684,35 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
             for ident in new:
                 if ident not in old:
                     options = {}
-                    if no_strict_reset:
+                    if ident in self.new_strict_reset_list:
                         options['no-strict-reset'] = True
                     ass = devices.DeviceAssignment(
                         self.vm.app.domains['dom0'],
                         ident.replace(':', '_'),
                         persistent=True, options=options)
                     self.vm.devices['pci'].attach(ass)
+                elif (ident in self.current_strict_reset_list) != \
+                        (ident in self.new_strict_reset_list):
+                    current_assignment = None
+                    for assignment in self.vm.devices['pci'].assignments(
+                            persistent=True):
+                        if assignment.ident.replace("_", ":") == ident:
+                            current_assignment = assignment
+                            break
+                    if current_assignment is None:
+                        # it would be very weird if this happened
+                        break
+                    self.vm.devices['pci'].detach(current_assignment)
+
+                    options = {}
+                    if ident in self.new_strict_reset_list:
+                        options['no-strict-reset'] = True
+                    new_assignment = devices.DeviceAssignment(
+                        self.vm.app.domains['dom0'],
+                        ident.replace(':', '_'),
+                        persistent=True, options=options)
+                    self.vm.devices['pci'].attach(new_assignment)
+
             for ass in self.vm.devices['pci'].assignments(persistent=True):
                 if ass.ident.replace('_', ':') not in new:
                     self.vm.devices['pci'].detach(ass)
@@ -725,12 +749,18 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
                 self.dmm_warning_adv.hide()
                 self.dmm_warning_dev.hide()
 
+    def define_strict_reset_devices(self):
+        for assignment in self.vm.devices['pci'].assignments():
+            if 'no-strict-reset' in assignment.options and \
+                    assignment.options['no-strict-reset']:
+                self.current_strict_reset_list.append(
+                    assignment.ident.replace('_', ':'))
+        self.new_strict_reset_list = self.current_strict_reset_list.copy()
+
     def strict_reset_button_pressed(self):
         device_list_window = device_list.PCIDeviceListWindow(
-            self.vm, self.qapp, self.dev_list, self)
-        device_list_window.show()
-        pass
-
+            self.vm, self.qapp, self.dev_list, self.new_strict_reset_list, self)
+        device_list_window.exec()
 
     ######## applications tab
 

+ 115 - 0
ui/devicelist.ui

@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Select devices</string>
+  </property>
+  <widget class="QDialogButtonBox" name="buttonBox">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>260</y>
+     <width>391</width>
+     <height>32</height>
+    </rect>
+   </property>
+   <property name="orientation">
+    <enum>Qt::Horizontal</enum>
+   </property>
+   <property name="standardButtons">
+    <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+   </property>
+  </widget>
+  <widget class="QListWidget" name="device_list">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>40</y>
+     <width>391</width>
+     <height>171</height>
+    </rect>
+   </property>
+   <property name="selectionMode">
+    <enum>QAbstractItemView::MultiSelection</enum>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>391</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Which PCI devices should use the no strict reset option?</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>220</y>
+     <width>391</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="font">
+    <font>
+     <italic>true</italic>
+    </font>
+   </property>
+   <property name="text">
+    <string>Note: use this option only if &quot;unable to reset PCI device&quot; error occurs. </string>
+   </property>
+   <property name="wordWrap">
+    <bool>true</bool>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>Dialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>Dialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>