automatically assign unused subnet address
[plstackapi.git] / planetstack / core / models / network.py
1 import os
2 import socket
3 from django.db import models
4 from core.models import PlCoreBase, Site, Slice, Sliver
5 from django.contrib.contenttypes.models import ContentType
6 from django.contrib.contenttypes import generic
7
8 # Create your models here.
9
10 SUBNET_BASE = "10.0.0.0"
11 SUBNET_NODE_BITS = 12     # enough for 4096 bits per subnet
12 SUBNET_SUBNET_BITS = 12   # enough for 4096 private networks
13
14 def find_unused_subnet(base, subnet_bits, node_bits, existing_subnets):
15     i=0
16     while True:
17         subnet_i = (i<<node_bits) | int(socket.inet_aton(base).encode('hex'),16)
18         subnet = socket.inet_ntoa(hex(subnet_i)[2:].zfill(8).decode('hex')) + "/" + str(32-node_bits)
19         if (subnet not in existing_subnets):
20             return subnet
21         i=i+1
22
23 class NetworkTemplate(PlCoreBase):
24     VISIBILITY_CHOICES = (('public', 'public'), ('private', 'private'))
25
26     name = models.CharField(max_length=32)
27     guaranteedBandwidth = models.IntegerField(default=0)
28     visibility = models.CharField(max_length=30, choices=VISIBILITY_CHOICES, default="private")
29
30     def __unicode__(self):  return u'%s' % (self.name)
31
32 class Network(PlCoreBase):
33     name = models.CharField(max_length=32)
34     template = models.ForeignKey(NetworkTemplate)
35     subnet = models.CharField(max_length=32, blank=True, null=True)
36     ports = models.CharField(max_length=1024)
37     labels = models.CharField(max_length=1024)
38     slice = models.ForeignKey(Slice, related_name="networks")
39
40     guaranteedBandwidth = models.IntegerField(default=0)
41     permittedSlices = models.ManyToManyField(Slice, blank=True, related_name="permittedNetworks")
42     boundSlivers = models.ManyToManyField(Sliver, blank=True, related_name="boundNetworks", through="NetworkSliver")
43
44     def __unicode__(self):  return u'%s' % (self.name)
45
46     def allocateSubnet(self):
47         existingSubnets = [x.subnet for x in Network.objects.all()]
48         return find_unused_subnet(SUBNET_BASE, SUBNET_SUBNET_BITS, SUBNET_NODE_BITS, existingSubnets)
49
50     def save(self, *args, **kwds):
51         if not self.subnet:
52             self.subnet = self.allocateSubnet()
53         super(Network, self).save(*args, **kwds)
54
55 class NetworkSliver(PlCoreBase):
56     network = models.ForeignKey(Network)
57     sliver = models.ForeignKey(Sliver)
58     ip = models.GenericIPAddressField(help_text="Sliver ip address", blank=True, null=True)
59
60     def __unicode__(self):  return u'foo!'
61
62 class Router(PlCoreBase):
63     name = models.CharField(max_length=32)
64     owner = models.ForeignKey(Slice, related_name="routers")
65     networks = models.ManyToManyField(Network, blank=True, related_name="routers")
66
67     def __unicode__(self):  return u'%s' % (self.name)
68
69 class NetworkParameterType(PlCoreBase):
70     name = models.SlugField(help_text="The name of this tag", max_length=128)
71
72     def __unicode__(self):  return u'%s' % (self.name)
73
74 class NetworkParameter(PlCoreBase):
75     networkParameterType = models.ForeignKey(NetworkParameterType, related_name="parameters", help_text="The name of the parameter")
76     value = models.CharField(help_text="The value of this parameter", max_length=1024)
77
78     # The required fields to do a ObjectType lookup, and object_id assignment
79     content_type = models.ForeignKey(ContentType)
80     object_id = models.PositiveIntegerField()
81     content_object = generic.GenericForeignKey('content_type', 'object_id')
82
83     def __unicode__(self):
84         return self.networkParameterType.name
85
86