diff --git a/qubes/ext/core_features.py b/qubes/ext/core_features.py index b24dc9e7..4df3da9f 100644 --- a/qubes/ext/core_features.py +++ b/qubes/ext/core_features.py @@ -62,3 +62,25 @@ class CoreFeatures(qubes.ext.Extension): # if this is the first time qrexec was advertised, now can finish # template setup yield from vm.fire_event_async('template-postinstall') + + # pylint: disable=no-self-use + def set_servicevm_feature(self, subject): + if getattr(subject, 'provides_network', False): + subject.features['servicevm'] = 1 + elif 'servicevm' in subject.features: + del subject.features['servicevm'] + + @qubes.ext.handler('property-set:provides_network') + def on_property_set(self, subject, event, name, newvalue, oldvalue=None): + # pylint: disable=unused-argument + self.set_servicevm_feature(subject) + + @qubes.ext.handler('property-del:provides_network') + def on_property_del(self, subject, event, name): + # pylint: disable=unused-argument + self.set_servicevm_feature(subject) + + @qubes.ext.handler('domain-load') + def on_domain_load(self, subject, event): + # pylint: disable=unused-argument + self.set_servicevm_feature(subject) diff --git a/qubes/tests/ext.py b/qubes/tests/ext.py index 8767dfef..fde1f6c2 100644 --- a/qubes/tests/ext.py +++ b/qubes/tests/ext.py @@ -34,8 +34,11 @@ class TC_00_CoreFeatures(qubes.tests.QubesTestCase): self.features = {} self.vm.configure_mock(**{ 'features.get.side_effect': self.features.get, + 'features.items.side_effect': self.features.items, + 'features.__iter__.side_effect': self.features.__iter__, 'features.__contains__.side_effect': self.features.__contains__, 'features.__setitem__.side_effect': self.features.__setitem__, + 'features.__delitem__.side_effect': self.features.__delitem__, }) def test_010_notify_tools(self): @@ -181,6 +184,16 @@ class TC_00_CoreFeatures(qubes.tests.QubesTestCase): ('features.__contains__', ('gui',), {}), ]) + def test_100_servicevm_feature(self): + self.vm.provides_network = True + self.ext.set_servicevm_feature(self.vm) + self.assertEqual(self.features['servicevm'], 1) + + self.vm.provides_network = False + self.ext.set_servicevm_feature(self.vm) + self.assertNotIn('servicevm', self.features) + + class TC_10_WindowsFeatures(qubes.tests.QubesTestCase): def setUp(self): super().setUp()