From d05592ba529a55bad5f10db4d660a332af6ce628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Tue, 17 Mar 2020 03:46:35 +0100 Subject: [PATCH] Add pre- events to vm features Allow extensions to validate feature values, before it is set. --- qubes/features.py | 9 +++++++++ qubes/tests/vm/init.py | 6 ++++++ qubes/vm/qubesvm.py | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/qubes/features.py b/qubes/features.py index 8e40deec..61e42381 100644 --- a/qubes/features.py +++ b/qubes/features.py @@ -51,6 +51,7 @@ class Features(dict): self.update(other, **kwargs) def __delitem__(self, key): + self.subject.fire_event('domain-feature-pre-delete:' + key, feature=key) super().__delitem__(key) self.subject.fire_event('domain-feature-delete:' + key, feature=key) @@ -64,6 +65,14 @@ class Features(dict): has_oldvalue = True except KeyError: has_oldvalue = False + if has_oldvalue: + self.subject.fire_event('domain-feature-pre-set:' + key, + pre_event=True, + feature=key, value=value, oldvalue=oldvalue) + else: + self.subject.fire_event('domain-feature-pre-set:' + key, + pre_event=True, + feature=key, value=value) super().__setitem__(key, value) if has_oldvalue: self.subject.fire_event('domain-feature-set:' + key, feature=key, diff --git a/qubes/tests/vm/init.py b/qubes/tests/vm/init.py index a669d46a..f48585a6 100644 --- a/qubes/tests/vm/init.py +++ b/qubes/tests/vm/init.py @@ -217,6 +217,8 @@ class TC_21_Features(qubes.tests.QubesTestCase): def test_000_set(self): self.features['testfeature'] = 'value' + self.assertEventFired(self.vm, 'domain-feature-pre-set:testfeature', + kwargs={'feature': 'testfeature', 'value': 'value'}) self.assertEventFired(self.vm, 'domain-feature-set:testfeature', kwargs={'feature': 'testfeature', 'value': 'value'}) @@ -263,8 +265,12 @@ class TC_21_Features(qubes.tests.QubesTestCase): self.features['test2'] = 'value2' self.vm.fired_events.clear() self.features.clear() + self.assertEventFired(self.vm, 'domain-feature-pre-delete:test', + kwargs={'feature': 'test'}) self.assertEventFired(self.vm, 'domain-feature-delete:test', kwargs={'feature': 'test'}) + self.assertEventFired(self.vm, 'domain-feature-pre-delete:test2', + kwargs={'feature': 'test2'}) self.assertEventFired(self.vm, 'domain-feature-delete:test2', kwargs={'feature': 'test2'}) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 395614f5..47b488f7 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -420,6 +420,19 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): :param subject: Event emitter (the qube object) :param event: Event name (``'domain-restore'``) + .. event:: domain-feature-pre-set:feature (subject, event, feature, + value [, oldvalue]) + + A feature will be changed. This event is fired before value is set. + If any handler raises an exception, value will not be set. + *oldvalue* is present only when there was any. + + :param subject: Event emitter (the qube object) + :param event: Event name (``'domain-feature-pre-set:' feature``) + :param feature: feature name + :param value: new value + :param oldvalue: old value, if any + .. event:: domain-feature-set:feature (subject, event, feature, value [, oldvalue]) @@ -442,6 +455,16 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): :param event: Event name (``'domain-feature-delete:' feature``) :param feature: feature name + .. event:: domain-feature-pre-delete:feature (subject, event, feature) + + A feature will be removed. This event is fired before feature is + removed. If any handler raises an exception,feature will not be + removed. + + :param subject: Event emitter (the qube object) + :param event: Event name (``'domain-feature-pre-delete:' feature``) + :param feature: feature name + .. event:: domain-tag-add:tag (subject, event, tag) A tag was added.