Skip to content

Commit f965d8c

Browse files
committed
Add Debug Console to Qui Domains systray widget
fixes: QubesOS/qubes-issues#9788
1 parent 7652c60 commit f965d8c

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

qui/tray/domains.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,26 @@ async def perform_action(self):
316316
)
317317

318318

319+
class RunDebugConsoleItem(VMActionMenuItem):
320+
"""Run Debug Console menu Item. When activated runs a qvm-console-dispvm."""
321+
322+
def __init__(self, vm, icon_cache):
323+
img = Gtk.Image.new_from_file(
324+
"/usr/share/icons/HighContrast/16x16/apps/logviewer.png"
325+
)
326+
super().__init__(
327+
vm,
328+
label=_("Debug Console"),
329+
img=img,
330+
)
331+
332+
async def perform_action(self):
333+
# pylint: disable=consider-using-with
334+
await asyncio.create_subprocess_exec(
335+
"qvm-console-dispvm", self.vm.name, stderr=subprocess.PIPE
336+
)
337+
338+
319339
class OpenFileManagerItem(VMActionMenuItem):
320340
"""Attempts to open a file manager in the VM. If fails, displays an
321341
error message."""
@@ -368,6 +388,11 @@ def __init__(self, vm, app, icon_cache):
368388

369389
self.add(OpenFileManagerItem(self.vm, icon_cache))
370390
self.add(RunTerminalItem(self.vm, icon_cache))
391+
392+
# Debug console for developers, troubleshooting, headless qubes
393+
self.debug_console = RunDebugConsoleItem(self.vm, icon_cache)
394+
self.add(self.debug_console)
395+
371396
self.add(PreferencesItem(self.vm, icon_cache))
372397
self.add(PauseItem(self.vm, icon_cache))
373398
self.add(ShutdownItem(self.vm, icon_cache))
@@ -377,6 +402,24 @@ def __init__(self, vm, app, icon_cache):
377402
self.set_reserve_toggle_size(False)
378403
self.show_all()
379404

405+
def show_all(self):
406+
super().do_show_all(self)
407+
self.debug_console_update()
408+
409+
def debug_console_update(self, *_args, **_kwargs):
410+
# Debug console is shown only if debug property is set, no GUIVM is set
411+
# ... or with `wizard-mode` feature per qube or per entire GUIVM.
412+
if (
413+
self.app.wizard_mode
414+
or getattr(self.vm, "debug")
415+
or not getattr(self.vm, "guivm")
416+
or bool(self.vm.features.get("wizard-mode", False))
417+
or bool(self.vm.features.get("gui", False))
418+
):
419+
self.debug_console.show()
420+
else:
421+
self.debug_console.hide()
422+
380423

381424
class PausedMenu(Gtk.Menu):
382425
"""The sub-menu for a paused domain"""
@@ -668,6 +711,11 @@ def __init__(self, app_name, qapp, dispatcher, stats_dispatcher):
668711
self.set_application_id(app_name)
669712
self.register() # register Gtk Application
670713

714+
# to display debug console for all qubes
715+
self.wizard_mode = self.qapp.domains[self.qapp.local_name].features.get(
716+
"wizard-mode", False
717+
)
718+
671719
def register_events(self):
672720
self.dispatcher.add_handler("connection-established", self.refresh_all)
673721
self.dispatcher.add_handler("domain-pre-start", self.update_domain_item)
@@ -717,6 +765,32 @@ def register_events(self):
717765

718766
self.stats_dispatcher.add_handler("vm-stats", self.update_stats)
719767

768+
self.dispatcher.add_handler("property-set:debug", self.debug_change)
769+
self.dispatcher.add_handler("property-set:guivm", self.debug_change)
770+
self.dispatcher.add_handler("domain-feature-set:gui", self.debug_change)
771+
self.dispatcher.add_handler(
772+
"domain-feature-delete:gui", self.debug_change
773+
)
774+
self.dispatcher.add_handler(
775+
"domain-feature-set:wizard-mode", self.debug_change
776+
)
777+
self.dispatcher.add_handler(
778+
"domain-feature-delete:wizard-mode", self.debug_change
779+
)
780+
781+
def debug_change(self, vm, *_args, **_kwargs):
782+
if vm == self.qapp.local_name:
783+
self.wizard_mode = self.qapp.domains[
784+
self.qapp.local_name
785+
].features.get("wizard-mode", False)
786+
vms = self.menu_items
787+
else:
788+
vms = {vm}
789+
for menu in vms:
790+
submenu = self.menu_items[menu].get_submenu()
791+
if isinstance(submenu, StartedMenu):
792+
submenu.debug_console_update()
793+
720794
def show_menu(self, _unused, event):
721795
self.tray_menu.popup_at_pointer(event) # None means current event
722796

@@ -1069,6 +1143,21 @@ def _disconnect_signals(self, _event):
10691143

10701144
self.stats_dispatcher.remove_handler("vm-stats", self.update_stats)
10711145

1146+
self.dispatcher.remove_handler("property-set:debug", self.debug_change)
1147+
self.dispatcher.remove_handler("property-set:guivm", self.debug_change)
1148+
self.dispatcher.remove_handler(
1149+
"domain-feature-set:gui", self.debug_change
1150+
)
1151+
self.dispatcher.remove_handler(
1152+
"domain-feature-delete:gui", self.debug_change
1153+
)
1154+
self.dispatcher.remove_handler(
1155+
"domain-feature-set:wizard-mode", self.debug_change
1156+
)
1157+
self.dispatcher.remove_handler(
1158+
"domain-feature-delete:wizard-mode", self.debug_change
1159+
)
1160+
10721161

10731162
def main():
10741163
"""main function"""

0 commit comments

Comments
 (0)