Skip to content

Commit f3d7fe6

Browse files
committed
Add prohibit-start to Qube Settings GUI.
1 parent 918b8d2 commit f3d7fe6

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

qubesmanager/qube_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def helpEvent(self, event, view, option, index):
198198
QToolTip.showText(event.globalPos(),
199199
self.tr(
200200
"The qube is prohibited from starting\n"
201-
"See `qvm-features` manual for more information"
201+
"Prohibition rationale is available in qube settings -> Advanced tab"
202202
),
203203
view
204204
)

qubesmanager/settings.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,17 @@ def __init_advanced_tab__(self):
951951
self.run_in_debug_mode.setVisible(False)
952952
self.run_in_debug_mode.setEnabled(False)
953953

954+
rationale = utils.get_feature(self.vm, "prohibit-start", "")
955+
self.prohibit_start_rationale.setText(rationale)
956+
self.prohibit_start_rationale.setVisible(bool(rationale))
957+
self.prohibit_start_rationale.textEdited.connect(
958+
lambda x: self.prohibit_start_checkbox.setChecked(bool(x))
959+
)
960+
self.prohibit_start_checkbox.setChecked(bool(rationale))
961+
self.prohibit_start_checkbox.stateChanged.connect(
962+
lambda x: self.prohibit_start_rationale.setVisible(bool(x))
963+
)
964+
954965
utils.initialize_widget(
955966
widget=self.allow_fullscreen,
956967
choices=[
@@ -1070,6 +1081,17 @@ def __apply_advanced_tab__(self):
10701081
except qubesadmin.exc.QubesException as ex:
10711082
msg.append(str(ex))
10721083

1084+
rationale = self.vm.features.get("prohibit-start", "")
1085+
if (self.prohibit_start_checkbox.isChecked() != bool(rationale)) or (
1086+
bool(rationale)
1087+
and self.prohibit_start_rationale.text() != rationale
1088+
):
1089+
rationale = self.prohibit_start_rationale.text()
1090+
if bool(rationale) and self.prohibit_start_checkbox.isChecked():
1091+
self.vm.features["prohibit-start"] = rationale
1092+
else:
1093+
del self.vm.features["prohibit-start"]
1094+
10731095
if self.allow_fullscreen_initial !=\
10741096
self.allow_fullscreen.currentIndex():
10751097
try:

qubesmanager/tests/test_vm_settings.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,40 @@ def test_212_boot_from_device(mock_boot, mock_start, settings_fixture):
907907
mock_start.assert_called_with(['--cdrom', mock.ANY, vm.name])
908908

909909

910+
@check_errors
911+
@pytest.mark.parametrize("settings_fixture", TEST_VMS, indirect=True)
912+
def test_213_prohibit_start(settings_fixture):
913+
settings_window, page, vm_name = settings_fixture
914+
vm = settings_window.qubesapp.domains[vm_name]
915+
916+
r = vm.features.get("prohibit-start", "")
917+
assert settings_window.prohibit_start_checkbox.isChecked() == bool(r)
918+
assert settings_window.prohibit_start_rationale.text() == r
919+
920+
settings_window.prohibit_start_checkbox.setChecked(not bool(r))
921+
922+
if bool(r):
923+
settings_window.prohibit_start_rationale.setText("")
924+
expected_call = (
925+
vm.name,
926+
"admin.vm.feature.Remove",
927+
"prohibit-start",
928+
None,
929+
)
930+
else:
931+
settings_window.prohibit_start_rationale.setText("RATIONALE")
932+
expected_call = (
933+
vm.name,
934+
"admin.vm.feature.Set",
935+
"prohibit-start",
936+
"RATIONALE".encode(),
937+
)
938+
939+
assert expected_call not in settings_window.qubesapp.actual_calls
940+
settings_window.qubesapp.expected_calls[expected_call] = b"0\x00"
941+
settings_window.accept()
942+
943+
910944
# FIREWALL TAB
911945

912946
@check_errors

ui/settingsdlg.ui

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,14 +742,32 @@ border-width: 1px;</string>
742742
<property name="topMargin">
743743
<number>15</number>
744744
</property>
745-
<item row="2" column="0">
745+
<item row="2" column="0" colspan="2">
746+
<layout class="QHBoxLayout" name="horizontalLayout_prohibit_start">
747+
<item>
748+
<widget class="QCheckBox" name="prohibit_start_checkbox">
749+
<property name="text">
750+
<string>Prohibit start</string>
751+
</property>
752+
</widget>
753+
</item>
754+
<item>
755+
<widget class="QLineEdit" name="prohibit_start_rationale">
756+
<property name="placeholderText">
757+
<string>Start prohibition rationale (mandatory)</string>
758+
</property>
759+
</widget>
760+
</item>
761+
</layout>
762+
</item>
763+
<item row="3" column="0">
746764
<widget class="QCheckBox" name="provides_network_checkbox">
747765
<property name="text">
748766
<string>Provides network</string>
749767
</property>
750768
</widget>
751769
</item>
752-
<item row="3" column="0">
770+
<item row="4" column="0">
753771
<widget class="QCheckBox" name="dvm_template_checkbox">
754772
<property name="toolTip">
755773
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Allows using this qube as a template for disposables. Disposables will inherit the qube's state (configuration, installed programs, etc.), but their state will not persist between restarts. &lt;/p&gt;&lt;p&gt;Setting this option will cause this qube to be listed as an option in the &amp;quot;Default disposable template&amp;quot; list for all other qubes.&lt;/p&gt;&lt;p&gt;Only AppVMs and StandaloneVMs could be turned in to Disposable Templates&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>

0 commit comments

Comments
 (0)