Merge "Build on jenkins nodes with label docker"
[osm/SO.git] / rwcm / plugins / rwconman / rift / tasklets / rwconmantasklet / xlate_cfg.py
1 #!/usr/bin/env python3
2
3 #
4 # Copyright 2016 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19
20 '''
21 This script will go through the input conffiguration template and convert all the matching "regular expression" and "strings"
22 specified in xlate_cp_list & xlate_str_list with matching IP addresses passed in as dictionary to this script.
23
24 -i Configuration template
25 -o Output final configuration complete with IP addresses
26 -x Xlate(Translate dictionary in string format
27 -t TAGS to be translated
28
29 '''
30
31 import sys
32 import getopt
33 import ast
34 import re
35 import yaml
36 import netaddr
37
38 from inspect import getsourcefile
39 import os.path
40
41 xlate_dict = None
42
43 def xlate_cp_list(line, cp_list):
44 for cp_string in cp_list:
45 match = re.search(cp_string, line)
46 if match is not None:
47 # resolve IP address using Connection Point dictionary
48 resolved_ip = xlate_dict[match.group(1)]
49 if resolved_ip is None:
50 print("No matching CP found: ", match.group(1))
51 exit(2)
52 else:
53 line = line[:match.start()] + resolved_ip + line[match.end():]
54 return line
55
56 def xlate_multi_colon_list(line, multi_colon_list):
57 for ucp_string in multi_colon_list:
58 #print("Searching :", ucp_string)
59 match = re.search(ucp_string, line)
60 if match is not None:
61 #print("match :", match.group())
62 # resolve IP address using Connection Point dictionary for specified member (unique) index
63 ucp_str_list = match.group(1).split(':')
64 print("matched = {}, split list = {}".format(match.group(1), ucp_str_list))
65 if len(ucp_str_list) != 3:
66 print("Invalid TAG in the configuration: ", match.group(1))
67 exit(2)
68
69 # Traslate given CP address & mask into netaddr
70 if ucp_string.startswith('<rw_unique_index:rw_connection_point:masklen'):
71 member_vnf_index = int(ucp_str_list[0])
72 resolved_ip = xlate_dict[ucp_str_list[1]]
73 masklen = ucp_str_list[2]
74 if resolved_ip is None:
75 print("No matching CP found: ", ucp_str_list[1])
76 exit(2)
77 if int(masklen) <= 0:
78 print("Invalid mask length: ", masklen)
79 exit(2)
80 else:
81 # Generate netaddr
82 ip_str = resolved_ip + '/' + masklen
83 #print("ip_str:", ip_str)
84 ip = netaddr.IPNetwork(ip_str)
85 if ucp_string.startswith('<rw_unique_index:rw_connection_point:masklen_broadcast'):
86 # Traslate given CP address & mask into broadcast address
87 addr = ip.broadcast
88 if ucp_string.startswith('<rw_unique_index:rw_connection_point:masklen_network'):
89 # Traslate given CP address & mask into network address
90 addr = ip.network
91 line = line[:match.start()] + str(addr) + line[match.end():]
92 return line
93
94
95
96 def xlate_colon_list(line, colon_list):
97 for ucp_string in colon_list:
98 #print("Searching :", ucp_string)
99 match = re.search(ucp_string, line)
100 if match is not None:
101 #print("match :", match.group())
102 # resolve IP address using Connection Point dictionary for specified member (unique) index
103 ucp_str_list = match.group(1).split(':')
104 #print("matched = {}, split list = {}".format(match.group(1), ucp_str_list))
105 if len(ucp_str_list) != 2:
106 print("Invalid TAG in the configuration: ", match.group(1))
107 exit(2)
108
109 # Unique Connection Point translation to IP
110 if ucp_string.startswith('<rw_unique_index:'):
111 member_vnf_index = int(ucp_str_list[0])
112 resolved_ip = xlate_dict[member_vnf_index][ucp_str_list[1]]
113 #print("member_vnf_index = {}, resolved_ip = {}", member_vnf_index, resolved_ip)
114 if resolved_ip is None:
115 print("For Unique index ({}), No matching CP found: {}", ucp_str_list[0], ucp_str_list[1])
116 exit(2)
117 else:
118 line = line[:match.start()] + resolved_ip + line[match.end():]
119
120 # Traslate given CP address & mask into netaddr
121 if ucp_string.startswith('<rw_connection_point:masklen'):
122 resolved_ip = xlate_dict[ucp_str_list[0]]
123 masklen = ucp_str_list[1]
124 if resolved_ip is None:
125 print("No matching CP found: ", ucp_str_list[0])
126 exit(2)
127 if int(masklen) <= 0:
128 print("Invalid mask length: ", masklen)
129 exit(2)
130 else:
131 # Generate netaddr
132 ip_str = resolved_ip + '/' + masklen
133 #print("ip_str:", ip_str)
134 ip = netaddr.IPNetwork(ip_str)
135
136 if ucp_string.startswith('<rw_connection_point:masklen_broadcast'):
137 # Traslate given CP address & mask into broadcast address
138 addr = ip.broadcast
139 if ucp_string.startswith('<rw_connection_point:masklen_network'):
140 # Traslate given CP address & mask into network address
141 addr = ip.network
142
143 line = line[:match.start()] + str(addr) + line[match.end():]
144 return line
145
146 def xlate_cp_to_tuple_list(line, cp_to_tuple_list):
147 for cp_string in cp_to_tuple_list:
148 match = re.search(cp_string, line)
149 if match is not None:
150 # resolve IP address using Connection Point dictionary
151 resolved_ip = xlate_dict[match.group(1)]
152 if resolved_ip is None:
153 print("No matching CP found: ", match.group(1))
154 exit(2)
155 else:
156 line = line[:match.start()] + match.group(1) + ':' + resolved_ip + line[match.end():]
157 return line
158
159 def xlate_str_list(line, str_list):
160 for replace_tag in str_list:
161 replace_string = replace_tag[1:-1]
162 line = line.replace(replace_tag, xlate_dict[replace_string])
163 return line
164
165
166 def main(argv=sys.argv[1:]):
167 cfg_template = None
168 cfg_file = None
169 global xlate_dict
170 try:
171 opts, args = getopt.getopt(argv,"i:o:x:")
172 except getopt.GetoptError:
173 print("Check arguments {}".format(argv))
174 sys.exit(2)
175 for opt, arg in opts:
176 if opt == '-i':
177 cfg_template = arg
178 elif opt in ("-o"):
179 cfg_file = arg
180 elif opt in ("-x"):
181 xlate_arg = arg
182
183 # Read TAGS from yaml file
184 # Read the translation tags from yaml file
185 yml_dir = os.path.dirname(os.path.abspath(getsourcefile(lambda:0)))
186 tags_input_file = os.path.join(yml_dir, 'xlate_tags.yml')
187 with open(tags_input_file, "r") as ti:
188 xlate_tags = yaml.load(ti.read())
189
190 # Need to work on the solution for multiple pattern of same type in single line.
191 try:
192 with open(xlate_arg, "r") as ti:
193 xlate_dict = yaml.load(ti.read())
194 try:
195 with open(cfg_template, 'r') as r:
196 try:
197 with open(cfg_file, 'w') as w:
198 # Traslate
199 try:
200 # For each line
201 for line in r:
202 if line.startswith("#"):
203 # Skip comment lines
204 continue
205 #print("1.Line : ", line)
206 # For each Connection Point translation to IP
207 line = xlate_cp_list(line, xlate_tags['xlate_cp_list'])
208 #print("2.Line : ", line)
209
210 # For each colon(:) separated tag, i.e. 3 inputs in a tag.
211 line = xlate_multi_colon_list(line, xlate_tags['xlate_multi_colon_list'])
212 #print("2a.Line : ", line)
213
214 # For each colon(:) separated tag, i.e. 2 inputs in a tag.
215 line = xlate_colon_list(line, xlate_tags['xlate_colon_list'])
216 #print("3.Line : ", line)
217
218 # For each connection point to tuple replacement
219 line = xlate_cp_to_tuple_list(line, xlate_tags['xlate_cp_to_tuple_list'])
220 #print("4.Line : ", line)
221
222 # For each direct replacement (currently only management IP address for ping/pong)
223 line = xlate_str_list(line, xlate_tags['xlate_str_list'])
224 #print("5.Line : ", line)
225
226 # Finally write the modified line to the new config file
227 w.write(line)
228 except Exception as e:
229 print("Error ({}) on line: {}".format(str(e), line))
230 exit(2)
231 except Exception as e:
232 print("Failed to open for write: {}, error({})".format(cfg_file, str(e)))
233 exit(2)
234 except Exception as e:
235 print("Failed to open for read: {}, error({})".format(cfg_template, str(e)))
236 exit(2)
237 print("Wrote configuration file", cfg_file)
238 except Exception as e:
239 print("Could not translate dictionary, error: ", str(e))
240
241 if __name__ == "__main__":
242 try:
243 main()
244 except Exception as e:
245 print(str(e))