Преглед на файлове

Merge branch 'rename-property-del-reset'

* rename-property-del-reset:
  Fire property-reset event when default value might change
  Convert handler to use property-reset instead of property-del
  Remove leftovers of default_fw_netvm
  Deprecate property-del:name events and introduce property-reset:name instead
Marek Marczykowski-Górecki преди 4 години
родител
ревизия
eba628e90f
променени са 12 файла, в които са добавени 158 реда и са изтрити 37 реда
  1. 42 0
      qubes/__init__.py
  2. 2 18
      qubes/app.py
  3. 2 3
      qubes/ext/audio.py
  4. 6 2
      qubes/ext/core_features.py
  5. 2 3
      qubes/ext/gui.py
  6. 2 2
      qubes/firewall.py
  7. 8 0
      qubes/tests/init.py
  8. 2 2
      qubes/vm/appvm.py
  9. 1 1
      qubes/vm/dispvm.py
  10. 57 4
      qubes/vm/mix/net.py
  11. 10 2
      qubes/vm/qubesvm.py
  12. 24 0
      qubes/vm/templatevm.py

+ 42 - 0
qubes/__init__.py

@@ -284,6 +284,10 @@ class property:  # pylint: disable=redefined-builtin,invalid-name
             has_oldvalue = False
 
         if has_oldvalue:
+            instance.fire_event('property-pre-reset:' + self.__name__,
+                pre_event=True,
+                name=self.__name__, oldvalue=oldvalue)
+            # deprecated, to be removed in Qubes 5.0
             instance.fire_event('property-pre-del:' + self.__name__,
                 pre_event=True,
                 name=self.__name__, oldvalue=oldvalue)
@@ -291,13 +295,23 @@ class property:  # pylint: disable=redefined-builtin,invalid-name
                 delattr(instance, self._attr_name)
             except AttributeError:
                 pass
+            instance.fire_event('property-reset:' + self.__name__,
+                name=self.__name__, oldvalue=oldvalue)
+            # deprecated, to be removed in Qubes 5.0
             instance.fire_event('property-del:' + self.__name__,
                 name=self.__name__, oldvalue=oldvalue)
 
         else:
+            instance.fire_event('property-pre-reset:' + self.__name__,
+                pre_event=True,
+                name=self.__name__)
+            # deprecated, to be removed in Qubes 5.0
             instance.fire_event('property-pre-del:' + self.__name__,
                 pre_event=True,
                 name=self.__name__)
+            instance.fire_event('property-reset:' + self.__name__,
+                name=self.__name__)
+            # deprecated, to be removed in Qubes 5.0
             instance.fire_event('property-del:' + self.__name__,
                 name=self.__name__)
 
@@ -470,6 +484,9 @@ class PropertyHolder(qubes.events.Emitter):
             Fired when property gets deleted (is set to default). Signature is
             variable, *oldvalue* is present only if there was an old value.
 
+            This event is deprecated and will be removed in Qubes 5.0.
+            Use property-reset instead.
+
             :param name: Property name
             :param oldvalue: Old value of the property
 
@@ -479,6 +496,31 @@ class PropertyHolder(qubes.events.Emitter):
             Fired before property gets deleted (is set to default). Signature
             is variable, *oldvalue* is present only if there was an old value.
 
+            This event is deprecated and will be removed in Qubes 5.0.
+            Use property-pre-reset instead.
+
+            :param name: Property name
+            :param oldvalue: Old value of the property
+
+        .. event:: property-reset:<propname> \
+                (subject, event, name[, oldvalue])
+
+            Fired when property gets reset to the (possibly dynamic) default.
+            This even may be also fired when the property is already in
+            "default" state, but the calculated default value changes.
+            Signature is variable, *oldvalue* is present only if there was an
+            old value.
+
+            :param name: Property name
+            :param oldvalue: Old value of the property
+
+        .. event:: property-pre-reset:<propname> \
+                (subject, event, name[, oldvalue])
+
+            Fired before property gets reset to the (possibly dynamic) default.
+            Signature is variable, *oldvalue* is present only if there was an
+            old value.
+
             :param name: Property name
             :param oldvalue: Old value of the property
 

+ 2 - 18
qubes/app.py

@@ -1523,20 +1523,6 @@ class Qubes(qubes.PropertyHolder):
                 'is not running ({!r}).'.format(
                     name, newvalue.name))
 
-    @qubes.events.handler('property-set:default_fw_netvm')
-    def on_property_set_default_fw_netvm(self, event, name, newvalue,
-                                         oldvalue=None):
-        # pylint: disable=unused-argument,invalid-name
-        for vm in self.domains:
-            if hasattr(vm, 'provides_network') and vm.provides_network and \
-                    hasattr(vm, 'netvm') and vm.property_is_default('netvm'):
-                # fire property-del:netvm as it is responsible for resetting
-                # netvm to it's default value
-                vm.fire_event('property-pre-del:netvm', pre_event=True,
-                              name='netvm', oldvalue=oldvalue)
-                vm.fire_event('property-del:netvm',
-                              name='netvm', oldvalue=oldvalue)
-
     @qubes.events.handler('property-set:default_netvm')
     def on_property_set_default_netvm(self, event, name, newvalue,
                                       oldvalue=None):
@@ -1544,9 +1530,7 @@ class Qubes(qubes.PropertyHolder):
         for vm in self.domains:
             if hasattr(vm, 'provides_network') and not vm.provides_network and \
                     hasattr(vm, 'netvm') and vm.property_is_default('netvm'):
-                # fire property-del:netvm as it is responsible for resetting
+                # fire property-reset:netvm as it is responsible for resetting
                 # netvm to it's default value
-                vm.fire_event('property-pre-del:netvm', pre_event=True,
-                              name='netvm', oldvalue=oldvalue)
-                vm.fire_event('property-del:netvm',
+                vm.fire_event('property-reset:netvm',
                               name='netvm', oldvalue=oldvalue)

+ 2 - 3
qubes/ext/audio.py

@@ -48,9 +48,8 @@ class AUDIO(qubes.ext.Extension):
                 self.on_property_set(vm, event, name='audiovm',
                                      newvalue=vm.audiovm)
 
-    # property-del <=> property-reset-to-default
-    @qubes.ext.handler('property-del:audiovm')
-    def on_property_del(self, subject, event, name, oldvalue=None):
+    @qubes.ext.handler('property-reset:audiovm')
+    def on_property_reset(self, subject, event, name, oldvalue=None):
         newvalue = getattr(subject, 'audiovm', None)
         self.on_property_set(subject, event, name, newvalue, oldvalue)
 

+ 6 - 2
qubes/ext/core_features.py

@@ -67,16 +67,20 @@ class CoreFeatures(qubes.ext.Extension):
     def set_servicevm_feature(self, subject):
         if getattr(subject, 'provides_network', False):
             subject.features['servicevm'] = 1
+            # icon is calculated based on this feature
+            subject.fire_event('property-reset:icon', name='icon')
         elif 'servicevm' in subject.features:
             del subject.features['servicevm']
+            # icon is calculated based on this feature
+            subject.fire_event('property-reset:icon', name='icon')
 
     @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):
+    @qubes.ext.handler('property-reset:provides_network')
+    def on_property_reset(self, subject, event, name):
         # pylint: disable=unused-argument
         self.set_servicevm_feature(subject)
 

+ 2 - 3
qubes/ext/gui.py

@@ -58,9 +58,8 @@ class GUI(qubes.ext.Extension):
             if 'guivm-' + vm.guivm.name not in vm.tags:
                 self.on_property_set(vm, event, name='guivm', newvalue=vm.guivm)
 
-    # property-del <=> property-reset-to-default
-    @qubes.ext.handler('property-del:guivm')
-    def on_property_del(self, subject, event, name, oldvalue=None):
+    @qubes.ext.handler('property-reset:guivm')
+    def on_property_reset(self, subject, event, name, oldvalue=None):
         newvalue = getattr(subject, 'guivm', None)
         self.on_property_set(subject, event, name, newvalue, oldvalue)
 

+ 2 - 2
qubes/firewall.py

@@ -329,8 +329,8 @@ class Rule(qubes.PropertyHolder):
         if newvalue not in ('icmp',):
             self.icmptype = qubes.property.DEFAULT
 
-    @qubes.events.handler('property-del:proto')
-    def on_del_proto(self, event, name, oldvalue):
+    @qubes.events.handler('property-reset:proto')
+    def on_reset_proto(self, event, name, oldvalue):
         # pylint: disable=unused-argument
         self.dstports = qubes.property.DEFAULT
         self.icmptype = qubes.property.DEFAULT

+ 8 - 0
qubes/tests/init.py

@@ -170,8 +170,12 @@ class TC_10_property(qubes.tests.QubesTestCase):
 
         self.assertEventFired(self.holder, 'property-pre-del:testprop1',
             kwargs={'name': 'testprop1', 'oldvalue': 'testvalue'})
+        self.assertEventFired(self.holder, 'property-pre-reset:testprop1',
+            kwargs={'name': 'testprop1', 'oldvalue': 'testvalue'})
         self.assertEventFired(self.holder, 'property-del:testprop1',
             kwargs={'name': 'testprop1', 'oldvalue': 'testvalue'})
+        self.assertEventFired(self.holder, 'property-reset:testprop1',
+            kwargs={'name': 'testprop1', 'oldvalue': 'testvalue'})
 
     def test_081_delete_by_assign(self):
         self.holder.testprop1 = 'testvalue'
@@ -203,8 +207,12 @@ class TC_10_property(qubes.tests.QubesTestCase):
         self.assertEqual(holder.testprop1, 'defaultvalue')
         self.assertEventFired(holder, 'property-pre-del:testprop1', kwargs={
             'name': 'testprop1', 'oldvalue': 'testvalue'})
+        self.assertEventFired(holder, 'property-pre-reset:testprop1', kwargs={
+            'name': 'testprop1', 'oldvalue': 'testvalue'})
         self.assertEventFired(holder, 'property-del:testprop1', kwargs={
             'name': 'testprop1', 'oldvalue': 'testvalue'})
+        self.assertEventFired(holder, 'property-reset:testprop1', kwargs={
+            'name': 'testprop1', 'oldvalue': 'testvalue'})
 
     def test_090_write_once_set(self):
         class MyTestHolder(qubes.tests.TestEmitter, qubes.PropertyHolder):

+ 2 - 2
qubes/vm/appvm.py

@@ -112,8 +112,8 @@ class AppVM(qubes.vm.qubesvm.QubesVM):
         '''  # pylint: disable=unused-argument
         assert self.template
 
-    @qubes.events.handler('property-pre-del:template')
-    def on_property_pre_del_template(self, event, name, oldvalue=None):
+    @qubes.events.handler('property-pre-reset:template')
+    def on_property_pre_reset_template(self, event, name, oldvalue=None):
         '''Forbid deleting template of running VM
         '''  # pylint: disable=unused-argument,no-self-use
         raise qubes.exc.QubesValueError('Cannot unset template')

+ 1 - 1
qubes/vm/dispvm.py

@@ -134,7 +134,7 @@ class DispVM(qubes.vm.qubesvm.QubesVM):
         assert self.template
 
     @qubes.events.handler('property-pre-set:template',
-        'property-pre-del:template')
+        'property-pre-reset:template')
     def on_property_pre_set_template(self, event, name, newvalue=None,
             oldvalue=None):
         ''' Disposable VM cannot have template changed '''

+ 57 - 4
qubes/vm/mix/net.py

@@ -406,8 +406,8 @@ class NetVMMixin(qubes.events.Emitter):
             '/connected-ips6',
             ' '.join(connected_ips6))
 
-    @qubes.events.handler('property-pre-del:netvm')
-    def on_property_pre_del_netvm(self, event, name, oldvalue=None):
+    @qubes.events.handler('property-pre-reset:netvm')
+    def on_property_pre_reset_netvm(self, event, name, oldvalue=None):
         ''' Sets the the NetVM to default NetVM '''
         # pylint: disable=unused-argument
         # we are changing to default netvm
@@ -419,8 +419,8 @@ class NetVMMixin(qubes.events.Emitter):
         self.fire_event('property-pre-set:netvm', pre_event=True,
             name='netvm', newvalue=newvalue, oldvalue=oldvalue)
 
-    @qubes.events.handler('property-del:netvm')
-    def on_property_del_netvm(self, event, name, oldvalue=None):
+    @qubes.events.handler('property-reset:netvm')
+    def on_property_reset_netvm(self, event, name, oldvalue=None):
         ''' Sets the the NetVM to default NetVM '''
         # pylint: disable=unused-argument
         # we are changing to default netvm
@@ -475,6 +475,59 @@ class NetVMMixin(qubes.events.Emitter):
         # pylint: disable=unused-argument
         self.reload_firewall_for_vm(vm)
 
+    @qubes.events.handler('property-set:ip', 'property-reset:ip')
+    def on_property_set_ip(self, _event, name, newvalue=None, oldvalue=None):
+        # pylint: disable=unused-argument
+        if newvalue == oldvalue:
+            return
+        if self.provides_network:
+            self.fire_event('property-reset:gateway', name='gateway')
+        self.fire_event('property-reset:visible_ip', name='visible_ip')
+        for vm in self.connected_vms:
+            vm.fire_event(
+                'property-reset:visible_gateway', name='visible_gateway')
+
+    @qubes.events.handler('property-set:ip6', 'property-reset:ipv6')
+    def on_property_set_ip6(self, _event, name, newvalue=None, oldvalue=None):
+        # pylint: disable=unused-argument
+        if newvalue == oldvalue:
+            return
+        if self.provides_network:
+            self.fire_event('property-reset:gateway6', name='gateway6')
+        self.fire_event('property-reset:visible_ip6', name='visible_ip6')
+        for vm in self.connected_vms:
+            vm.fire_event(
+                'property-reset:visible_gateway6', name='visible_gateway6')
+
+    @qubes.events.handler('feature-set:net.fake-ip')
+    def on_feature_set_net_fake_ip(self, event, name, newvalue, oldvalue=None):
+        # pylint: disable=unused-argument
+        if oldvalue == newvalue:
+            return
+        self.fire_event('property-reset:visible_ip', name='visible_ip')
+        for vm in self.connected_vms:
+            vm.fire_event(
+                'property-reset:visible_gateway', name='visible_gateway')
+
+    @qubes.events.handler('feature-set:ipv6')
+    def on_feature_set_ipv6(self, event, name, newvalue, oldvalue=None):
+        # pylint: disable=unused-argument
+        if oldvalue == newvalue:
+            return
+        self.fire_event('property-reset:visible_ip6', name='visible_ip6')
+        for vm in self.connected_vms:
+            vm.fire_event(
+                'property-reset:visible_gateway6', name='visible_gateway6')
+
+    @qubes.events.handler('property-set:provides_network')
+    def on_property_set_provides(
+            self, _event, name, newvalue, oldvalue=None):
+        # pylint: disable=unused-argument
+        if newvalue == oldvalue:
+            return
+        self.fire_event('property-reset:gateway', name='gateway')
+        self.fire_event('property-reset:gateway6', name='gateway6')
+
     @qubes.events.handler('domain-qdb-create')
     def on_domain_qdb_create(self, event):
         ''' Fills the QubesDB with firewall entries. '''

+ 10 - 2
qubes/vm/qubesvm.py

@@ -965,6 +965,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
             else:
                 shutil.copy(newvalue.icon_path, self.icon_path)
 
+        # icon is calculated based on label
+        self.fire_event('property-reset:icon', name='icon')
+
     @qubes.events.handler('property-pre-set:kernel')
     def on_property_pre_set_kernel(self, event, name, newvalue, oldvalue=None):
         # pylint: disable=unused-argument
@@ -1006,8 +1009,8 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
             raise qubes.exc.QubesException(
                 'Failed to set autostart for VM in systemd')
 
-    @qubes.events.handler('property-pre-del:autostart')
-    def on_property_pre_del_autostart(self, event, name, oldvalue=None):
+    @qubes.events.handler('property-pre-reset:autostart')
+    def on_property_pre_reset_autostart(self, event, name, oldvalue=None):
         # pylint: disable=unused-argument
         if oldvalue:
             retcode = subprocess.call(
@@ -1142,6 +1145,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
                 self.libvirt_domain.createWithFlags(
                     libvirt.VIR_DOMAIN_START_PAUSED)
 
+                # the above allocates xid, lets announce that
+                self.fire_event('property-reset:xid', name='xid')
+                self.fire_event('property-reset:start_time', name='start_time')
             except libvirt.libvirtError as exc:
                 # missing IOMMU?
                 if self.virt_mode == 'hvm' and \
@@ -1250,6 +1256,8 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
         except qubes.storage.StoragePoolException:
             self.log.exception('Failed to stop storage for domain %s',
                                self.name)
+        self.fire_event('property-reset:xid', name='xid')
+        self.fire_event('property-reset:start_time', name='start_time')
 
     @asyncio.coroutine
     def shutdown(self, force=False, wait=False, timeout=None):

+ 24 - 0
qubes/vm/templatevm.py

@@ -85,3 +85,27 @@ class TemplateVM(QubesVM):
             }
         }
         super(TemplateVM, self).__init__(*args, **kwargs)
+
+    @qubes.events.handler('property-set:default_user',
+                          'property-set:kernel',
+                          'property-set:kernelopts',
+                          'property-set:vcpus',
+                          'property-set:memory',
+                          'property-set:maxmem',
+                          'property-set:qrexec_timeout',
+                          'property-set:shutdown_timeout',
+                          'property-set:management_dispvm')
+    def on_property_set_child(self, _event, name, newvalue, oldvalue=None):
+        """Send event about default value change to child VMs
+           (which use default inherited from the template).
+
+           This handler is supposed to be set for properties using
+           `_default_with_template()` function for the default value.
+           """
+        if newvalue == oldvalue:
+            return
+
+        for vm in self.appvms:
+            if not vm.property_is_default(name):
+                continue
+            vm.fire_event('property-reset:' + name, name=name)