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