SUBNET_NODE_BITS = 12 # enough for 4096 bits per subnet
SUBNET_SUBNET_BITS = 12 # enough for 4096 private networks
+def ip_to_int(ip):
+ return int(socket.inet_aton(ip).encode('hex'),16)
+
+def int_to_ip(i):
+ return socket.inet_ntoa(hex(i)[2:].zfill(8).decode('hex'))
+
def find_unused_subnet(base, subnet_bits, node_bits, existing_subnets):
- # start at the first allocatable subnet
+ # enumerate possible subnets until we find one that isn't used
i=1
while True:
- subnet_i = int(socket.inet_aton(base).encode('hex'),16) | (i<<node_bits)
- subnet = socket.inet_ntoa(hex(subnet_i)[2:].zfill(8).decode('hex')) + "/" + str(32-node_bits)
+ subnet_i = ip_to_int(base) | (i<<node_bits)
+ subnet = int_to_ip(subnet_i) + "/" + str(32-node_bits)
if (subnet not in existing_subnets):
return subnet
i=i+1
# TODO: we could run out...
+def find_unused_address(subnet, existingAddresses):
+ # enumerate possible addresses until we find one that isn't used
+ (network, bits) = subnet.split("/")
+ network_i = ip_to_int(network)
+ max_addr = 1<<(32-int(bits))
+ i = 1
+ while True:
+ if i>=max_addr:
+ raise ValueError("No more ips available")
+ ip = int_to_ip(network_i | i)
+ if not (ip in existingAddresses):
+ return ip
+ i=i+1
+
class NetworkTemplate(PlCoreBase):
VISIBILITY_CHOICES = (('public', 'public'), ('private', 'private'))
guaranteedBandwidth = models.IntegerField(default=0)
permittedSlices = models.ManyToManyField(Slice, blank=True, related_name="permittedNetworks")
- boundSlivers = models.ManyToManyField(Sliver, blank=True, related_name="boundNetworks", through="NetworkSliver")
+ slivers = models.ManyToManyField(Sliver, blank=True, related_name="boundNetworks", through="NetworkSliver")
def __unicode__(self): return u'%s' % (self.name)
existingSubnets = [x.subnet for x in Network.objects.all()]
return find_unused_subnet(SUBNET_BASE, SUBNET_SUBNET_BITS, SUBNET_NODE_BITS, existingSubnets)
+ def allocateAddress(self):
+ existingAddresses = [x.ip for x in self.networksliver_set.all()]
+ return find_unused_address(self.subnet, existingAddresses)
+
def save(self, *args, **kwds):
if not self.subnet:
self.subnet = self.allocateSubnet()
sliver = models.ForeignKey(Sliver)
ip = models.GenericIPAddressField(help_text="Sliver ip address", blank=True, null=True)
+ def save(self, *args, **kwds):
+ if not self.ip:
+ self.ip = self.network.allocateAddress()
+ super(NetworkSliver, self).save(*args, **kwds)
+
def __unicode__(self): return u'foo!'
class Router(PlCoreBase):