Browse Source

Add pre- events to vm features

Allow extensions to validate feature values, before it is set.
Marek Marczykowski-Górecki 4 years ago
parent
commit
d05592ba52
3 changed files with 38 additions and 0 deletions
  1. 9 0
      qubes/features.py
  2. 6 0
      qubes/tests/vm/init.py
  3. 23 0
      qubes/vm/qubesvm.py

+ 9 - 0
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,

+ 6 - 0
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'})
 

+ 23 - 0
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.