Merge remote-tracking branch 'qubesos/pr/55'

* qubesos/pr/55:
  Fixed according to @marmarek request
  Fixed according to @marmarek request
  Added 'configure no strict reset for PCI devices' button
  Adding a button to list PCI devices and enable no-strict-reset
  Fixed some indents and whitespaces
  Fixed python2 in settings.py
This commit is contained in:
Marek Marczykowski-Górecki 2018-01-19 03:01:57 +01:00
commit 81413907bf
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
5 changed files with 272 additions and 50 deletions

View File

@ -0,0 +1,62 @@
#!/usr/bin/python3
#
# The Qubes OS Project, http://www.qubes-os.org
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.
#
#
from . import ui_devicelist # pylint: disable=no-name-in-module
from PyQt4 import QtGui, QtCore # pylint: disable=import-error
class PCIDeviceListWindow(ui_devicelist.Ui_Dialog, QtGui.QDialog):
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)
self.connect(
self.buttonBox, QtCore.SIGNAL("accepted()"), self.save_and_apply)
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()
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
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)

View File

@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
#
# The Qubes OS Project, http://www.qubes-os.org
#
@ -39,12 +39,14 @@ import qubesadmin.exc
from . import utils
from . import multiselectwidget
from . import thread_monitor
from . import device_list
from .appmenu_select import AppmenuSelectManager
from . import firewall
from PyQt4 import QtCore, QtGui # pylint: disable=import-error
from . import ui_settingsdlg #pylint: disable=no-name-in-module
from . import ui_settingsdlg # pylint: disable=no-name-in-module
# pylint: disable=too-many-instance-attributes
class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
@ -124,6 +126,11 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
self.connect(self.dev_list,
QtCore.SIGNAL("selected_changed()"),
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__()
@ -141,7 +148,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
def reject(self):
self.done(0)
#needed not to close the dialog before applying changes
# needed not to close the dialog before applying changes
def accept(self):
pass
@ -279,8 +286,8 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
self.delete_vm_button.setEnabled(not self.vm.is_running())
if self.vm.is_running():
self.delete_vm_button.setText(self.tr('Delete VM '
'(cannot delete a running VM)'))
self.delete_vm_button.setText(
self.tr('Delete VM (cannot delete a running VM)'))
if self.vm.qid == 0:
self.vmlabel.setVisible(False)
@ -328,13 +335,13 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except AttributeError:
self.autostart_vm.setVisible(False)
#type
# type
self.type_label.setText(self.vm.klass)
#installed by rpm
# installed by rpm
self.rpm_label.setText('Yes' if self.vm.installed_by_rpm else 'No')
#networking info
# networking info
if self.vm.netvm:
self.networking_groupbox.setEnabled(True)
self.ip_label.setText(self.vm.ip or "none")
@ -343,7 +350,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
else:
self.networking_groupbox.setEnabled(False)
#max priv storage
# max priv storage
self.priv_img_size = self.vm.volumes['private'].size // 1024**2
self.max_priv_storage.setMinimum(self.priv_img_size)
self.max_priv_storage.setValue(self.priv_img_size)
@ -357,7 +364,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
def __apply_basic_tab__(self):
msg = []
#vm label changed
# vm label changed
try:
if self.vmlabel.isVisible():
if self.vmlabel.currentIndex() != self.label_idx:
@ -366,7 +373,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#vm template changed
# vm template changed
try:
if self.template_name.currentIndex() != self.template_idx:
self.vm.template = \
@ -374,14 +381,14 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#vm netvm changed
# vm netvm changed
try:
if self.netVM.currentIndex() != self.netvm_idx:
self.vm.netvm = self.netvm_list[self.netVM.currentIndex()]
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#include in backups
# include in backups
try:
if self.vm.include_in_backups != \
self.include_in_backups.isChecked():
@ -389,7 +396,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#run_in_debug_mode
# run_in_debug_mode
try:
if self.run_in_debug_mode.isVisible():
if self.vm.debug != self.run_in_debug_mode.isChecked():
@ -397,7 +404,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#autostart_vm
# autostart_vm
try:
if self.autostart_vm.isVisible():
if self.vm.autostart != self.autostart_vm.isChecked():
@ -405,7 +412,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#max priv storage
# max priv storage
priv_size = self.max_priv_storage.value()
if self.priv_img_size != priv_size:
try:
@ -413,7 +420,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#max sys storage
# max sys storage
sys_size = self.root_resize.value()
if self.root_img_size != sys_size:
try:
@ -423,7 +430,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
return msg
def check_mem_changes(self):
if self.max_mem_size.value() < self.init_mem.value():
QtGui.QMessageBox.warning(
@ -456,10 +462,9 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
if not t_monitor.success:
QtGui.QMessageBox.warning(None,
self.tr("Error!"),
self.tr("ERROR: {}").format(
t_monitor.error_msg))
self.tr("Error!"),
self.tr("ERROR: {}").format(
t_monitor.error_msg))
def _rename_vm(self, t_monitor, name):
try:
@ -473,7 +478,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
t_monitor.set_finished()
def rename_vm(self):
new_vm_name, ok = QtGui.QInputDialog.getText(
@ -502,10 +506,9 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
self,
self.tr('Delete VM'),
self.tr('Are you absolutely sure you want to delete this VM? '
'<br/> All VM settings and data will be irrevocably'
' deleted. <br/> If you are sure, please enter this '
'VM\'s name below.'))
'<br/> All VM settings and data will be irrevocably'
' deleted. <br/> If you are sure, please enter this '
'VM\'s name below.'))
if ok and answer == self.vm.name:
self._run_in_thread(self._remove_vm)
@ -546,7 +549,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
def __init_advanced_tab__(self):
#mem/cpu
# mem/cpu
# qubes_memory = QubesHost().memory_total/1024
self.init_mem.setValue(int(self.vm.memory))
@ -564,7 +567,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
bool(self.vm.features.get('service.meminfo-writer', True)))
self.max_mem_size.setEnabled(self.include_in_balancing.isChecked())
#in case VM is HVM
# in case VM is HVM
if hasattr(self.vm, "kernel"):
self.kernel_groupbox.setVisible(True)
self.kernel_list, self.kernel_idx = utils.prepare_kernel_choice(
@ -594,7 +597,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
def __apply_advanced_tab__(self):
msg = []
#mem/cpu
# mem/cpu
try:
if self.init_mem.value() != int(self.vm.memory):
self.vm.memory = self.init_mem.value()
@ -607,9 +610,9 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#include_in_memory_balancing applied in services tab
# include_in_memory_balancing applied in services tab
#in case VM is not Linux
# in case VM is not Linux
if hasattr(self.vm, "kernel") and self.kernel_groupbox.isVisible():
try:
if self.kernel.currentIndex() != self.kernel_idx:
@ -618,7 +621,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
except qubesadmin.exc.QubesException as ex:
msg.append(str(ex))
#vm default_dispvm changed
# vm default_dispvm changed
try:
if self.default_dispvm.currentIndex() != self.default_dispvm_idx:
self.vm.default_dispvm = \
@ -739,7 +742,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
self.ident = ident
persistent = [ass.ident.replace('_', ':')
for ass in self.vm.devices['pci'].persistent()]
for ass in self.vm.devices['pci'].persistent()]
for name, ident in devs:
if ident in persistent:
@ -760,29 +763,53 @@ 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)
self.update_pvh_dont_support_devs()
def __apply_devices_tab__(self):
msg = []
try:
old = [ass.ident.replace('_', ':')
for ass in self.vm.devices['pci'].persistent()]
for ass in self.vm.devices['pci'].persistent()]
new = [self.dev_list.selected_list.item(i).ident
for i in range(self.dev_list.selected_list.count())]
for i in range(self.dev_list.selected_list.count())]
for ident in new:
if ident not in old:
options = {}
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)
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
msg.append(self.tr("Error re-assigning device ") +
ident)
continue
self.vm.devices['pci'].detach(current_assignment)
current_assignment.options['no-strict-reset'] = \
(ident in self.new_strict_reset_list)
self.vm.devices['pci'].attach(current_assignment)
for ass in self.vm.devices['pci'].assignments(persistent=True):
if ass.ident.replace('_', ':') not in new:
self.vm.devices['pci'].detach(ass)
@ -829,6 +856,18 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
self.dev_list.setEnabled(True)
self.pvh_dont_support_devs.setVisible(False)
def define_strict_reset_devices(self):
for assignment in self.vm.devices['pci'].assignments():
if assignment.options.get('no-strict-reset', False):
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.new_strict_reset_list, self)
device_list_window.exec()
######## applications tab
def refresh_apps_in_vm(self, t_monitor):
@ -881,7 +920,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
service = feature[len('service.'):]
item = QtGui.QListWidgetItem(service)
item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked
if self.vm.features[feature]
if self.vm.features[feature]
else ui_settingsdlg.QtCore.Qt.Unchecked)
self.services_list.addItem(item)
self.new_srv_dict[service] = self.vm.features[feature]
@ -922,7 +961,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
item = self.services_list.takeItem(row)
del self.new_srv_dict[str(item.text())]
def services_item_clicked(self, item):
if str(item.text()) == 'meminfo-writer':
if item.checkState() == ui_settingsdlg.QtCore.Qt.Checked:
@ -932,7 +970,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
if self.include_in_balancing.isChecked():
self.include_in_balancing.setChecked(False)
def __apply_services_tab__(self):
msg = []
@ -968,9 +1005,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
return msg
######### firewall tab related
def set_fw_model(self, model):
self.fw_model = model
self.rulesTreeView.setModel(model)
@ -1049,10 +1084,10 @@ def handle_exception(exc_type, exc_value, exc_traceback):
while stacktrace:
(filename, line, func, txt) = stacktrace.pop()
strace += "----\n"
strace += "line: %s\n" %txt
strace += "func: %s\n" %func
strace += "line no.: %d\n" %line
strace += "file: %s\n" %filename
strace += "line: %s\n" % txt
strace += "func: %s\n" % func
strace += "line no.: %d\n" % line
strace += "file: %s\n" % filename
msg_box = QtGui.QMessageBox()
msg_box.setDetailedText(strace)
@ -1070,13 +1105,14 @@ def handle_exception(exc_type, exc_value, exc_traceback):
parser = QubesArgumentParser(vmname_nargs=1)
parser.add_argument('--tab', metavar='TAB',
action='store',
choices=VMSettingsWindow.tabs_indices.keys())
action='store',
choices=VMSettingsWindow.tabs_indices.keys())
parser.set_defaults(
tab='basic',
)
def main(args=None):
args = parser.parse_args(args)
vm = args.domains.pop()

View File

@ -91,6 +91,7 @@ rm -rf $RPM_BUILD_ROOT
%{python3_sitelib}/qubesmanager/qube_manager.py
%{python3_sitelib}/qubesmanager/utils.py
%{python3_sitelib}/qubesmanager/bootfromdevice.py
%{python3_sitelib}/qubesmanager/device_list.py
%{python3_sitelib}/qubesmanager/resources_rc.py
@ -107,6 +108,7 @@ rm -rf $RPM_BUILD_ROOT
%{python3_sitelib}/qubesmanager/ui_releasenotes.py
%{python3_sitelib}/qubesmanager/ui_informationnotes.py
%{python3_sitelib}/qubesmanager/ui_qubemanager.py
%{python3_sitelib}/qubesmanager/ui_devicelist.py
%{python3_sitelib}/qubesmanager/i18n/qubesmanager_*.qm
%{python3_sitelib}/qubesmanager/i18n/qubesmanager_*.ts

115
ui/devicelist.ui Normal file
View File

@ -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>

View File

@ -29,7 +29,7 @@
<locale language="English" country="UnitedStates"/>
</property>
<property name="currentIndex">
<number>2</number>
<number>3</number>
</property>
<widget class="QWidget" name="basic_tab">
<property name="locale">
@ -1216,6 +1216,13 @@ border-width: 1px;</string>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="no_strict_reset_button">
<property name="text">
<string>Configure strict reset for PCI devices</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="apps_tab">