From 4bb6e66af4bf6922db3bc6c8300e61dda8b4b4eb Mon Sep 17 00:00:00 2001 From: Ben Grande Date: Thu, 22 Jan 2026 15:28:29 +0100 Subject: [PATCH] Skip events from mixins when unnecessary Mixins are loaded to other classes, which means that these events are called on a varied number of qubes even when it is unnecessary. --- qubes/tests/vm/qubesvm.py | 13 +------------ qubes/vm/mix/dvmtemplate.py | 10 ++++++++++ qubes/vm/mix/net.py | 9 +++++++++ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/qubes/tests/vm/qubesvm.py b/qubes/tests/vm/qubesvm.py index 2af1763b3..492621639 100644 --- a/qubes/tests/vm/qubesvm.py +++ b/qubes/tests/vm/qubesvm.py @@ -2457,8 +2457,6 @@ def test_620_qdb_standalone( "/qubes-iptables-header": iptables_header, "/qubes-service/qubes-update-check": "0", "/qubes-service/meminfo-writer": "1", - "/connected-ips": "", - "/connected-ips6": "", } self.assertEqual(test_qubesdb.data, data) @@ -2550,8 +2548,6 @@ def test_621_qdb_vm_with_network( "/qubes-gui-enabled": "False", "/qubes-primary-dns": "10.139.1.1", "/qubes-secondary-dns": "10.139.1.2", - "/connected-ips": "", - "/connected-ips6": "", } with self.subTest("ipv4"): @@ -2608,6 +2604,7 @@ def test_621_qdb_vm_with_network( expected["/qubes-firewall/10.137.0.3/0000"] = "action=accept" expected["/qubes-firewall/10.137.0.3/policy"] = "drop" expected["/connected-ips"] = "10.137.0.3" + expected["/connected-ips6"] = "" with unittest.mock.patch( "qubes.vm.qubesvm.QubesVM.is_running", lambda _: True @@ -2691,8 +2688,6 @@ def test_622_qdb_guivm_keyboard_layout( "/qubes-iptables-header": unittest.mock.ANY, "/qubes-service/qubes-update-check": "0", "/qubes-service/meminfo-writer": "1", - "/connected-ips": "", - "/connected-ips6": "", }, ) @@ -2750,8 +2745,6 @@ def test_623_qdb_audiovm(self, mock_qubesdb, mock_urandom, mock_timezone): "/qubes-iptables-header": unittest.mock.ANY, "/qubes-service/qubes-update-check": "0", "/qubes-service/meminfo-writer": "1", - "/connected-ips": "", - "/connected-ips6": "", }, ) @@ -2820,8 +2813,6 @@ def test_624_qdb_audiovm_change_to_new_and_none( "/qubes-iptables-header": unittest.mock.ANY, "/qubes-service/qubes-update-check": "0", "/qubes-service/meminfo-writer": "1", - "/connected-ips": "", - "/connected-ips6": "", } with self.subTest("default"): @@ -2926,8 +2917,6 @@ def test_626_qdb_keyboard_layout_change( "/qubes-iptables-header": unittest.mock.ANY, "/qubes-service/qubes-update-check": "0", "/qubes-service/meminfo-writer": "1", - "/connected-ips": "", - "/connected-ips6": "", } with self.subTest("default"): diff --git a/qubes/vm/mix/dvmtemplate.py b/qubes/vm/mix/dvmtemplate.py index 0209711f1..6fce68338 100644 --- a/qubes/vm/mix/dvmtemplate.py +++ b/qubes/vm/mix/dvmtemplate.py @@ -62,6 +62,8 @@ def on_domain_loaded(self, event) -> None: """ # pylint: disable=unused-argument assert isinstance(self, qubes.vm.BaseVM) + if not getattr(self, "template_for_dispvms"): + return changes = False # Began preloading, host rebooted, autostart script didn't run yet. old_preload = self.get_feat_preload() @@ -131,6 +133,8 @@ def __on_domain_pre_start(self, event, **kwargs) -> None: @qubes.events.handler("domain-remove-from-disk") async def on_dvmtemplate_remove_from_disk(self, event, **kwargs): # pylint: disable=unused-argument + if not getattr(self, "template_for_dispvms"): + return preloads = [disp for disp in self.dispvms if disp.is_preload] if not preloads: return @@ -148,6 +152,8 @@ async def on_dvmtemplate_domain_shutdown(self, _event, **_kwargs) -> None: """ Refresh preloaded disposables on shutdown. """ + if not getattr(self, "template_for_dispvms"): + return self.refresh_outdated_preload() @qubes.events.handler("property-reset:*", "property-set:*") @@ -155,6 +161,8 @@ def on_dvmtemplate_property_changed(self, _event, name, **_kwargs) -> None: """ Refresh preloaded disposables if property affects the disposable. """ + if not getattr(self, "template_for_dispvms"): + return if name not in qubes.vm.dispvm.PRELOAD_OUTDATED_IGNORED_PROPERTIES: self.refresh_outdated_preload(delay=30) @@ -407,6 +415,8 @@ def __on_pre_property_set_template( property. """ # pylint: disable=unused-argument + if not getattr(self, "template_for_dispvms"): + return if newvalue == oldvalue: return dependencies = [ diff --git a/qubes/vm/mix/net.py b/qubes/vm/mix/net.py index 7625341f4..dc552f636 100644 --- a/qubes/vm/mix/net.py +++ b/qubes/vm/mix/net.py @@ -294,6 +294,8 @@ def on_domain_load_netvm_loop_check(self, event): # pylint: disable=unused-argument # make sure there are no netvm loops - which could cause qubesd # looping infinitely + if not self.netvm: + return if self is self.netvm: self.log.error( "vm '%s' network-connected to itself, breaking the " @@ -338,6 +340,9 @@ async def on_domain_started_net(self, event, **kwargs): if self.netvm: self.netvm.reload_firewall_for_vm(self) # pylint: disable=no-member + if not self.provides_network: + return + for vm in self.connected_vms: if not vm.is_running() or vm.is_paused(): continue @@ -409,6 +414,8 @@ def on_domain_pre_shutdown(self, event, force=False): If `force` is `True` tries to detach network interfaces of connected vms """ # pylint: disable=unused-argument + if not self.provides_network: + return connected_vms = [ vm @@ -741,6 +748,8 @@ def on_property_set_provides(self, _event, name, newvalue, oldvalue=None): def on_domain_qdb_create(self, event): """Fills the QubesDB with firewall entries.""" # pylint: disable=unused-argument + if not self.provides_network: + return # Keep the following in sync with on_firewall_changed. self.reload_connected_ips()