blob: 2be6079f9813f75cd8aae45fd06f96b975cabf7e [file] [log] [blame]
Adam Tengler82074b02018-08-10 15:58:06 +00001from itertools import chain
Alexandr Lovtsov42037e92019-02-22 18:49:50 +03002
3try:
4 from netaddr import iter_iprange, IPAddress, IPNetwork
5 HAS_NETADDR = True
6except ImportError:
7 HAS_NETADDR = False
Adam Tenglera2f260a2018-07-12 17:35:28 +00008
9__virtualname__ = 'netutils'
10
11
12def __virtual__():
Alexandr Lovtsov42037e92019-02-22 18:49:50 +030013 if not HAS_NETADDR:
14 return False, "'netaddr' python library is unavailable"
Adam Tenglera2f260a2018-07-12 17:35:28 +000015 return __virtualname__
16
17
Adam Tengler82074b02018-08-10 15:58:06 +000018def parse_ip_ranges(ranges, needed):
Adam Tenglera2f260a2018-07-12 17:35:28 +000019 '''
20 Takes comma seprated list of IP ranges and returns full list of IP addresses in these ranges.
21 Second argument is used to check if there is enough IP addresses to cover the required number of nodes.
22
Adam Tengler82074b02018-08-10 15:58:06 +000023 >>> parse_ip_ranges("192.168.1.101-192.168.1.103,192.168.2.101-192.168.2.103")
Adam Tenglera2f260a2018-07-12 17:35:28 +000024 ["192.168.1.101", "192.168.1.102", "192.168.1.103", "192.168.2.101", "192.168.2.102", "192.168.2.103"]
25 '''
26 range_list = ranges.split(',')
27 ip_obj_list = []
28 for _range in ranges.split(','):
29 ip_obj_list += list(iter_iprange(*_range.split('-')))
30 ip_list = [str(ip) for ip in ip_obj_list]
31 if len(ip_list) < needed:
32 raise ValueError('There is not enough IP addresses in ranges: "{}". {} available, {} required.'.format(ranges, len(ip_list), needed))
33 return ip_list
Adam Tengler82074b02018-08-10 15:58:06 +000034
35
36def parse_network_ranges(ranges, iterate=False):
37 '''
38 Takes comma separated list of network ranges and returns full list of first IP addresses in every given subnet.
39 Second argument is used to check if there is enough IP addresses to cover the required number of nodes.
40
41 >>> parse_network_ranges("10.10.0.1/24-10.10.10.1/24,192.168.0.1/24-192.168.10.1/24")
42 ['10.10.0.1', '10.10.1.1', '10.10.2.1', '10.10.3.1', '10.10.4.1', '10.10.5.1', '10.10.6.1', '10.10.7.1', '10.10.8.1', '10.10.9.1', '10.10.10.1', '192.168.0.1', '192.168.1.1', '192.168.2.1', '192.168.3.1', '192.168.4.1', '192.168.5.1', '192.168.6.1', '192.168.7.1', '192.168.8.1', '192.168.9.1', '192.168.10.1']
43 '''
44 def _iter_subnet_list(start, end):
45 yield str(IPAddress(start.first) + 1)
46 if start != end:
47 for ip in _iter_subnet_list(start.next(), end):
48 yield ip
49
50 generators = tuple()
51
52 for _range in ranges.split(','):
53 start_str, end_str = _range.split('-')
54 start, end = IPNetwork(start_str), IPNetwork(end_str)
55 if start > end:
56 raise ValueError('Invalid network range, start address is higher than end address')
57 generators += (_iter_subnet_list(start, end),)
58
59 if iterate:
60 return [ip for ip in chain(*generators)]
61 return chain(*generators)