|
@@ -1,4 +1,5 @@
|
|
|
from django.db import models
|
|
|
+from django.core.exceptions import ValidationError
|
|
|
from netfields import InetAddressField, NetManager
|
|
|
from netaddr import IPAddress
|
|
|
|
|
@@ -24,11 +25,30 @@ class VPNSubscription(models.Model):
|
|
|
objects = NetManager()
|
|
|
|
|
|
def clean(self):
|
|
|
+ # TODO: this should be factored for other technologies (DSL, etc)
|
|
|
subnets = self.administrative_subscription.ip_subnet.all()
|
|
|
+ # If saving for the first time and IP endpoints are not specified,
|
|
|
+ # generate them automatically.
|
|
|
+ if self.pk is None:
|
|
|
+ subnets_v4 = [s for s in subnets if s.inet.version == 4]
|
|
|
+ subnets_v6 = [s for s in subnets if s.inet.version == 6]
|
|
|
+ if self.ipv4_endpoint is None:
|
|
|
+ if len(subnets_v4) == 0:
|
|
|
+ # TODO: should we fail silently instead?
|
|
|
+ raise ValidationError('No IPv4 subnet defined, needed to choose an endpoint from')
|
|
|
+ self.ipv4_endpoint = subnets_v4[0].inet.ip
|
|
|
+ if self.ipv6_endpoint is None:
|
|
|
+ if len(subnets_v6) == 0:
|
|
|
+ # TODO: should we fail silently instead?
|
|
|
+ raise ValidationError('No IPv6 subnet defined, needed to choose an endpoint from')
|
|
|
+ # With v6, we choose the second host of the subnet (cafe::1)
|
|
|
+ gen = subnets_v6[0].inet.iter_hosts()
|
|
|
+ gen.next()
|
|
|
+ self.ipv6_endpoint = gen.next()
|
|
|
# Check that the endpoints are included in one of the routed subnets
|
|
|
for endpoint in [self.ipv4_endpoint, self.ipv6_endpoint]:
|
|
|
if endpoint:
|
|
|
- if not any([endpoint in subnet for subnet in subnets]):
|
|
|
+ if not any([endpoint in subnet.inet for subnet in subnets]):
|
|
|
raise ValidationError("Endpoint {} is not in an attributed range".format(endpoint))
|
|
|
|
|
|
def __unicode__(self):
|