1 ##############################################################################
2 # Copyright (c) 2018 OPNFV and others.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9 """Library for generate_config functions and custom jinja2 filters"""
12 from ipaddress import IPv4Network, IPv4Address
15 def load_custom_filters(environment):
16 """Load all defined filters into the jinja2 enviroment"""
18 # TODO deprecate ipaddr_index and netmask for the better ipnet ones
20 'dpkg_arch': filter_dpkg_arch,
21 'storage_size_num': filter_storage_size_num,
22 'ipnet_hostaddr': filter_ipnet_hostaddr,
23 'ipnet_hostmin': filter_ipnet_hostmin,
24 'ipnet_hostmax': filter_ipnet_hostmax,
25 'ipnet_broadcast': filter_ipnet_broadcast,
26 'ipnet_netmask': filter_ipnet_netmask,
27 'ipnet_contains_ip': filter_ipnet_contains_ip,
28 'ipnet_contains_iprange': filter_ipnet_contains_iprange,
29 'ipnet_range_size': filter_ipnet_range_size,
30 'ipaddr_index': filter_ipaddr_index,
31 'netmask': filter_netmask
34 for name, function in filter_list.items():
35 environment.filters[name] = function
38 def filter_dpkg_arch(arch, to_dpkg=True):
39 """Convert DPKG-compatible from processor arch and vice-versa"""
41 # Processor architecture (as reported by $(uname -m))
42 # vs DPKG architecture mapping
47 arch_dpkg_table = dict(
48 zip(dpkg_arch_table.values(), dpkg_arch_table.keys()))
51 return dpkg_arch_table[arch]
53 return arch_dpkg_table[arch]
56 def filter_storage_size_num(size_str):
57 """Convert human-readable size string to a string convertible to float"""
59 # pattern: '^[1-9][\d\.]*[MGT]B?$', multiplier=1000 (not KiB)
60 if size_str.endswith('B'):
61 size_str = size_str[:-1]
64 for multiplier in ['M', 'G', 'T']:
65 if size_str.endswith(multiplier):
66 return '{:.2f}'.format(size_num * float(size_str[:-1]))
67 size_num = size_num * 1000
68 return '{:.2f}'.format(float(size_str))
69 except ValueError as ex:
70 logging.error(size_str + " is not a valid size string")
74 def filter_ipnet_hostaddr(network_cidr, index):
75 """Return the host IP address on given index from an IP network"""
77 network_cidr_str = unicode(network_cidr)
78 except NameError as ex:
79 network_cidr_str = str(network_cidr)
81 return IPv4Network(network_cidr_str)[index]
82 except ValueError as ex:
83 logging.error(network_cidr_str + " is not a valid network address")
85 except IndexError as ex:
86 logging.error(network_cidr_str + " has not enough range for "
87 + str(index) + " host IPs.")
91 def filter_ipnet_broadcast(network_cidr):
92 """Return broadcast IP address from given IP network"""
94 network_cidr_str = unicode(network_cidr)
95 except NameError as ex:
96 network_cidr_str = str(network_cidr)
98 return IPv4Network(network_cidr_str).broadcast_address
99 except ValueError as ex:
100 logging.error(network_cidr_str + " is not a valid network address")
104 def filter_ipnet_hostmin(network_cidr):
105 """Return the first host IP address from given IP network"""
107 network_cidr_str = unicode(network_cidr)
108 except NameError as ex:
109 network_cidr_str = str(network_cidr)
111 return IPv4Network(network_cidr_str)[1]
112 except ValueError as ex:
113 logging.error(network_cidr_str + " is not a valid network address")
117 def filter_ipnet_hostmax(network_cidr):
118 """Return the last host IP address from given IP network"""
120 network_cidr_str = unicode(network_cidr)
121 except NameError as ex:
122 network_cidr_str = str(network_cidr)
124 return IPv4Network(network_cidr_str)[-2]
125 except ValueError as ex:
126 logging.error(network_cidr_str + " is not a valid network address")
130 def filter_ipnet_netmask(network_cidr):
131 """Return the IP netmask from given IP network"""
133 network_cidr_str = unicode(network_cidr)
134 except NameError as ex:
135 network_cidr_str = str(network_cidr)
137 return IPv4Network(network_cidr_str).netmask
138 except ValueError as ex:
139 logging.error(network_cidr_str + " is not a valid network address")
143 def filter_ipnet_contains_ip(network_cidr, ip_address):
144 """Check if an IP network cointains a given range"""
146 network_cidr_str = unicode(network_cidr)
147 ip_address_str = unicode(ip_address)
148 except NameError as ex:
149 network_cidr_str = str(network_cidr)
150 ip_address_str = str(ip_address)
152 return IPv4Address(ip_address_str) in IPv4Network(network_cidr_str)
153 except ValueError as ex:
154 logging.error(network_cidr_str + " is not a valid network address")
158 def filter_ipnet_contains_iprange(network_cidr, range_start, range_end):
159 """Check if an IP network cointains a given range"""
161 network_cidr_str = unicode(network_cidr)
162 range_start_str = unicode(range_start)
163 range_end_str = unicode(range_end)
164 except NameError as ex:
165 network_cidr_str = str(network_cidr)
166 range_start_str = str(range_start)
167 range_end_str = str(range_end)
169 ipnet = IPv4Network(network_cidr_str)
170 return (IPv4Address(range_start_str) in ipnet
171 and IPv4Address(range_end_str) in ipnet)
172 except ValueError as ex:
173 logging.error(network_cidr_str + " is not a valid network address")
177 def filter_ipnet_range_size(network_cidr, range_start, range_end):
178 """Get the size of an IP range between two IP addresses"""
180 network_cidr_str = unicode(network_cidr)
181 range_start_str = unicode(range_start)
182 range_end_str = unicode(range_end)
183 except NameError as ex:
184 network_cidr_str = str(network_cidr)
185 range_start_str = str(range_start)
186 range_end_str = str(range_end)
188 ipnet = IPv4Network(network_cidr_str)
189 ip1 = IPv4Address(range_start_str)
190 ip2 = IPv4Address(range_end_str)
192 if ip1 in ipnet and ip2 in ipnet:
193 index1 = list(ipnet.hosts()).index(ip1)
194 index2 = list(ipnet.hosts()).index(ip2)
195 ip_range_size = index2 - index1 + 1
199 except ValueError as ex:
200 logging.error(range_start_str + " and " + range_end_str +
201 " are not valid IP addresses for range inside " +
206 # This filter is too simple and does not take network mask into account.
207 # TODO Deprecate for filter_ipnet_hostaddr
208 def filter_ipaddr_index(base_address, index):
209 """Return IP address in given network at given index"""
211 base_address_str = unicode(base_address)
212 except NameError as ex:
213 base_address_str = str(base_address)
214 return IPv4Address(base_address_str) + int(index)
217 # TODO deprecate for filter_ipnet_netmask
218 def filter_netmask(prefix):
219 """Get netmask from prefix length integer"""
221 prefix_str = unicode(prefix)
222 except NameError as ex:
223 prefix_str = str(prefix)
224 return IPv4Network("1.0.0.0/"+prefix_str).netmask