Skip to content

Commit 5d9c320

Browse files
committed
Add handler for internal feature
For: QubesOS/qubes-issues#1512
1 parent 673a4a5 commit 5d9c320

2 files changed

Lines changed: 76 additions & 18 deletions

File tree

qubes_menu/tests/test_vmmanager.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,20 @@
2828
def test_vm_manager(test_qapp):
2929
dispatcher = qubesadmin.events.EventsDispatcher(test_qapp)
3030
vm_manager = VMManager(test_qapp, dispatcher)
31+
vm_name = "test-vm"
32+
template_name = "fedora-36"
3133

32-
entry_test = vm_manager.load_vm_from_name("test-vm")
34+
entry_test = vm_manager.load_vm_from_name(vm_name)
3335
assert entry_test
34-
assert entry_test.vm_name == "test-vm"
36+
assert entry_test.vm_name == vm_name
3537
assert entry_test.vm_icon_name == "appvm-green"
36-
entry_template = vm_manager.load_vm_from_name("fedora-36")
38+
entry_template = vm_manager.load_vm_from_name(template_name)
3739
assert entry_template
3840
assert not entry_template.has_network
41+
assert not entry_template.internal
3942
assert not entry_test.is_dispvm_template
4043
assert not entry_test.service_vm
44+
assert not entry_test.internal
4145

4246
test_qapp._qubes["fedora-36"].properties["netvm"] = Property(
4347
"sys-firewall", "vm", False
@@ -53,44 +57,62 @@ def test_vm_manager(test_qapp):
5357
)
5458
assert entry_template.has_network
5559

56-
test_qapp._qubes["test-vm"].properties["label"] = Property(
60+
test_qapp._qubes[vm_name].properties["label"] = Property(
5761
"red", "label", False
5862
)
59-
test_qapp._qubes["test-vm"].properties["icon"] = Property(
63+
test_qapp._qubes[vm_name].properties["icon"] = Property(
6064
"appvm-red", "str", False
6165
)
62-
test_qapp._qubes["test-vm"].update_calls()
63-
66+
test_qapp._qubes[vm_name].update_calls()
6467
vm_manager._update_domain_property(
65-
"test-vm",
68+
vm_name,
6669
"property-set:label",
6770
name="label",
6871
newvalue="red",
6972
oldvalue="blue",
7073
)
7174
assert entry_test.vm_icon_name == "appvm-red"
7275

73-
test_qapp._qubes["test-vm"].properties["template_for_dispvms"] = Property(
76+
test_qapp._qubes[vm_name].properties["template_for_dispvms"] = Property(
7477
"True", "bool", False
7578
)
76-
test_qapp._qubes["test-vm"].update_calls()
77-
79+
test_qapp._qubes[vm_name].update_calls()
7880
vm_manager._update_domain_property(
79-
"test-vm",
81+
vm_name,
8082
"property-set:template_for_dispvms",
8183
name="template_for_dispvms",
8284
newvalue=True,
8385
)
8486
assert entry_test.is_dispvm_template
8587

86-
test_qapp._qubes["test-vm"].features["servicevm"] = 1
87-
test_qapp._qubes["test-vm"].update_calls()
88-
88+
test_qapp._qubes[vm_name].features["servicevm"] = 1
89+
test_qapp._qubes[vm_name].update_calls()
8990
vm_manager._update_domain_feature(
90-
"test-vm", "feature-set:servicevm", feature="servicevm", value=1
91+
vm_name, "feature-set:servicevm", feature="servicevm", value=1
9192
)
9293
assert entry_test.service_vm
9394

95+
test_qapp._qubes[vm_name].features["internal"] = 1
96+
test_qapp._qubes[vm_name].update_calls()
97+
vm_manager._update_domain_feature(
98+
vm_name, "feature-set:internal", feature="internal", value=1
99+
)
100+
assert entry_test.internal
101+
102+
del test_qapp._qubes[vm_name].features["internal"]
103+
test_qapp._qubes[vm_name].update_calls()
104+
vm_manager._update_domain_feature(
105+
vm_name, "feature-delete:internal", feature="internal"
106+
)
107+
assert not entry_test.internal
108+
109+
test_qapp._qubes[template_name].features["internal"] = 1
110+
test_qapp._qubes[vm_name].update_calls()
111+
vm_manager._update_domain_feature(
112+
vm_name, "feature-set:internal", feature="internal", value=1
113+
)
114+
assert entry_test.internal
115+
94116

95117
def test_filter(test_qapp):
96118
dispatcher = qubesadmin.events.EventsDispatcher(test_qapp)

qubes_menu/vm_manager.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
Helper class that manages all events related to VMs.
2222
"""
2323
import qubesadmin.events
24+
import qubesadmin.exc
2425
from qubesadmin.vm import QubesVM
2526
from typing import Optional, Dict, List, Callable
2627

@@ -49,6 +50,12 @@ def __init__(self, vm: QubesVM):
4950
# the space here is to assure correct sorting for dispvm children
5051
self.sort_name = self.vm_name.lower() + " "
5152

53+
try:
54+
self._internal = bool(
55+
self.vm.features.check_with_template("internal", False)
56+
)
57+
except qubesadmin.exc.QubesDaemonAccessError:
58+
self._internal = False
5259
self._servicevm = bool(self.vm.features.get("servicevm", False))
5360
self._is_dispvm_template = getattr(
5461
self.vm, "template_for_dispvms", False
@@ -133,6 +140,16 @@ def is_dispvm_template(self, new_value):
133140
self._is_dispvm_template = new_value
134141
self.update_entries(update_type=True)
135142

143+
@property
144+
def internal(self):
145+
"""Is the VM internal"""
146+
return self._internal
147+
148+
@internal.setter
149+
def internal(self, new_value):
150+
self._internal = new_value
151+
self.update_entries(update_type=True)
152+
136153
@property
137154
def service_vm(self):
138155
"""Does the VM provide network"""
@@ -146,6 +163,8 @@ def service_vm(self, new_value):
146163
@property
147164
def show_in_apps(self):
148165
"""Should this qube be shown in the Apps section of the menu?"""
166+
if self.internal:
167+
return False
149168
if self.service_vm:
150169
return False
151170
if self.vm_klass == "TemplateVM":
@@ -212,8 +231,11 @@ def load_vm_from_name(self, vm_name: str) -> Optional[VMEntry]:
212231
vm: QubesVM = self.qapp.domains[vm_name]
213232
except KeyError:
214233
return None
215-
if vm.features.get("internal", False):
216-
return None
234+
try:
235+
if vm.features.check_with_template("internal", False):
236+
return None
237+
except qubesadmin.exc.QubesDaemonAccessError:
238+
pass
217239

218240
return self._add_vm(vm)
219241

@@ -289,6 +311,14 @@ def _update_domain_feature(
289311
value = bool(value)
290312

291313
try:
314+
if feature == "internal":
315+
vm_entry.internal = value
316+
for derived in self.qapp.domains:
317+
if not getattr(derived, "template", None) == vm:
318+
continue
319+
derived_vm_entry = self.load_vm_from_name(derived)
320+
if derived_vm_entry:
321+
derived_vm_entry.internal = value
292322
if feature == "servicevm":
293323
vm_entry.service_vm = value
294324
if feature == "appmenus-dispvm":
@@ -354,3 +384,9 @@ def register_events(self):
354384
self.dispatcher.add_handler(
355385
"domain-feature-delete:appmenus-dispvm", self._update_domain_feature
356386
)
387+
self.dispatcher.add_handler(
388+
"domain-feature-set:internal", self._update_domain_feature
389+
)
390+
self.dispatcher.add_handler(
391+
"domain-feature-delete:internal", self._update_domain_feature
392+
)

0 commit comments

Comments
 (0)