Revision 4445f97a snf-cyclades-app/synnefo/api/subnets.py
b/snf-cyclades-app/synnefo/api/subnets.py | ||
---|---|---|
40 | 40 |
from django.utils import simplejson as json |
41 | 41 |
|
42 | 42 |
from snf_django.lib.api import utils |
43 |
from synnefo.db.models import Subnet, Network |
|
43 |
from synnefo.db.models import Subnet, Network, IPPoolTable
|
|
44 | 44 |
from synnefo.logic import networks |
45 | 45 |
|
46 | 46 |
from ipaddr import IPv4Network, IPv6Network, IPv4Address, IPAddress, IPNetwork |
... | ... | |
148 | 148 |
|
149 | 149 |
allocation_pools = subnet.get('allocation_pools', None) |
150 | 150 |
|
151 |
if allocation_pools: |
|
151 |
# FIX ME |
|
152 |
sub = Subnet.objects.create(name=name, network=network, cidr=cidr, |
|
153 |
ipversion=ipversion, gateway=gateway, |
|
154 |
dhcp=dhcp, host_routes=hosts, |
|
155 |
dns_nameservers=dns) |
|
156 |
|
|
157 |
pool_list = list() |
|
158 |
if allocation_pools is not None: |
|
159 |
# If the user specified IP allocation pools, validate them and use them |
|
152 | 160 |
if ipversion == 6: |
153 | 161 |
raise api.faults.Conflict("Can't allocate an IP Pool in IPv6") |
154 | 162 |
pools = parse_ip_pools(allocation_pools) |
155 |
validate_subpools(pools, cidr_ip, gateway_ip) |
|
156 |
else: |
|
157 |
# FIX ME |
|
158 |
pass |
|
163 |
pool_list = string_to_ipaddr(pools) |
|
164 |
validate_subpools(pool_list, cidr_ip, gateway_ip) |
|
165 |
if allocation_pools is None and ipversion == 4: |
|
166 |
# Check if the gateway is the first IP of the subnet, in this case |
|
167 |
# create a single ip pool |
|
168 |
if int(gateway_ip) - int(cidr_ip) == 1: |
|
169 |
pool_list = [[gateway_ip + 1, cidr_ip.broadcast - 1]] |
|
170 |
else: |
|
171 |
# If the gateway isn't the first available ip, create two different |
|
172 |
# ip pools adjacent to said ip |
|
173 |
pool_list.append([cidr_ip.network + 1, gateway_ip - 1]) |
|
174 |
pool_list.append([gateway_ip + 1, cidr_ip.broadcast - 1]) |
|
159 | 175 |
|
160 |
# FIX ME |
|
161 |
try: |
|
162 |
sub = Subnet.objects.create(name=name, network=network, cidr=cidr, |
|
163 |
ipversion=ipversion, gateway=gateway, |
|
164 |
dhcp=dhcp, host_routes=hosts, |
|
165 |
dns_nameservers=dns) |
|
166 |
except: |
|
167 |
raise |
|
168 |
return "Error" |
|
176 |
if pool_list: |
|
177 |
create_ip_pools(pool_list, cidr_ip, sub) |
|
169 | 178 |
|
170 | 179 |
subnet_dict = subnet_to_dict(sub) |
171 | 180 |
data = json.dumps({'subnet': subnet_dict}) |
... | ... | |
246 | 255 |
"""Returns a dictionary containing the info of a subnet""" |
247 | 256 |
dns = check_empty_lists(subnet.dns_nameservers) |
248 | 257 |
hosts = check_empty_lists(subnet.host_routes) |
249 |
#allocation_pools = |
|
258 |
allocation_pools = subnet.ip_pools.all() |
|
259 |
pools = list() |
|
260 |
|
|
261 |
if allocation_pools: |
|
262 |
for pool in allocation_pools: |
|
263 |
cidr = IPNetwork(pool.base) |
|
264 |
start = str(cidr.network + pool.offset) |
|
265 |
end = str(cidr.network + pool.offset + pool.size - 1) |
|
266 |
pools.append([{"start": start, "end": end}]) |
|
250 | 267 |
|
251 | 268 |
dictionary = dict({'id': str(subnet.id), |
252 | 269 |
'network_id': str(subnet.network.id), |
... | ... | |
259 | 276 |
'enable_dhcp': subnet.dhcp, |
260 | 277 |
'dns_nameservers': dns, |
261 | 278 |
'host_routes': hosts, |
262 |
'allocation_pools': []}) |
|
279 |
'allocation_pools': pools if pools is not None else []})
|
|
263 | 280 |
|
264 | 281 |
if subnet.ipversion == 6: |
265 | 282 |
dictionary['slac'] = subnet.dhcp |
... | ... | |
267 | 284 |
return dictionary |
268 | 285 |
|
269 | 286 |
|
287 |
def string_to_ipaddr(pools): |
|
288 |
""" |
|
289 |
Convert [["192.168.42.1", "192.168.42.15"], |
|
290 |
["192.168.42.30", "192.168.42.60"]] |
|
291 |
to |
|
292 |
[[IPv4Address('192.168.42.1'), IPv4Address('192.168.42.15')], |
|
293 |
[IPv4Address('192.168.42.30'), IPv4Address('192.168.42.60')]] |
|
294 |
and sort the output |
|
295 |
""" |
|
296 |
pool_list = [(map(lambda ip_str: IPAddress(ip_str), pool)) |
|
297 |
for pool in pools] |
|
298 |
pool_list.sort() |
|
299 |
return pool_list |
|
300 |
|
|
301 |
|
|
302 |
def create_ip_pools(pools, cidr, subnet): |
|
303 |
"""Placeholder""" |
|
304 |
for pool in pools: |
|
305 |
size = int(pool[1]) - int(pool[0]) + 1 |
|
306 |
base = str(cidr) |
|
307 |
offset = int(pool[0]) - int(cidr.network) |
|
308 |
ip_pool = IPPoolTable.objects.create(size=size, offset=offset, |
|
309 |
base=base, subnet=subnet) |
|
310 |
|
|
311 |
|
|
270 | 312 |
def check_empty_lists(value): |
271 | 313 |
"""Check if value is Null/None, in which case we return an empty list""" |
272 | 314 |
if value is None: |
... | ... | |
338 | 380 |
return pool_list |
339 | 381 |
|
340 | 382 |
|
341 |
def validate_subpools(pools, cidr, gateway):
|
|
383 |
def validate_subpools(pool_list, cidr, gateway):
|
|
342 | 384 |
""" |
343 | 385 |
Validate the given IP pools are inside the cidr range |
344 | 386 |
Validate there are no overlaps in the given pools |
345 | 387 |
Finally, validate the gateway isn't in the given ip pools |
346 |
Input must be a list containing a sublist with start/end ranges as strings |
|
347 |
[["192.168.42.1", "192.168.42.15"], ["192.168.42.30", "192.168.42.60"]] |
|
388 |
Input must be a list containing a sublist with start/end ranges as |
|
389 |
ipaddr.IPAddress items eg., |
|
390 |
[[IPv4Address('192.168.42.11'), IPv4Address('192.168.42.15')], |
|
391 |
[IPv4Address('192.168.42.30'), IPv4Address('192.168.42.60')]] |
|
348 | 392 |
""" |
349 |
pool_list = [(map(lambda ip_str: IPAddress(ip_str), pool)) |
|
350 |
for pool in pools] |
|
351 |
pool_list.sort() |
|
352 |
|
|
353 | 393 |
if pool_list[0][0] <= cidr.network: |
354 | 394 |
raise api.faults.Conflict("IP Pool out of bounds") |
355 | 395 |
elif pool_list[-1][1] >= cidr.broadcast: |
Also available in: Unified diff