automatically assign unused subnet address
authorsmbaker <smbaker@fc8-storktest.lan>
Thu, 25 Jul 2013 14:13:38 +0000 (07:13 -0700)
committersmbaker <smbaker@fc8-storktest.lan>
Thu, 25 Jul 2013 14:13:38 +0000 (07:13 -0700)
planetstack/core/models/network.py

index c55bae6..be13ea7 100644 (file)
@@ -1,4 +1,5 @@
 import os
+import socket
 from django.db import models
 from core.models import PlCoreBase, Site, Slice, Sliver
 from django.contrib.contenttypes.models import ContentType
@@ -6,6 +7,19 @@ from django.contrib.contenttypes import generic
 
 # Create your models here.
 
+SUBNET_BASE = "10.0.0.0"
+SUBNET_NODE_BITS = 12     # enough for 4096 bits per subnet
+SUBNET_SUBNET_BITS = 12   # enough for 4096 private networks
+
+def find_unused_subnet(base, subnet_bits, node_bits, existing_subnets):
+    i=0
+    while True:
+        subnet_i = (i<<node_bits) | int(socket.inet_aton(base).encode('hex'),16)
+        subnet = socket.inet_ntoa(hex(subnet_i)[2:].zfill(8).decode('hex')) + "/" + str(32-node_bits)
+        if (subnet not in existing_subnets):
+            return subnet
+        i=i+1
+
 class NetworkTemplate(PlCoreBase):
     VISIBILITY_CHOICES = (('public', 'public'), ('private', 'private'))
 
@@ -18,7 +32,7 @@ class NetworkTemplate(PlCoreBase):
 class Network(PlCoreBase):
     name = models.CharField(max_length=32)
     template = models.ForeignKey(NetworkTemplate)
-    subnet = models.CharField(max_length=32)
+    subnet = models.CharField(max_length=32, blank=True, null=True)
     ports = models.CharField(max_length=1024)
     labels = models.CharField(max_length=1024)
     slice = models.ForeignKey(Slice, related_name="networks")
@@ -29,6 +43,15 @@ class Network(PlCoreBase):
 
     def __unicode__(self):  return u'%s' % (self.name)
 
+    def allocateSubnet(self):
+        existingSubnets = [x.subnet for x in Network.objects.all()]
+        return find_unused_subnet(SUBNET_BASE, SUBNET_SUBNET_BITS, SUBNET_NODE_BITS, existingSubnets)
+
+    def save(self, *args, **kwds):
+        if not self.subnet:
+            self.subnet = self.allocateSubnet()
+        super(Network, self).save(*args, **kwds)
+
 class NetworkSliver(PlCoreBase):
     network = models.ForeignKey(Network)
     sliver = models.ForeignKey(Sliver)