Fixed VM settings to be more tolerant of missing permissions
Settings unavailable due to permissions will be unavailable in the tool, but the tool will start and attempt to show as much as possible.
This commit is contained in:
parent
39129bd804
commit
8eb61b11ae
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from PyQt5 import QtWidgets, QtCore # pylint: disable=import-error
|
from PyQt5 import QtWidgets, QtCore # pylint: disable=import-error
|
||||||
|
from qubesadmin import exc
|
||||||
|
|
||||||
# TODO description in tooltip
|
# TODO description in tooltip
|
||||||
# TODO icon
|
# TODO icon
|
||||||
@ -60,9 +61,12 @@ class AppmenuSelectManager:
|
|||||||
self.fill_apps_list(template=None)
|
self.fill_apps_list(template=None)
|
||||||
|
|
||||||
def fill_apps_list(self, template=None):
|
def fill_apps_list(self, template=None):
|
||||||
self.whitelisted = [line for line in subprocess.check_output(
|
try:
|
||||||
['qvm-appmenus', '--get-whitelist', self.vm.name]
|
self.whitelisted = [line for line in subprocess.check_output(
|
||||||
).decode().strip().split('\n') if line]
|
['qvm-appmenus', '--get-whitelist', self.vm.name]
|
||||||
|
).decode().strip().split('\n') if line]
|
||||||
|
except exc.QubesException:
|
||||||
|
self.whitelisted = []
|
||||||
|
|
||||||
currently_selected = [
|
currently_selected = [
|
||||||
self.app_list.selected_list.item(i).ident
|
self.app_list.selected_list.item(i).ident
|
||||||
@ -84,9 +88,13 @@ class AppmenuSelectManager:
|
|||||||
command.extend(['--template', template.name])
|
command.extend(['--template', template.name])
|
||||||
command.append(self.vm.name)
|
command.append(self.vm.name)
|
||||||
|
|
||||||
available_appmenus = [
|
try:
|
||||||
AppListWidgetItem.from_line(line)
|
available_appmenus = [
|
||||||
for line in subprocess.check_output(command).decode().splitlines()]
|
AppListWidgetItem.from_line(line)
|
||||||
|
for line in subprocess.check_output(
|
||||||
|
command).decode().splitlines()]
|
||||||
|
except exc.QubesException:
|
||||||
|
available_appmenus = []
|
||||||
|
|
||||||
for app in available_appmenus:
|
for app in available_appmenus:
|
||||||
if app.ident in whitelist:
|
if app.ident in whitelist:
|
||||||
|
@ -453,7 +453,7 @@ class QubesTableModel(QAbstractTableModel):
|
|||||||
|
|
||||||
# Used for sorting
|
# Used for sorting
|
||||||
if role == Qt.UserRole + 1:
|
if role == Qt.UserRole + 1:
|
||||||
if vm.klass != 'AdminVM':
|
if vm.klass == 'AdminVM':
|
||||||
return ""
|
return ""
|
||||||
if col_name == "Type":
|
if col_name == "Type":
|
||||||
return vm.klass
|
return vm.klass
|
||||||
@ -572,7 +572,7 @@ class StartVMThread(common_threads.QubesThread):
|
|||||||
class UpdateVMThread(common_threads.QubesThread):
|
class UpdateVMThread(common_threads.QubesThread):
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
if self.vm.klass != 'AdminVM':
|
if self.vm.klass == 'AdminVM':
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
["/usr/bin/qubes-dom0-update", "--clean", "--gui"])
|
["/usr/bin/qubes-dom0-update", "--clean", "--gui"])
|
||||||
else:
|
else:
|
||||||
|
@ -102,7 +102,7 @@ class RefreshAppsVMThread(common_threads.QubesThread):
|
|||||||
self.tr('Refresh in progress (refreshing applications '
|
self.tr('Refresh in progress (refreshing applications '
|
||||||
'from {})').format(vm.name))
|
'from {})').format(vm.name))
|
||||||
try:
|
try:
|
||||||
if not vm.is_running():
|
if not utils.is_running(vm, True):
|
||||||
not_running = True
|
not_running = True
|
||||||
vm.start()
|
vm.start()
|
||||||
else:
|
else:
|
||||||
@ -137,10 +137,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.threads_list = []
|
self.threads_list = []
|
||||||
self.progress = None
|
self.progress = None
|
||||||
self.thread_closes = False
|
self.thread_closes = False
|
||||||
try:
|
|
||||||
self.source_vm = self.vm.template
|
|
||||||
except AttributeError:
|
|
||||||
self.source_vm = self.vm
|
|
||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.setWindowTitle(self.tr("Settings: {vm}").format(vm=self.vm.name))
|
self.setWindowTitle(self.tr("Settings: {vm}").format(vm=self.vm.name))
|
||||||
@ -182,6 +178,9 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.firewall_modified_outside_label.setVisible(False)
|
self.firewall_modified_outside_label.setVisible(False)
|
||||||
except firewall.FirewallModifiedOutsideError:
|
except firewall.FirewallModifiedOutsideError:
|
||||||
self.disable_all_fw_conf()
|
self.disable_all_fw_conf()
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
self.tabWidget.setTabEnabled(
|
||||||
|
self.tabs_indices['firewall'], False)
|
||||||
|
|
||||||
self.new_rule_button.clicked.connect(self.new_rule_button_pressed)
|
self.new_rule_button.clicked.connect(self.new_rule_button_pressed)
|
||||||
self.edit_rule_button.clicked.connect(self.edit_rule_button_pressed)
|
self.edit_rule_button.clicked.connect(self.edit_rule_button_pressed)
|
||||||
@ -306,7 +305,8 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
ret.append(repr(ex))
|
ret.append(repr(ex))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.policy_allow_radio_button.isEnabled():
|
if self.tabWidget.isTabEnabled(self.tabs_indices['firewall']) and \
|
||||||
|
self.policy_allow_radio_button.isEnabled():
|
||||||
self.fw_model.apply_rules(
|
self.fw_model.apply_rules(
|
||||||
self.policy_allow_radio_button.isChecked(),
|
self.policy_allow_radio_button.isChecked(),
|
||||||
self.temp_full_access.isChecked(),
|
self.temp_full_access.isChecked(),
|
||||||
@ -328,15 +328,19 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def check_network_availability(self):
|
def check_network_availability(self):
|
||||||
netvm = self.vm.netvm
|
netvm = getattr(self.vm, 'netvm', None)
|
||||||
try:
|
provides_network = getattr(self.vm, 'provides_network', False)
|
||||||
provides_network = self.vm.provides_network
|
|
||||||
except AttributeError:
|
|
||||||
provides_network = False
|
|
||||||
self.no_netvm_label.setVisible(netvm is None and not provides_network)
|
self.no_netvm_label.setVisible(netvm is None and not provides_network)
|
||||||
self.netvm_no_firewall_label.setVisible(
|
|
||||||
netvm is not None and
|
try:
|
||||||
not netvm.features.check_with_template('qubes-firewall', False))
|
no_firewall_state = \
|
||||||
|
netvm is not None and \
|
||||||
|
not netvm.features.check_with_template('qubes-firewall', False)
|
||||||
|
except qubesadmin.exc.QubesDaemonCommunicationError:
|
||||||
|
no_firewall_state = False
|
||||||
|
|
||||||
|
self.netvm_no_firewall_label.setVisible(no_firewall_state)
|
||||||
self.sysnet_warning_label.setVisible(netvm is None and provides_network)
|
self.sysnet_warning_label.setVisible(netvm is None and provides_network)
|
||||||
|
|
||||||
def current_tab_changed(self, idx):
|
def current_tab_changed(self, idx):
|
||||||
@ -364,57 +368,80 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.rename_vm_button.setEnabled(not self.vm.is_running())
|
self.rename_vm_button.setEnabled(not self.vm.is_running())
|
||||||
self.delete_vm_button.setEnabled(not self.vm.is_running())
|
self.delete_vm_button.setEnabled(not self.vm.is_running())
|
||||||
|
|
||||||
if self.vm.is_running():
|
if utils.is_running(self.vm, False):
|
||||||
self.delete_vm_button.setText(
|
self.delete_vm_button.setText(
|
||||||
self.tr('Delete qube (cannot delete a running qube)'))
|
self.tr('Delete qube (cannot delete a running qube)'))
|
||||||
|
|
||||||
if self.vm.qid == 0:
|
if self.vm.qid == 0:
|
||||||
self.vmlabel.setVisible(False)
|
self.vmlabel.setVisible(False)
|
||||||
else:
|
else:
|
||||||
utils.initialize_widget_with_labels(
|
try:
|
||||||
widget=self.vmlabel,
|
utils.initialize_widget_with_labels(
|
||||||
qubes_app=self.qubesapp,
|
widget=self.vmlabel,
|
||||||
holder=self.vm)
|
qubes_app=self.qubesapp,
|
||||||
self.vmlabel.setVisible(True)
|
holder=self.vm)
|
||||||
self.vmlabel.setEnabled(not self.vm.is_running())
|
self.vmlabel.setVisible(True)
|
||||||
|
self.vmlabel.setEnabled(not utils.is_running(self.vm, False))
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.vmlabel.setEnabled(False)
|
||||||
|
|
||||||
if self.vm.klass == 'AppVM':
|
if self.vm.klass == 'AppVM':
|
||||||
utils.initialize_widget_with_vms(
|
try:
|
||||||
widget=self.template_name,
|
utils.initialize_widget_with_vms(
|
||||||
qubes_app=self.qubesapp,
|
widget=self.template_name,
|
||||||
filter_function=(lambda vm: vm.klass == 'TemplateVM'),
|
qubes_app=self.qubesapp,
|
||||||
holder=self.vm,
|
filter_function=(lambda vm: vm.klass == 'TemplateVM'),
|
||||||
property_name='template')
|
holder=self.vm,
|
||||||
|
property_name='template')
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.template_name.setCurrentIndex(-1)
|
||||||
|
self.template_name.setEnabled(False)
|
||||||
|
|
||||||
elif self.vm.klass == 'DispVM':
|
elif self.vm.klass == 'DispVM':
|
||||||
utils.initialize_widget_with_vms(
|
try:
|
||||||
widget=self.template_name,
|
utils.initialize_widget_with_vms(
|
||||||
qubes_app=self.qubesapp,
|
widget=self.template_name,
|
||||||
filter_function=(lambda vm:
|
qubes_app=self.qubesapp,
|
||||||
getattr(vm, 'template_for_dispvms', False)),
|
filter_function=(lambda vm:
|
||||||
holder=self.vm,
|
getattr(vm, 'template_for_dispvms', False)),
|
||||||
property_name='template')
|
holder=self.vm,
|
||||||
|
property_name='template')
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.template_name.setCurrentIndex(-1)
|
||||||
|
self.template_name.setEnabled(False)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.template_name.setEnabled(False)
|
self.template_name.setEnabled(False)
|
||||||
|
|
||||||
if self.vm.is_running():
|
if utils.is_running(self.vm, False):
|
||||||
self.template_name.setEnabled(False)
|
self.template_name.setEnabled(False)
|
||||||
|
|
||||||
utils.initialize_widget_with_vms(
|
try:
|
||||||
widget=self.netVM,
|
utils.initialize_widget_with_vms(
|
||||||
qubes_app=self.qubesapp,
|
widget=self.netVM,
|
||||||
filter_function=(lambda vm: vm.provides_network),
|
qubes_app=self.qubesapp,
|
||||||
holder=self.vm,
|
filter_function=(lambda vm:
|
||||||
property_name='netvm',
|
getattr(vm, 'provides_network', False)),
|
||||||
allow_default=True,
|
holder=self.vm,
|
||||||
allow_none=True)
|
property_name='netvm',
|
||||||
|
allow_default=True,
|
||||||
|
allow_none=True)
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.netVM.setEnabled(False)
|
||||||
|
self.netVM.setCurrentIndex(-1)
|
||||||
|
|
||||||
self.netVM.currentIndexChanged.connect(self.check_warn_dispvmnetvm)
|
self.netVM.currentIndexChanged.connect(self.check_warn_dispvmnetvm)
|
||||||
|
|
||||||
self.include_in_backups.setChecked(self.vm.include_in_backups)
|
try:
|
||||||
|
self.include_in_backups.setChecked(self.vm.include_in_backups)
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.include_in_backups.setEnabled(False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.autostart_vm.setChecked(self.vm.autostart)
|
self.autostart_vm.setChecked(self.vm.autostart)
|
||||||
self.autostart_vm.setVisible(True)
|
self.autostart_vm.setVisible(True)
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.autostart_vm.setEnabled(False)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.autostart_vm.setVisible(False)
|
self.autostart_vm.setVisible(False)
|
||||||
|
|
||||||
@ -422,41 +449,50 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.type_label.setText(self.vm.klass)
|
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')
|
self.rpm_label.setText(
|
||||||
|
'Yes' if getattr(self.vm, 'installed_by_rpm', False) else 'No')
|
||||||
|
|
||||||
# networking info
|
# networking info
|
||||||
if self.vm.netvm:
|
if getattr(self.vm, 'netvm', None):
|
||||||
self.networking_groupbox.setEnabled(True)
|
self.networking_groupbox.setEnabled(True)
|
||||||
self.ip_label.setText(self.vm.ip or "none")
|
self.ip_label.setText(getattr(self.vm, 'ip', None) or "none")
|
||||||
self.netmask_label.setText(self.vm.visible_netmask or "none")
|
self.netmask_label.setText(
|
||||||
self.gateway_label.setText(self.vm.visible_gateway or "none")
|
getattr(self.vm, 'visible_netmask', None) or "none")
|
||||||
|
self.gateway_label.setText(
|
||||||
|
getattr(self.vm, 'visible_gateway', None) or "none")
|
||||||
dns_list = getattr(self.vm, 'dns', ['10.139.1.1', '10.139.1.2'])
|
dns_list = getattr(self.vm, 'dns', ['10.139.1.1', '10.139.1.2'])
|
||||||
self.dns_label.setText(", ".join(dns_list))
|
self.dns_label.setText(", ".join(dns_list))
|
||||||
else:
|
else:
|
||||||
self.networking_groupbox.setEnabled(False)
|
self.networking_groupbox.setEnabled(False)
|
||||||
|
|
||||||
# max priv storage
|
# max priv storage
|
||||||
self.priv_img_size = self.vm.volumes['private'].size // 1024**2
|
try:
|
||||||
self.max_priv_storage.setMinimum(self.priv_img_size)
|
self.priv_img_size = self.vm.volumes['private'].size // 1024**2
|
||||||
self.max_priv_storage.setValue(self.priv_img_size)
|
self.max_priv_storage.setMinimum(self.priv_img_size)
|
||||||
self.max_priv_storage.setMaximum(
|
self.max_priv_storage.setValue(self.priv_img_size)
|
||||||
max(self.priv_img_size,
|
self.max_priv_storage.setMaximum(
|
||||||
self.qubesapp.pools[self.vm.volumes['private'].pool].size
|
max(self.priv_img_size,
|
||||||
// 1024**2))
|
self.qubesapp.pools[self.vm.volumes['private'].pool].size
|
||||||
|
// 1024**2))
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
self.max_priv_storage.setEnabled(False)
|
||||||
|
|
||||||
self.root_img_size = self.vm.volumes['root'].size // 1024**2
|
try:
|
||||||
self.root_resize.setValue(self.root_img_size)
|
self.root_img_size = self.vm.volumes['root'].size // 1024**2
|
||||||
self.root_resize.setMinimum(self.root_img_size)
|
self.root_resize.setValue(self.root_img_size)
|
||||||
self.root_resize.setMaximum(
|
self.root_resize.setMinimum(self.root_img_size)
|
||||||
max(self.root_img_size,
|
self.root_resize.setMaximum(
|
||||||
self.qubesapp.pools[self.vm.volumes['root'].pool].size
|
max(self.root_img_size,
|
||||||
// 1024**2))
|
self.qubesapp.pools[self.vm.volumes['root'].pool].size
|
||||||
self.root_resize.setEnabled(self.vm.volumes['root'].save_on_stop)
|
// 1024**2))
|
||||||
if not self.root_resize.isEnabled():
|
self.root_resize.setEnabled(self.vm.volumes['root'].save_on_stop)
|
||||||
self.root_resize.setToolTip(
|
if not self.root_resize.isEnabled():
|
||||||
self.tr("To change system storage size, change properties "
|
self.root_resize.setToolTip(
|
||||||
"of the underlying template."))
|
self.tr("To change system storage size, change properties "
|
||||||
self.root_resize_label.setEnabled(self.root_resize.isEnabled())
|
"of the underlying template."))
|
||||||
|
self.root_resize_label.setEnabled(self.root_resize.isEnabled())
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
self.root_resize.setEnabled(False)
|
||||||
|
|
||||||
self.warn_template_missing_apps.setVisible(False)
|
self.warn_template_missing_apps.setVisible(False)
|
||||||
|
|
||||||
@ -487,7 +523,8 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
|
|
||||||
# include in backups
|
# include in backups
|
||||||
try:
|
try:
|
||||||
if self.vm.include_in_backups != \
|
if self.include_in_backups.isEnabled() and\
|
||||||
|
self.vm.include_in_backups != \
|
||||||
self.include_in_backups.isChecked():
|
self.include_in_backups.isChecked():
|
||||||
self.vm.include_in_backups = self.include_in_backups.isChecked()
|
self.vm.include_in_backups = self.include_in_backups.isChecked()
|
||||||
except qubesadmin.exc.QubesException as ex:
|
except qubesadmin.exc.QubesException as ex:
|
||||||
@ -502,22 +539,24 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
msg.append(str(ex))
|
msg.append(str(ex))
|
||||||
|
|
||||||
# max priv storage
|
# max priv storage
|
||||||
priv_size = self.max_priv_storage.value()
|
if self.max_priv_storage.isEnabled():
|
||||||
if self.priv_img_size != priv_size:
|
priv_size = self.max_priv_storage.value()
|
||||||
try:
|
if self.priv_img_size != priv_size:
|
||||||
self.vm.volumes['private'].resize(priv_size * 1024**2)
|
try:
|
||||||
self.priv_img_size = priv_size
|
self.vm.volumes['private'].resize(priv_size * 1024**2)
|
||||||
except qubesadmin.exc.QubesException as ex:
|
self.priv_img_size = priv_size
|
||||||
msg.append(str(ex))
|
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_resize.isEnabled():
|
||||||
if self.root_img_size != sys_size:
|
sys_size = self.root_resize.value()
|
||||||
try:
|
if self.root_img_size != sys_size:
|
||||||
self.vm.volumes['root'].resize(sys_size * 1024**2)
|
try:
|
||||||
self.root_img_size = sys_size
|
self.vm.volumes['root'].resize(sys_size * 1024**2)
|
||||||
except qubesadmin.exc.QubesException as ex:
|
self.root_img_size = sys_size
|
||||||
msg.append(str(ex))
|
except qubesadmin.exc.QubesException as ex:
|
||||||
|
msg.append(str(ex))
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@ -526,6 +565,9 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
# do not interfere with settings if the VM is not included in memory
|
# do not interfere with settings if the VM is not included in memory
|
||||||
# balancing
|
# balancing
|
||||||
return
|
return
|
||||||
|
if not self.max_mem_size.isEnabled() or not self.init_mem.isEnabled():
|
||||||
|
# do not interfere with settings if they are unavailable
|
||||||
|
return
|
||||||
if self.max_mem_size.value() < self.init_mem.value():
|
if self.max_mem_size.value() < self.init_mem.value():
|
||||||
QtWidgets.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
@ -536,7 +578,13 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
# Linux specific limit: init memory must not be below
|
# Linux specific limit: init memory must not be below
|
||||||
# max_mem_size/10.79 in order to allow scaling up to
|
# max_mem_size/10.79 in order to allow scaling up to
|
||||||
# max_mem_size (or else "add_memory() failed: -17" problem)
|
# max_mem_size (or else "add_memory() failed: -17" problem)
|
||||||
if self.vm.features.check_with_template('os', None) == 'Linux' and \
|
try:
|
||||||
|
is_linux = self.vm.features.check_with_template('os', None) == \
|
||||||
|
'Linux'
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
is_linux = False
|
||||||
|
|
||||||
|
if is_linux and \
|
||||||
self.init_mem.value() * 10 < self.max_mem_size.value():
|
self.init_mem.value() * 10 < self.max_mem_size.value():
|
||||||
self.init_mem.setValue((self.max_mem_size.value() + 9) // 10)
|
self.init_mem.setValue((self.max_mem_size.value() + 9) // 10)
|
||||||
QtWidgets.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
@ -563,7 +611,12 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
dispvm_netvm = getattr(dispvm, 'netvm', None)
|
dispvm_netvm = getattr(dispvm, 'netvm', None)
|
||||||
|
|
||||||
if own_netvm == qubesadmin.DEFAULT:
|
if own_netvm == qubesadmin.DEFAULT:
|
||||||
own_netvm = self.vm.property_get_default('netvm')
|
try:
|
||||||
|
own_netvm = self.vm.property_get_default('netvm')
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
# no point in warning if we don't know what we're warning about
|
||||||
|
self.warn_netvm_dispvm.setVisible(False)
|
||||||
|
return
|
||||||
|
|
||||||
if dispvm_netvm and dispvm_netvm != own_netvm:
|
if dispvm_netvm and dispvm_netvm != own_netvm:
|
||||||
self.warn_netvm_dispvm.setVisible(True)
|
self.warn_netvm_dispvm.setVisible(True)
|
||||||
@ -576,7 +629,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
|
|
||||||
running_dependencies = [vm.name for (vm, prop) in dependencies
|
running_dependencies = [vm.name for (vm, prop) in dependencies
|
||||||
if vm and prop == 'template'
|
if vm and prop == 'template'
|
||||||
and vm.is_running()]
|
and utils.is_running(vm, False)]
|
||||||
|
|
||||||
if running_dependencies:
|
if running_dependencies:
|
||||||
QtWidgets.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
@ -663,64 +716,85 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
|
|
||||||
def __init_advanced_tab__(self):
|
def __init_advanced_tab__(self):
|
||||||
|
|
||||||
self.init_mem.setValue(int(self.vm.memory))
|
vm_memory = getattr(self.vm, 'memory', None)
|
||||||
|
vm_maxmem = getattr(self.vm, 'maxmem', None)
|
||||||
|
|
||||||
if self.vm.maxmem > 0:
|
if vm_memory is None:
|
||||||
self.max_mem_size.setValue(int(self.vm.maxmem))
|
self.init_mem.setEnabled(False)
|
||||||
else:
|
else:
|
||||||
maxmem = self.vm.property_get_default('maxmem')
|
self.init_mem.setValue(int(vm_memory))
|
||||||
|
|
||||||
|
if vm_maxmem is None:
|
||||||
|
self.max_mem_size.setEnabled(False)
|
||||||
|
elif vm_maxmem > 0:
|
||||||
|
self.max_mem_size.setValue(int(vm_maxmem))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
maxmem = self.vm.property_get_default('maxmem')
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
maxmem = 0
|
||||||
if maxmem == 0:
|
if maxmem == 0:
|
||||||
maxmem = self.vm.memory
|
maxmem = vm_memory
|
||||||
self.max_mem_size.setValue(int(
|
self.max_mem_size.setValue(
|
||||||
self.vm.features.get('qubesmanager.maxmem_value', maxmem)))
|
int(utils.get_feature(
|
||||||
|
self.vm, 'qubesmanager.maxmem_value', maxmem)))
|
||||||
|
|
||||||
self.vcpus.setMinimum(1)
|
self.vcpus.setMinimum(1)
|
||||||
self.vcpus.setValue(int(self.vm.vcpus))
|
self.vcpus.setValue(int(getattr(self.vm, 'vcpus', 1)))
|
||||||
|
|
||||||
self.include_in_balancing.setEnabled(True)
|
self.include_in_balancing.setEnabled(True)
|
||||||
self.include_in_balancing.setChecked(int(self.vm.maxmem) > 0)
|
self.include_in_balancing.setChecked(
|
||||||
|
int(getattr(self.vm, 'maxmem', 0)) > 0)
|
||||||
self.max_mem_size.setEnabled(self.include_in_balancing.isChecked())
|
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"):
|
if hasattr(self.vm, "kernel"):
|
||||||
self.kernel_groupbox.setVisible(True)
|
self.kernel_groupbox.setVisible(True)
|
||||||
utils.initialize_widget_with_kernels(
|
try:
|
||||||
widget=self.kernel,
|
utils.initialize_widget_with_kernels(
|
||||||
qubes_app=self.qubesapp,
|
widget=self.kernel,
|
||||||
allow_none=True,
|
qubes_app=self.qubesapp,
|
||||||
allow_default=True,
|
allow_none=True,
|
||||||
holder=self.vm,
|
allow_default=True,
|
||||||
property_name='kernel')
|
holder=self.vm,
|
||||||
self.kernel.currentIndexChanged.connect(self.kernel_changed)
|
property_name='kernel')
|
||||||
self.kernel_opts.setText(getattr(self.vm, 'kernelopts', '-'))
|
self.kernel.currentIndexChanged.connect(self.kernel_changed)
|
||||||
|
self.kernel_opts.setText(getattr(self.vm, 'kernelopts', '-'))
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.kernel_groupbox.setVisible(False)
|
||||||
else:
|
else:
|
||||||
self.kernel_groupbox.setVisible(False)
|
self.kernel_groupbox.setVisible(False)
|
||||||
|
|
||||||
self.other_groupbox.setVisible(False)
|
|
||||||
|
|
||||||
if not hasattr(self.vm, 'default_dispvm'):
|
if not hasattr(self.vm, 'default_dispvm'):
|
||||||
self.other_groupbox.setVisible(False)
|
self.other_groupbox.setVisible(False)
|
||||||
else:
|
else:
|
||||||
self.other_groupbox.setVisible(True)
|
try:
|
||||||
utils.initialize_widget_with_vms(
|
self.other_groupbox.setVisible(True)
|
||||||
widget=self.default_dispvm,
|
utils.initialize_widget_with_vms(
|
||||||
qubes_app=self.qubesapp,
|
widget=self.default_dispvm,
|
||||||
filter_function=(lambda vm:
|
qubes_app=self.qubesapp,
|
||||||
getattr(vm, 'template_for_dispvms', False)),
|
filter_function=(lambda vm:
|
||||||
allow_none=True,
|
getattr(
|
||||||
allow_default=True,
|
vm, 'template_for_dispvms', False)),
|
||||||
holder=self.vm,
|
allow_none=True,
|
||||||
property_name='default_dispvm'
|
allow_default=True,
|
||||||
)
|
holder=self.vm,
|
||||||
self.default_dispvm.currentIndexChanged.connect(
|
property_name='default_dispvm'
|
||||||
self.check_warn_dispvmnetvm)
|
)
|
||||||
|
self.default_dispvm.currentIndexChanged.connect(
|
||||||
|
self.check_warn_dispvmnetvm)
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.other_groupbox.setVisible(False)
|
||||||
|
|
||||||
self.check_warn_dispvmnetvm()
|
self.check_warn_dispvmnetvm()
|
||||||
self.update_virt_mode_list()
|
self.update_virt_mode_list()
|
||||||
|
|
||||||
windows_running = \
|
try:
|
||||||
self.vm.features.check_with_template('os', None) == 'Windows' \
|
windows_running = \
|
||||||
and self.vm.is_running()
|
self.vm.features.check_with_template('os', None) == 'Windows' \
|
||||||
|
and self.vm.is_running()
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
windows_running = False
|
||||||
|
|
||||||
self.seamless_on_button.setEnabled(windows_running)
|
self.seamless_on_button.setEnabled(windows_running)
|
||||||
self.seamless_off_button.setEnabled(windows_running)
|
self.seamless_off_button.setEnabled(windows_running)
|
||||||
@ -728,15 +802,14 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.seamless_on_button.clicked.connect(self.enable_seamless)
|
self.seamless_on_button.clicked.connect(self.enable_seamless)
|
||||||
self.seamless_off_button.clicked.connect(self.disable_seamless)
|
self.seamless_off_button.clicked.connect(self.disable_seamless)
|
||||||
|
|
||||||
if hasattr(self.vm, "template_for_dispvms"):
|
self.dvm_template_checkbox.setChecked(
|
||||||
self.dvm_template_checkbox.setChecked(self.vm.template_for_dispvms)
|
getattr(self.vm, 'template_for_dispvms', False))
|
||||||
else:
|
|
||||||
self.dvm_template_checkbox.setVisible(False)
|
|
||||||
|
|
||||||
self.provides_network_checkbox.setChecked(
|
self.provides_network_checkbox.setChecked(
|
||||||
getattr(self.vm, 'provides_network', False))
|
getattr(self.vm, 'provides_network', False))
|
||||||
if self.provides_network_checkbox.isChecked():
|
if self.provides_network_checkbox.isChecked():
|
||||||
domains_using = [vm.name for vm in self.vm.connected_vms]
|
domains_using = [vm.name for vm
|
||||||
|
in getattr(self.vm, 'connected_vms', [])]
|
||||||
if domains_using:
|
if domains_using:
|
||||||
self.provides_network_checkbox.setEnabled(False)
|
self.provides_network_checkbox.setEnabled(False)
|
||||||
self.provides_network_checkbox.setToolTip(self.tr(
|
self.provides_network_checkbox.setToolTip(self.tr(
|
||||||
@ -772,20 +845,34 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.allow_utf8_initial = self.allow_utf8.currentIndex()
|
self.allow_utf8_initial = self.allow_utf8.currentIndex()
|
||||||
|
|
||||||
def enable_seamless(self):
|
def enable_seamless(self):
|
||||||
self.vm.run_service_for_stdio("qubes.SetGuiMode", input=b'SEAMLESS')
|
try:
|
||||||
|
self.vm.run_service_for_stdio("qubes.SetGuiMode", input=b'SEAMLESS')
|
||||||
|
except qubesadmin.exc.QubesException as ex:
|
||||||
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
self.tr("Failed to set seamless mode"),
|
||||||
|
self.tr("Error occured: {}".format(str(ex))))
|
||||||
|
|
||||||
def disable_seamless(self):
|
def disable_seamless(self):
|
||||||
self.vm.run_service_for_stdio("qubes.SetGuiMode", input=b'FULLSCREEN')
|
try:
|
||||||
|
self.vm.run_service_for_stdio("qubes.SetGuiMode",
|
||||||
|
input=b'FULLSCREEN')
|
||||||
|
except qubesadmin.exc.QubesException as ex:
|
||||||
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
self.tr("Failed to set fullscreen mode"),
|
||||||
|
self.tr("Error occured: {}".format(str(ex))))
|
||||||
|
|
||||||
def __apply_advanced_tab__(self):
|
def __apply_advanced_tab__(self):
|
||||||
msg = []
|
msg = []
|
||||||
|
|
||||||
# mem/cpu
|
# mem/cpu
|
||||||
try:
|
try:
|
||||||
if self.init_mem.value() != int(self.vm.memory):
|
if self.init_mem.isEnabled() and \
|
||||||
|
self.init_mem.value() != int(self.vm.memory):
|
||||||
self.vm.memory = self.init_mem.value()
|
self.vm.memory = self.init_mem.value()
|
||||||
|
|
||||||
curr_maxmem = int(self.vm.maxmem)
|
curr_maxmem = int(getattr(self.vm, 'maxmem', 0))
|
||||||
|
|
||||||
if not self.include_in_balancing.isChecked():
|
if not self.include_in_balancing.isChecked():
|
||||||
maxmem = 0
|
maxmem = 0
|
||||||
@ -795,9 +882,11 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
if maxmem != curr_maxmem:
|
if maxmem != curr_maxmem:
|
||||||
if curr_maxmem > 0:
|
if curr_maxmem > 0:
|
||||||
self.vm.features['qubesmanager.maxmem_value'] = curr_maxmem
|
self.vm.features['qubesmanager.maxmem_value'] = curr_maxmem
|
||||||
self.vm.maxmem = maxmem
|
if maxmem == 0 or self.max_mem_size.isEnabled():
|
||||||
|
self.vm.maxmem = maxmem
|
||||||
|
|
||||||
if self.vcpus.value() != int(self.vm.vcpus):
|
if self.vcpus.isEnabled() and \
|
||||||
|
self.vcpus.value() != int(self.vm.vcpus):
|
||||||
self.vm.vcpus = self.vcpus.value()
|
self.vm.vcpus = self.vcpus.value()
|
||||||
|
|
||||||
except qubesadmin.exc.QubesException as ex:
|
except qubesadmin.exc.QubesException as ex:
|
||||||
@ -909,7 +998,10 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
if hasattr(self, "dev_list"):
|
if hasattr(self, "dev_list"):
|
||||||
devs_attached = self.dev_list.selected_list.count() != 0
|
devs_attached = self.dev_list.selected_list.count() != 0
|
||||||
else:
|
else:
|
||||||
devs_attached = bool(list(self.vm.devices['pci'].persistent()))
|
try:
|
||||||
|
devs_attached = bool(list(self.vm.devices['pci'].persistent()))
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
devs_attached = False
|
||||||
|
|
||||||
if devs_attached:
|
if devs_attached:
|
||||||
self.pvh_mode_hidden.show()
|
self.pvh_mode_hidden.show()
|
||||||
@ -923,18 +1015,25 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
|
|
||||||
# due to how virtualization mode has uniquely different displayed and
|
# due to how virtualization mode has uniquely different displayed and
|
||||||
# actual name of the default value, I will add it manually
|
# actual name of the default value, I will add it manually
|
||||||
choices.insert(0, (
|
try:
|
||||||
"default ({})".format(
|
choices.insert(0, (
|
||||||
self.vm.property_get_default('virt_mode').upper()),
|
"default ({})".format(
|
||||||
qubesadmin.DEFAULT))
|
self.vm.property_get_default('virt_mode').upper()),
|
||||||
|
qubesadmin.DEFAULT))
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
choices.insert(0,
|
||||||
|
("default ({SYSTEM DEFAULT})", qubesadmin.DEFAULT))
|
||||||
|
|
||||||
utils.initialize_widget_for_property(
|
try:
|
||||||
widget=self.virt_mode,
|
utils.initialize_widget_for_property(
|
||||||
choices=choices,
|
widget=self.virt_mode,
|
||||||
holder=self.vm,
|
choices=choices,
|
||||||
property_name='virt_mode')
|
holder=self.vm,
|
||||||
|
property_name='virt_mode')
|
||||||
|
except qubesadmin.exc.QubesPropertyAccessError:
|
||||||
|
self.virt_mode.setEnabled(False)
|
||||||
|
|
||||||
if old_mode is not None:
|
if self.virt_mode.isEnabled() and old_mode is not None:
|
||||||
self.virt_mode.setCurrentIndex(self.virt_mode.findData(old_mode))
|
self.virt_mode.setCurrentIndex(self.virt_mode.findData(old_mode))
|
||||||
|
|
||||||
self.virt_mode.currentIndexChanged.connect(self.virt_mode_changed)
|
self.virt_mode.currentIndexChanged.connect(self.virt_mode_changed)
|
||||||
@ -967,7 +1066,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if name is qubesadmin.DEFAULT:
|
if name is qubesadmin.DEFAULT:
|
||||||
name = self.vm.app.default_kernel
|
name = getattr(self.vm.app, 'default_kernel', None)
|
||||||
|
|
||||||
m = re.search(r'(\d+)\.(\d+)', name)
|
m = re.search(r'(\d+)\.(\d+)', name)
|
||||||
|
|
||||||
@ -982,9 +1081,14 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.dev_list.add_all_button.setVisible(False)
|
self.dev_list.add_all_button.setVisible(False)
|
||||||
self.devices_layout.addWidget(self.dev_list)
|
self.devices_layout.addWidget(self.dev_list)
|
||||||
|
|
||||||
dom0_devs = list(self.vm.app.domains['dom0'].devices['pci'].available())
|
try:
|
||||||
|
dom0_devs = \
|
||||||
attached_devs = list(self.vm.devices['pci'].persistent())
|
list(self.vm.app.domains['dom0'].devices['pci'].available())
|
||||||
|
attached_devs = list(self.vm.devices['pci'].persistent())
|
||||||
|
except qubesadmin.exc.QubesException:
|
||||||
|
# no permission to access devices
|
||||||
|
self.tabWidget.setTabEnabled(self.tabs_indices['devices'], False)
|
||||||
|
return
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class DevListWidgetItem(QtWidgets.QListWidgetItem):
|
class DevListWidgetItem(QtWidgets.QListWidgetItem):
|
||||||
@ -1014,7 +1118,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
self.dmm_warning_adv.hide()
|
self.dmm_warning_adv.hide()
|
||||||
self.dmm_warning_dev.hide()
|
self.dmm_warning_dev.hide()
|
||||||
|
|
||||||
if self.vm.is_running():
|
if utils.is_running(self.vm, False):
|
||||||
self.dev_list.setEnabled(False)
|
self.dev_list.setEnabled(False)
|
||||||
self.turn_off_vm_to_modify_devs.setVisible(True)
|
self.turn_off_vm_to_modify_devs.setVisible(True)
|
||||||
self.no_strict_reset_button.setEnabled(False)
|
self.no_strict_reset_button.setEnabled(False)
|
||||||
@ -1024,11 +1128,14 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
|
|
||||||
self.update_pvh_dont_support_devs()
|
self.update_pvh_dont_support_devs()
|
||||||
|
|
||||||
self.dev_list.setEnabled(not self.vm.is_running())
|
self.dev_list.setEnabled(not utils.is_running(self.vm, False))
|
||||||
|
|
||||||
def __apply_devices_tab__(self):
|
def __apply_devices_tab__(self):
|
||||||
msg = []
|
msg = []
|
||||||
|
|
||||||
|
if not self.tabWidget.isTabEnabled(self.tabs_indices['devices']):
|
||||||
|
return msg
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_devs = list(self.vm.devices['pci'].persistent())
|
old_devs = list(self.vm.devices['pci'].persistent())
|
||||||
|
|
||||||
@ -1137,16 +1244,20 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
|
|
||||||
def __init_services_tab__(self):
|
def __init_services_tab__(self):
|
||||||
self.new_srv_dict = {}
|
self.new_srv_dict = {}
|
||||||
for feature in self.vm.features:
|
try:
|
||||||
if not feature.startswith('service.'):
|
for feature in self.vm.features:
|
||||||
continue
|
if not feature.startswith('service.'):
|
||||||
service = feature[len('service.'):]
|
continue
|
||||||
item = QtWidgets.QListWidgetItem(service)
|
service = feature[len('service.'):]
|
||||||
item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked
|
item = QtWidgets.QListWidgetItem(service)
|
||||||
if self.vm.features[feature]
|
item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked
|
||||||
else ui_settingsdlg.QtCore.Qt.Unchecked)
|
if self.vm.features[feature]
|
||||||
self.services_list.addItem(item)
|
else ui_settingsdlg.QtCore.Qt.Unchecked)
|
||||||
self.new_srv_dict[service] = self.vm.features[feature]
|
self.services_list.addItem(item)
|
||||||
|
self.new_srv_dict[service] = self.vm.features[feature]
|
||||||
|
except qubesadmin.exc.QubesDaemonCommunicationError:
|
||||||
|
self.tabWidget.setTabEnabled(self.tabs_indices["services"], False)
|
||||||
|
return
|
||||||
|
|
||||||
self.service_line_edit.addItem("")
|
self.service_line_edit.addItem("")
|
||||||
|
|
||||||
@ -1157,9 +1268,12 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
if feature.startswith(service_prefix):
|
if feature.startswith(service_prefix):
|
||||||
supported_services.add(feature[len(service_prefix):])
|
supported_services.add(feature[len(service_prefix):])
|
||||||
if getattr(self.vm, "template", None):
|
if getattr(self.vm, "template", None):
|
||||||
for feature in self.vm.template.features:
|
try:
|
||||||
if feature.startswith(service_prefix):
|
for feature in self.vm.template.features:
|
||||||
supported_services.add(feature[len(service_prefix):])
|
if feature.startswith(service_prefix):
|
||||||
|
supported_services.add(feature[len(service_prefix):])
|
||||||
|
except qubesadmin.exc.QubesDaemonCommunicationError:
|
||||||
|
pass
|
||||||
|
|
||||||
for service in sorted(supported_services):
|
for service in sorted(supported_services):
|
||||||
self.service_line_edit.addItem(service)
|
self.service_line_edit.addItem(service)
|
||||||
@ -1205,6 +1319,9 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
|||||||
def __apply_services_tab__(self):
|
def __apply_services_tab__(self):
|
||||||
msg = []
|
msg = []
|
||||||
|
|
||||||
|
if not self.tabWidget.isTabEnabled(self.tabs_indices['services']):
|
||||||
|
return msg
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for i in range(self.services_list.count()):
|
for i in range(self.services_list.count()):
|
||||||
item = self.services_list.item(i)
|
item = self.services_list.item(i)
|
||||||
|
@ -1313,8 +1313,8 @@ class QubeManagerThreadTest(unittest.TestCase):
|
|||||||
|
|
||||||
@unittest.mock.patch('subprocess.check_call')
|
@unittest.mock.patch('subprocess.check_call')
|
||||||
def test_20_update_vm_thread_dom0(self, check_call):
|
def test_20_update_vm_thread_dom0(self, check_call):
|
||||||
vm = unittest.mock.Mock(spec=['qid'])
|
vm = unittest.mock.Mock(spec=['klass'])
|
||||||
vm.qid = 0
|
vm.klass = 'AdminVM'
|
||||||
thread = qube_manager.UpdateVMThread(vm)
|
thread = qube_manager.UpdateVMThread(vm)
|
||||||
thread.run()
|
thread.run()
|
||||||
|
|
||||||
@ -1325,10 +1325,10 @@ class QubeManagerThreadTest(unittest.TestCase):
|
|||||||
@unittest.mock.patch('subprocess.call')
|
@unittest.mock.patch('subprocess.call')
|
||||||
def test_21_update_vm_thread_running(self, mock_call, mock_open):
|
def test_21_update_vm_thread_running(self, mock_call, mock_open):
|
||||||
vm = unittest.mock.Mock(
|
vm = unittest.mock.Mock(
|
||||||
spec=['qid', 'is_running', 'run_service_for_stdio', 'run_service'],
|
spec=['klass', 'is_running', 'run_service_for_stdio', 'run_service'],
|
||||||
**{'is_running.return_value': True})
|
**{'is_running.return_value': True})
|
||||||
|
|
||||||
vm.qid = 1
|
vm.klass = 'AppVM'
|
||||||
vm.run_service_for_stdio.return_value = (b'changed=no\n', None)
|
vm.run_service_for_stdio.return_value = (b'changed=no\n', None)
|
||||||
|
|
||||||
thread = qube_manager.UpdateVMThread(vm)
|
thread = qube_manager.UpdateVMThread(vm)
|
||||||
@ -1350,11 +1350,11 @@ class QubeManagerThreadTest(unittest.TestCase):
|
|||||||
@unittest.mock.patch('subprocess.call')
|
@unittest.mock.patch('subprocess.call')
|
||||||
def test_22_update_vm_thread_not_running(self, mock_call, mock_open):
|
def test_22_update_vm_thread_not_running(self, mock_call, mock_open):
|
||||||
vm = unittest.mock.Mock(
|
vm = unittest.mock.Mock(
|
||||||
spec=['qid', 'is_running', 'run_service_for_stdio',
|
spec=['klass', 'is_running', 'run_service_for_stdio',
|
||||||
'run_service', 'start', 'name'],
|
'run_service', 'start', 'name'],
|
||||||
**{'is_running.return_value': False})
|
**{'is_running.return_value': False})
|
||||||
|
|
||||||
vm.qid = 1
|
vm.klass = 'AppVM'
|
||||||
vm.run_service_for_stdio.return_value = (b'changed=yes\n', None)
|
vm.run_service_for_stdio.return_value = (b'changed=yes\n', None)
|
||||||
|
|
||||||
thread = qube_manager.UpdateVMThread(vm)
|
thread = qube_manager.UpdateVMThread(vm)
|
||||||
@ -1377,10 +1377,10 @@ class QubeManagerThreadTest(unittest.TestCase):
|
|||||||
@unittest.mock.patch('subprocess.check_call')
|
@unittest.mock.patch('subprocess.check_call')
|
||||||
def test_23_update_vm_thread_error(self, *_args):
|
def test_23_update_vm_thread_error(self, *_args):
|
||||||
vm = unittest.mock.Mock(
|
vm = unittest.mock.Mock(
|
||||||
spec=['qid', 'is_running'],
|
spec=['klass', 'is_running'],
|
||||||
**{'is_running.side_effect': ChildProcessError})
|
**{'is_running.side_effect': ChildProcessError})
|
||||||
|
|
||||||
vm.qid = 1
|
vm.klass = 'AppVM'
|
||||||
|
|
||||||
thread = qube_manager.UpdateVMThread(vm)
|
thread = qube_manager.UpdateVMThread(vm)
|
||||||
thread.run()
|
thread.run()
|
||||||
|
@ -124,6 +124,8 @@ def get_boolean_feature(vm, feature_name):
|
|||||||
def did_widget_selection_change(widget):
|
def did_widget_selection_change(widget):
|
||||||
"""a simple heuristic to check if the widget text contains appropriately
|
"""a simple heuristic to check if the widget text contains appropriately
|
||||||
translated 'current'"""
|
translated 'current'"""
|
||||||
|
if not widget.isEnabled():
|
||||||
|
return False
|
||||||
return not translate(" (current)") in widget.currentText()
|
return not translate(" (current)") in widget.currentText()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user