1
1
from ipaddr import IPNetwork
2
+ from optparse import make_option
2
3
3
4
from django .core .management .base import BaseCommand , CommandError
4
- from portal .models import Subnet
5
+ from portal .models import IPAddress , Subnet
5
6
6
7
7
8
prefixlenq = Subnet .objects .extra (select = {'masklen' : "masklen(network)" }
@@ -12,10 +13,14 @@ def get_next_network(address, prefixlen):
12
13
return IPNetwork ("/" .join (map (str , [address , prefixlen ])))
13
14
14
15
15
- def find_free_network (existing_networks , start , prefixlen ):
16
+ def find_free_network (existing_networks , start , prefixlen , ignore_hosts = False ):
16
17
new_network = get_next_network (start , prefixlen )
17
18
for net in existing_networks :
18
- if new_network in net or net in new_network :
19
+ if any ([
20
+ new_network in net ,
21
+ net in new_network ,
22
+ not ignore_hosts and IPAddress .objects .extra (where = ["ip <<= inet '%s'" % new_network ]),
23
+ ]):
19
24
return find_free_network (existing_networks ,
20
25
max (new_network ) + 1 ,
21
26
prefixlen )
@@ -28,6 +33,14 @@ class Command(BaseCommand):
28
33
'\n Suggested block names:\n ' + \
29
34
'\n ' .join (prefixlenq .values_list ('notes' , flat = True )[:10 ]) + \
30
35
'\n Block names use case-insensitive starts-with matching.'
36
+ option_list = BaseCommand .option_list + (
37
+ make_option (
38
+ '--ignore-hosts' ,
39
+ action = 'store_true' ,
40
+ dest = 'ignore_hosts' ,
41
+ default = False ,
42
+ help = 'Skips checking for any hosts in the new subnet' ),
43
+ )
31
44
32
45
def handle (self , * args , ** options ):
33
46
blockname , prefixlen = args
@@ -40,7 +53,8 @@ def handle(self, *args, **options):
40
53
[n .network for n in Subnet .objects .extra (
41
54
where = ["inet '%s' >> network" % block ])],
42
55
min (block ),
43
- prefixlen )
56
+ prefixlen ,
57
+ options .get ("ignore_hosts" ))
44
58
if found not in block :
45
59
raise CommandError (
46
60
"No /%ss available in %s" % (prefixlen , str (block )))
0 commit comments