Browse Source

Optimisation of the check for intersecting subnets

Baptiste Jonglez 11 years ago
parent
commit
469accfea9
1 changed files with 5 additions and 6 deletions
  1. 5 6
      coin/resources/models.py

+ 5 - 6
coin/resources/models.py

@@ -2,6 +2,7 @@
 from django.db import models
 from django.core.exceptions import ValidationError
 from django.core.validators import MaxValueValidator
+from django.db.models import Q
 from netfields import CidrAddressField, NetManager
 from netaddr import IPNetwork, IPSet
 
@@ -73,12 +74,10 @@ class IPSubnet(models.Model):
             if not self.inet in self.ip_pool.inet:
                 raise ValidationError('Subnet must be included in the IP pool.')
             # Check that we don't conflict with existing subnets.
-            # TODO: use precise database query instead of querying all
-            # subnets and filtering in Python.
-            existing = IPSet((s.inet for s in self.ip_pool.ipsubnet_set.all()))
-            intersection = IPSet([self.inet]).intersection(existing)
-            if intersection.size:
-                raise ValidationError('Subnet must not intersect with existing subnets.\nIntersected subnets: {}.'.format([str(p) for p in intersection.iter_cidrs()]))
+            conflicting = self.ip_pool.ipsubnet_set.filter(Q(inet__net_contained_or_equal=self.inet) |
+                                                           Q(inet__net_contains_or_equals=self.inet)).exclude(id=self.id)
+            if conflicting:
+                raise ValidationError('Subnet must not intersect with existing subnets.\nIntersected subnets: {}.'.format(conflicting))
 
     def __unicode__(self):
         return str(self.inet)