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 os
+import socket
 from django.db import models
 from core.models import PlCoreBase, Site, Slice, Sliver
 from django.contrib.contenttypes.models import ContentType
 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.
 
 
 # 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'))
 
 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)
 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")
     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 __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)
 class NetworkSliver(PlCoreBase):
     network = models.ForeignKey(Network)
     sliver = models.ForeignKey(Sliver)