From 80c59badd398fd031a60ed924f1084664ffeee3f Mon Sep 17 00:00:00 2001 From: Marcus Ofenhed Date: Sat, 30 Nov 2024 13:31:08 +0100 Subject: [PATCH] Added filter for qubes stored on inaccessible pools --- qubesmanager/qube_manager.py | 70 ++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 1ddb7424..a6155c63 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -227,9 +227,31 @@ def __init__(self, vm): self.icon = getattr(vm, 'icon', 'appvm-black') self.auto_cleanup = getattr(vm, 'auto_cleanup', False) + self.available = None self.state = {'power': "", 'outdated': ""} self.updateable = getattr(vm, 'updateable', False) - self.update(True) + self.update(update_size_on_disk=True, update_availability=True) + + def check_availability_state(self): + for volume in self.vm.volumes.values(): + if volume.ephemeral: + continue + if volume.pool not in self.vm.app.pools: + return False + if volume.source is not None: + if volume.source not in ( + pool_volume.vid + for pool in self.vm.app.pools.values() + for pool_volume in pool.volumes + ): + return False + elif volume.vid != "": + if volume.vid not in ( + pool_volume.vid + for pool_volume in self.vm.app.pools[volume.pool].volumes + ): + return False + return True def update_power_state(self): try: @@ -267,10 +289,15 @@ def update_power_state(self): except exc.QubesDaemonAccessError: pass - def update(self, update_size_on_disk=False, event=None): + def update(self, + update_size_on_disk=False, + update_availability=False, + event=None + ): """ Update VmInfo :param update_size_on_disk: should disk utilization be updated? + :param update_availability: should disk volume availability be updated? :param event: name of the event that caused the update, to avoid updating unnecessary properties; if event is none, update everything :return: None @@ -341,6 +368,9 @@ def update(self, update_size_on_disk=False, event=None): self.disk_float = None self.disk = None + if self.vm.klass != 'AdminVM' and update_availability: + self.available = self.check_availability_state() + if self.vm.klass != 'AdminVM': self.virt_mode = getattr(self.vm, 'virt_mode', None) else: @@ -691,6 +721,10 @@ def filterAcceptsRow(self, sourceRow, sourceParent): if not self.window.show_internal_action.isChecked() and vm.internal: return False + if not self.window.show_unavailable_pool_action.isChecked() and \ + not vm.available: + return False + if self.window.show_user.isChecked() \ and vm.klass in ['AppVM', 'StandaloneVM'] \ and not getattr(vm.vm, 'template_for_dispvms', False) \ @@ -800,6 +834,11 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None): self.show_internal_action.setCheckable(True) self.show_internal_action.toggled.connect(self.invalidate) + self.show_unavailable_pool_action = self.menu_view.addAction( + self.tr('Show qubes stored on unavailable storage pools')) + self.show_unavailable_pool_action.setCheckable(True) + self.show_unavailable_pool_action.toggled.connect(self.invalidate) + self.menu_view.addSeparator() self.menu_view.addAction(self.action_toolbar) self.menu_view.addAction(self.action_menubar) @@ -892,15 +931,27 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None): self.size_on_disk_timer.setInterval(1000 * 60 * 5) # every 5 mins self.size_on_disk_timer.start() + self.volumes_available_timer = QTimer() + self.volumes_available_timer.timeout.connect( + self.update_halted_availability + ) + self.volumes_available_timer.setInterval( + 1000 * 60 * 5 + ) # every 5 minutes + self.volumes_available_timer.start() + self.new_qube = QProcess() def eventFilter(self, _object, event): - ''' refresh disk usage every 60s if focused & every 5m in background ''' + ''' refresh disk info every 60s if focused & every 5m in background ''' if event.type() == QEvent.Type.WindowActivate: self.update_running_size() + self.update_halted_availability() self.size_on_disk_timer.setInterval(1000 * 60) + self.volumes_available_timer.setInterval(1000 * 60) elif event.type() == QEvent.Type.WindowDeactivate: self.size_on_disk_timer.setInterval(1000 * 60 * 5) + self.volumes_available_timer.setInterval(1000 * 60 * 5) return False def scroll_to_top(self): @@ -1018,6 +1069,8 @@ def save_showing(self): self.show_standalone.isChecked()) self.manager_settings.setValue('show/internal', self.show_internal_action.isChecked()) + self.manager_settings.setValue('show/unavailable_pool', + self.show_unavailable_pool_action.isChecked()) self.manager_settings.setValue('show/user', self.show_user.isChecked()) self.manager_settings.setValue('show/all', @@ -1139,6 +1192,14 @@ def update_running_size(self, *_args): self.qubes_cache.get_vm(qid=vm.qid).update( update_size_on_disk=True, event='disk_size') + def update_halted_availability(self, *_args): + if not self.show_unavailable_pool_action.isChecked(): + for vm in self.qubes_app.domains: + if not vm.is_running(): + self.qubes_cache.get_vm(qid=vm.qid).update( + update_availability=True, event='volume_availability') + self.invalidate() + def on_domain_added(self, _submitter, _event, vm, **_kwargs): try: domain = self.qubes_app.domains[vm] @@ -1258,6 +1319,9 @@ def load_manager_settings(self): self.show_internal_action.setChecked(self.manager_settings.value( 'show/internal', "false") == "true") + self.show_unavailable_pool_action.setChecked( + self.manager_settings.value( + 'show/unavailable_pool', "false") == "true") # load last window size self.resize(self.manager_settings.value("window_size", QSize(1100, 600)))