Browse Source

Signal the configuration backend when a subnet changes

Baptiste Jonglez 11 years ago
parent
commit
57fd765bc0
2 changed files with 46 additions and 0 deletions
  1. 39 0
      coin/offers/models.py
  2. 7 0
      coin/vpn/models.py

+ 39 - 0
coin/offers/models.py

@@ -1,6 +1,11 @@
 # -*- coding: utf-8 -*-
 import datetime
+
 from django.db import models
+from django.db.models.signals import post_save, post_delete
+from django.dispatch import receiver
+
+from coin.resources.models import IPSubnet
 
 
 class Offer(models.Model):
@@ -103,3 +108,37 @@ class OfferSubscription(models.Model):
 
     class Meta:
         verbose_name = 'abonnement'
+
+
+@receiver(post_save, sender=IPSubnet)
+def subnet_save_event(sender, **kwargs):
+    """Fires when a subnet is saved (created/modified).  We tell the
+    configuration backend to do whatever it needs to do with it.
+
+    We should use a pre_save signal, so that if anything goes wrong in the
+    backend (exception raised), nothing is actually saved in the database.
+    But it has a big problem: the configuration backend will not see the
+    change, since it has not been saved into the database yet.
+
+    That's why we use a post_save signal instead.  But surprisingly, all
+    is well: if we raise an exception here, the IPSubnet object will not
+    be saved in the database.  But the backend *does* see the new state of
+    the database.  It looks like the database rollbacks if an exception is
+    raised.  Whatever the reason, this is not a documented feature of
+    Django signals.
+    """
+    subnet = kwargs['instance']
+    config = subnet.offer_subscription.configuration
+    if config:
+        config.save_subnet(subnet, kwargs['created'])
+
+
+@receiver(post_delete, sender=IPSubnet)
+def subnet_delete_event(sender, **kwargs):
+    """Fires when a subnet is deleted.  We tell the configuration backend to
+    do whatever it needs to do with it.
+    """
+    subnet = kwargs['instance']
+    config = subnet.offer_subscription.configuration
+    if config:
+        config.delete_subnet(subnet)

+ 7 - 0
coin/vpn/models.py

@@ -29,6 +29,13 @@ class VPNSubscription(CoinLdapSyncModel):
 
     objects = NetManager()
 
+    # These two methods are part of the general configuration interface.
+    def save_subnet(self, subnet, creation):
+        self.sync_to_ldap(False)
+
+    def delete_subnet(self, subnet):
+        self.sync_to_ldap(False)
+
     def get_subnets(self, version):
         subnets = self.administrative_subscription.ip_subnet.all()
         return [subnet for subnet in subnets if subnet.inet.version == version]