blob: 75f8838352c9e3708d27243ee8a3ce09972bbe8a [file] [log] [blame]
Kang Xi11d278c2018-04-06 16:56:04 -04001import json
2import logging
3import os
4import pickle
5import re
6import sys
7
8import ipaddress
9import mysql.connector
10import requests
11import commands
12import time
13
14
15class VcpeCommon:
16 #############################################################################################
17 # Start: configurations that you must change for a new ONAP installation
18 external_net_addr = '10.12.0.0'
19 external_net_prefix_len = 16
20 #############################################################################################
21 # set the openstack cloud access credentials here
Kang Xi0e0a1d62018-07-23 16:53:54 -040022 oom_mode = False
23
Kang Xi11d278c2018-04-06 16:56:04 -040024 cloud = {
25 '--os-auth-url': 'http://10.12.25.2:5000',
Kang Xi268b74d2018-05-23 15:53:42 -040026 '--os-username': 'kxi',
Kang Xi11d278c2018-04-06 16:56:04 -040027 '--os-user-domain-id': 'default',
28 '--os-project-domain-id': 'default',
Kang Xi0e0a1d62018-07-23 16:53:54 -040029 '--os-tenant-id': '41d6d38489bd40b09ea8a6b6b852dcbd' if oom_mode else '1e097c6713e74fd7ac8e4295e605ee1e',
Kang Xi11d278c2018-04-06 16:56:04 -040030 '--os-region-name': 'RegionOne',
Kang Xi268b74d2018-05-23 15:53:42 -040031 '--os-password': 'n3JhGMGuDzD8',
Kang Xi0e0a1d62018-07-23 16:53:54 -040032 '--os-project-domain-name': 'Integration-SB-00' if oom_mode else 'Integration-SB-07',
Kang Xi11d278c2018-04-06 16:56:04 -040033 '--os-identity-api-version': '3'
34 }
35
36 common_preload_config = {
Kang Xi0e0a1d62018-07-23 16:53:54 -040037 'oam_onap_net': 'oam_network_0qV7' if oom_mode else 'oam_onap_lAky',
38 'oam_onap_subnet': 'oam_network_0qV7' if oom_mode else 'oam_onap_lAky',
Kang Xi11d278c2018-04-06 16:56:04 -040039 'public_net': 'external',
40 'public_net_id': '971040b2-7059-49dc-b220-4fab50cb2ad4'
41 }
Kang Xi0e0a1d62018-07-23 16:53:54 -040042# for sb07
43# 'oam_onap_lAky',
44# for sb00
45 #'oam_onap_net': 'oam_network_0qV7',
46 #'oam_onap_subnet': 'oam_network_0qV7',
Kang Xi11d278c2018-04-06 16:56:04 -040047 # End: configurations that you must change for a new ONAP installation
48 #############################################################################################
49
50 template_variable_symbol = '${'
Kang Xi6c762392018-05-30 09:27:34 -040051 cpe_vm_prefix = 'zdcpe'
Kang Xi11d278c2018-04-06 16:56:04 -040052 #############################################################################################
53 # preloading network config
54 # key=network role
55 # value = [subnet_start_ip, subnet_gateway_ip]
56 preload_network_config = {
57 'cpe_public': ['10.2.0.2', '10.2.0.1'],
58 'cpe_signal': ['10.4.0.2', '10.4.0.1'],
59 'brg_bng': ['10.3.0.2', '10.3.0.1'],
60 'bng_mux': ['10.1.0.10', '10.1.0.1'],
61 'mux_gw': ['10.5.0.10', '10.5.0.1']
62 }
63
Kang Xi268b74d2018-05-23 15:53:42 -040064 dcae_ves_collector_name = 'dcae-bootstrap'
Kang Xi11d278c2018-04-06 16:56:04 -040065 global_subscriber_id = 'SDN-ETHERNET-INTERNET'
Kang Xi268b74d2018-05-23 15:53:42 -040066 project_name = 'Project-Demonstration'
67 owning_entity_id = '520cc603-a3c4-4ec2-9ef4-ca70facd79c0'
68 owning_entity_name = 'OE-Demonstration'
Kang Xi11d278c2018-04-06 16:56:04 -040069
70 def __init__(self, extra_host_names=None):
71 self.logger = logging.getLogger(__name__)
72 self.logger.info('Initializing configuration')
73
Kang Xi0e0a1d62018-07-23 16:53:54 -040074 self.oom_so_sdnc_aai_ip = '10.12.5.18'
75 self.oom_dcae_ves_collector = '10.12.5.18'
76 self.so_nbi_port = '30223' if self.oom_mode else '8080'
77 self.sdnc_preloading_port = '30202' if self.oom_mode else '8282'
78 self.aai_query_port = '30233' if self.oom_mode else '8443'
79 self.sniro_port = '30288' if self.oom_mode else '8080'
80
Kang Xi268b74d2018-05-23 15:53:42 -040081 self.host_names = ['so', 'sdnc', 'robot', 'aai-inst1', self.dcae_ves_collector_name]
Kang Xi11d278c2018-04-06 16:56:04 -040082 if extra_host_names:
83 self.host_names.extend(extra_host_names)
84 # get IP addresses
85 self.hosts = self.get_vm_ip(self.host_names, self.external_net_addr, self.external_net_prefix_len)
86 # this is the keyword used to name vgw stack, must not be used in other stacks
87 self.vgw_name_keyword = 'base_vcpe_vgw'
88 self.svc_instance_uuid_file = '__var/svc_instance_uuid'
89 self.preload_dict_file = '__var/preload_dict'
90 self.vgmux_vnf_name_file = '__var/vgmux_vnf_name'
91 self.product_family_id = 'f9457e8c-4afd-45da-9389-46acd9bf5116'
92 self.custom_product_family_id = 'a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb'
93 self.instance_name_prefix = {
94 'service': 'vcpe_svc',
95 'network': 'vcpe_net',
96 'vnf': 'vcpe_vnf',
97 'vfmodule': 'vcpe_vfmodule'
98 }
99 self.aai_userpass = 'AAI', 'AAI'
100 self.pub_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKXDgoo3+WOqcUG8/5uUbk81+yczgwC4Y8ywTmuQqbNxlY1oQ0YxdMUqUnhitSXs5S/yRuAVOYHwGg2mCs20oAINrP+mxBI544AMIb9itPjCtgqtE2EWo6MmnFGbHB4Sx3XioE7F4VPsh7japsIwzOjbrQe+Mua1TGQ5d4nfEOQaaglXLLPFfuc7WbhbJbK6Q7rHqZfRcOwAMXgDoBqlyqKeiKwnumddo2RyNT8ljYmvB6buz7KnMinzo7qB0uktVT05FH9Rg0CTWH5norlG5qXgP2aukL0gk1ph8iAt7uYLf1ktp+LJI2gaF6L0/qli9EmVCSLr1uJ38Q8CBflhkh'
101 self.os_tenant_id = self.cloud['--os-tenant-id']
102 self.os_region_name = self.cloud['--os-region-name']
103 self.common_preload_config['pub_key'] = self.pub_key
Kang Xi0e0a1d62018-07-23 16:53:54 -0400104 self.sniro_url = 'http://' + self.hosts['robot'] + ':' + self.sniro_port + '/__admin/mappings'
Kang Xi11d278c2018-04-06 16:56:04 -0400105 self.sniro_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
Kang Xi268b74d2018-05-23 15:53:42 -0400106 self.homing_solution = 'sniro' # value is either 'sniro' or 'oof'
107# self.homing_solution = 'oof'
108 self.customer_location_used_by_oof = {
109 "customerLatitude": "32.897480",
110 "customerLongitude": "-97.040443",
111 "customerName": "some_company"
112 }
Kang Xi11d278c2018-04-06 16:56:04 -0400113
114 #############################################################################################
115 # SDNC urls
116 self.sdnc_userpass = 'admin', 'Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
117 self.sdnc_db_name = 'sdnctl'
118 self.sdnc_db_user = 'sdnctl'
119 self.sdnc_db_pass = 'gamma'
Kang Xi268b74d2018-05-23 15:53:42 -0400120 self.sdnc_db_port = '32774'
Kang Xi11d278c2018-04-06 16:56:04 -0400121 self.sdnc_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
122 self.sdnc_preload_network_url = 'http://' + self.hosts['sdnc'] + \
Kang Xi0e0a1d62018-07-23 16:53:54 -0400123 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-network-topology-operation'
Kang Xi11d278c2018-04-06 16:56:04 -0400124 self.sdnc_preload_vnf_url = 'http://' + self.hosts['sdnc'] + \
Kang Xi0e0a1d62018-07-23 16:53:54 -0400125 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-vnf-topology-operation'
126 self.sdnc_ar_cleanup_url = 'http://' + self.hosts['sdnc'] + ':' + self.sdnc_preloading_port + \
127 '/restconf/config/GENERIC-RESOURCE-API:'
Kang Xi11d278c2018-04-06 16:56:04 -0400128
129 #############################################################################################
130 # SO urls, note: do NOT add a '/' at the end of the url
Kang Xi0e0a1d62018-07-23 16:53:54 -0400131 self.so_req_api_url = {'v4': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/ecomp/mso/infra/serviceInstances/v4',
132 'v5': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/ecomp/mso/infra/serviceInstances/v5'}
133 self.so_check_progress_api_url = 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/ecomp/mso/infra/orchestrationRequests/v5'
Kang Xi11d278c2018-04-06 16:56:04 -0400134 self.so_userpass = 'InfraPortalClient', 'password1$'
135 self.so_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
136 self.so_db_name = 'mso_catalog'
137 self.so_db_user = 'root'
138 self.so_db_pass = 'password'
Kang Xi0e0a1d62018-07-23 16:53:54 -0400139 self.so_db_port = '30252' if self.oom_mode else '32769'
Kang Xi11d278c2018-04-06 16:56:04 -0400140
141 self.vpp_inf_url = 'http://{0}:8183/restconf/config/ietf-interfaces:interfaces'
142 self.vpp_api_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
143 self.vpp_api_userpass = ('admin', 'admin')
144 self.vpp_ves_url= 'http://{0}:8183/restconf/config/vesagent:vesagent'
145
146 def headbridge(self, openstack_stack_name, svc_instance_uuid):
147 """
148 Add vserver information to AAI
149 """
150 self.logger.info('Adding vServer information to AAI for {0}'.format(openstack_stack_name))
Kang Xi0e0a1d62018-07-23 16:53:54 -0400151 if not self.oom_mode:
152 cmd = '/opt/demo.sh heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid)
153 ret = commands.getstatusoutput("ssh -i onap_dev root@{0} '{1}'".format(self.hosts['robot'], cmd))
154 self.logger.debug('%s', ret)
155 else:
156 print('To add vGMUX vserver info to AAI, do the following:')
157 print('- ssh to rancher')
158 print('- sudo su -')
159 print('- cd /root/oom/kubernetes/robot')
160 print('- ./demo-k8s.sh onap heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid))
Kang Xi11d278c2018-04-06 16:56:04 -0400161
162 def get_brg_mac_from_sdnc(self):
163 """
Kang Xi6c762392018-05-30 09:27:34 -0400164 Check table DHCP_MAP in the SDNC DB. Find the newly instantiated BRG MAC address.
165 Note that there might be multiple BRGs, the most recently instantiated BRG always has the largest IP address.
Kang Xi11d278c2018-04-06 16:56:04 -0400166 """
167 cnx = mysql.connector.connect(user=self.sdnc_db_user, password=self.sdnc_db_pass, database=self.sdnc_db_name,
168 host=self.hosts['sdnc'], port=self.sdnc_db_port)
169 cursor = cnx.cursor()
170 query = "SELECT * from DHCP_MAP"
171 cursor.execute(query)
172
173 self.logger.debug('DHCP_MAP table in SDNC')
Kang Xi6c762392018-05-30 09:27:34 -0400174 mac_recent = None
175 host = -1
Kang Xi11d278c2018-04-06 16:56:04 -0400176 for mac, ip in cursor:
Kang Xi11d278c2018-04-06 16:56:04 -0400177 self.logger.debug(mac + ':' + ip)
Kang Xi6c762392018-05-30 09:27:34 -0400178 this_host = int(ip.split('.')[-1])
179 if host < this_host:
180 host = this_host
181 mac_recent = mac
Kang Xi11d278c2018-04-06 16:56:04 -0400182
183 cnx.close()
184
Kang Xi6c762392018-05-30 09:27:34 -0400185 assert mac_recent
186 return mac_recent
Kang Xi11d278c2018-04-06 16:56:04 -0400187
Kang Xi6c762392018-05-30 09:27:34 -0400188 def execute_cmds_sdnc_db(self, cmds):
189 self.execute_cmds_db(cmds, self.sdnc_db_user, self.sdnc_db_pass, self.sdnc_db_name,
190 self.hosts['sdnc'], self.sdnc_db_port)
Kang Xi11d278c2018-04-06 16:56:04 -0400191
Kang Xi6c762392018-05-30 09:27:34 -0400192 def execute_cmds_so_db(self, cmds):
193 self.execute_cmds_db(cmds, self.so_db_user, self.so_db_pass, self.so_db_name,
194 self.hosts['so'], self.so_db_port)
195
196 def execute_cmds_db(self, cmds, dbuser, dbpass, dbname, host, port):
197 cnx = mysql.connector.connect(user=dbuser, password=dbpass, database=dbname, host=host, port=port)
Kang Xi11d278c2018-04-06 16:56:04 -0400198 cursor = cnx.cursor()
199 for cmd in cmds:
200 self.logger.debug(cmd)
201 cursor.execute(cmd)
202 self.logger.debug('%s', cursor)
203 cnx.commit()
204 cursor.close()
205 cnx.close()
206
207 def find_file(self, file_name_keyword, file_ext, search_dir):
208 """
209 :param file_name_keyword: keyword used to look for the csar file, case insensitive matching, e.g, infra
210 :param file_ext: e.g., csar, json
211 :param search_dir path to search
212 :return: path name of the file
213 """
214 file_name_keyword = file_name_keyword.lower()
215 file_ext = file_ext.lower()
216 if not file_ext.startswith('.'):
217 file_ext = '.' + file_ext
218
219 filenamepath = None
220 for file_name in os.listdir(search_dir):
221 file_name_lower = file_name.lower()
222 if file_name_keyword in file_name_lower and file_name_lower.endswith(file_ext):
223 if filenamepath:
224 self.logger.error('Multiple files found for *{0}*.{1} in '
225 'directory {2}'.format(file_name_keyword, file_ext, search_dir))
226 sys.exit()
227 filenamepath = os.path.abspath(os.path.join(search_dir, file_name))
228
229 if filenamepath:
230 return filenamepath
231 else:
232 self.logger.error("Cannot find *{0}*{1} in directory {2}".format(file_name_keyword, file_ext, search_dir))
233 sys.exit()
234
235 @staticmethod
236 def network_name_to_subnet_name(network_name):
237 """
238 :param network_name: example: vcpe_net_cpe_signal_201711281221
239 :return: vcpe_net_cpe_signal_subnet_201711281221
240 """
241 fields = network_name.split('_')
242 fields.insert(-1, 'subnet')
243 return '_'.join(fields)
244
245 def set_network_name(self, network_name):
246 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
247 openstackcmd = 'openstack ' + param
248 cmd = ' '.join([openstackcmd, 'network set --name', network_name, 'ONAP-NW1'])
249 os.popen(cmd)
250
251 def set_subnet_name(self, network_name):
252 """
253 Example: network_name = vcpe_net_cpe_signal_201711281221
254 set subnet name to vcpe_net_cpe_signal_subnet_201711281221
255 :return:
256 """
257 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
258 openstackcmd = 'openstack ' + param
259
260 # expected results: | subnets | subnet_id |
261 subnet_info = os.popen(openstackcmd + ' network show ' + network_name + ' |grep subnets').read().split('|')
262 if len(subnet_info) > 2 and subnet_info[1].strip() == 'subnets':
263 subnet_id = subnet_info[2].strip()
264 subnet_name = self.network_name_to_subnet_name(network_name)
265 cmd = ' '.join([openstackcmd, 'subnet set --name', subnet_name, subnet_id])
266 os.popen(cmd)
267 self.logger.info("Subnet name set to: " + subnet_name)
268 return True
269 else:
270 self.logger.error("Can't get subnet info from network name: " + network_name)
271 return False
272
273 def is_node_in_aai(self, node_type, node_uuid):
274 key = None
275 search_node_type = None
276 if node_type == 'service':
277 search_node_type = 'service-instance'
278 key = 'service-instance-id'
279 elif node_type == 'vnf':
280 search_node_type = 'generic-vnf'
281 key = 'vnf-id'
282 else:
283 logging.error('Invalid node_type: ' + node_type)
284 sys.exit()
285
Kang Xi0e0a1d62018-07-23 16:53:54 -0400286 url = 'https://{0}:{1}/aai/v11/search/nodes-query?search-node-type={2}&filter={3}:EQUALS:{4}'.format(
287 self.hosts['aai-inst1'], self.aai_query_port, search_node_type, key, node_uuid)
Kang Xi11d278c2018-04-06 16:56:04 -0400288
Kang Xi268b74d2018-05-23 15:53:42 -0400289 headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-FromAppID': 'vCPE-Robot', 'X-TransactionId': 'get_aai_subscr'}
Kang Xi11d278c2018-04-06 16:56:04 -0400290 requests.packages.urllib3.disable_warnings()
291 r = requests.get(url, headers=headers, auth=self.aai_userpass, verify=False)
292 response = r.json()
293 self.logger.debug('aai query: ' + url)
294 self.logger.debug('aai response:\n' + json.dumps(response, indent=4, sort_keys=True))
295 return 'result-data' in response
296
297 @staticmethod
298 def extract_ip_from_str(net_addr, net_addr_len, sz):
299 """
300 :param net_addr: e.g. 10.5.12.0
301 :param net_addr_len: e.g. 24
302 :param sz: a string
303 :return: the first IP address matching the network, e.g. 10.5.12.3
304 """
305 network = ipaddress.ip_network(unicode('{0}/{1}'.format(net_addr, net_addr_len)), strict=False)
306 ip_list = re.findall(r'[0-9]+(?:\.[0-9]+){3}', sz)
307 for ip in ip_list:
308 this_net = ipaddress.ip_network(unicode('{0}/{1}'.format(ip, net_addr_len)), strict=False)
309 if this_net == network:
310 return str(ip)
311 return None
312
313 def get_vm_ip(self, keywords, net_addr=None, net_addr_len=None):
314 """
315 :param keywords: list of keywords to search for vm, e.g. ['bng', 'gmux', 'brg']
316 :param net_addr: e.g. 10.12.5.0
317 :param net_addr_len: e.g. 24
318 :return: dictionary {keyword: ip}
319 """
320 if not net_addr:
321 net_addr = self.external_net_addr
322
323 if not net_addr_len:
324 net_addr_len = self.external_net_prefix_len
325
326 param = ' '.join([k + ' ' + v for k, v in self.cloud.items() if 'identity' not in k])
327 openstackcmd = 'nova ' + param + ' list'
328 self.logger.debug(openstackcmd)
329
Kang Xi11d278c2018-04-06 16:56:04 -0400330 results = os.popen(openstackcmd).read()
Kang Xi6c762392018-05-30 09:27:34 -0400331 all_vm_ip_dict = self.extract_vm_ip_as_dict(results, net_addr, net_addr_len)
332 latest_vm_list = self.remove_old_vms(all_vm_ip_dict.keys(), self.cpe_vm_prefix)
333 latest_vm_ip_dict = {vm: all_vm_ip_dict[vm] for vm in latest_vm_list}
334 ip_dict = self.select_subset_vm_ip(latest_vm_ip_dict, keywords)
Kang Xi0e0a1d62018-07-23 16:53:54 -0400335 if self.oom_mode:
336 ip_dict.update(self.get_oom_onap_vm_ip(keywords))
Kang Xi6c762392018-05-30 09:27:34 -0400337
Kang Xi11d278c2018-04-06 16:56:04 -0400338 if len(ip_dict) != len(keywords):
339 self.logger.error('Cannot find all desired IP addresses for %s.', keywords)
340 self.logger.error(json.dumps(ip_dict, indent=4, sort_keys=True))
Kang Xi268b74d2018-05-23 15:53:42 -0400341 self.logger.error('Temporarily continue.. remember to check back vcpecommon.py line: 316')
342# sys.exit()
Kang Xi11d278c2018-04-06 16:56:04 -0400343 return ip_dict
344
Kang Xi0e0a1d62018-07-23 16:53:54 -0400345 def get_oom_onap_vm_ip(self, keywords):
346 vm_ip = {}
347 onap_vm_list = set(['so', 'sdnc', 'aai-inst1', 'robot', self.dcae_ves_collector_name])
348 for vm in keywords:
349 if vm in onap_vm_list:
350 vm_ip[vm] = self.oom_so_sdnc_aai_ip
351 return vm_ip
352
Kang Xi6c762392018-05-30 09:27:34 -0400353 def extract_vm_ip_as_dict(self, novalist_results, net_addr, net_addr_len):
354 vm_ip_dict = {}
355 for line in novalist_results.split('\n'):
356 fields = line.split('|')
357 if len(fields) == 8:
358 vm_name = fields[2]
359 ip_info = fields[-2]
360 ip = self.extract_ip_from_str(net_addr, net_addr_len, ip_info)
361 vm_ip_dict[vm_name] = ip
362
363 return vm_ip_dict
364
365 def remove_old_vms(self, vm_list, prefix):
366 """
367 For vms with format name_timestamp, only keep the one with the latest timestamp.
368 E.g.,
369 zdcpe1cpe01brgemu01_201805222148 (drop this)
370 zdcpe1cpe01brgemu01_201805222229 (keep this)
371 zdcpe1cpe01gw01_201805162201
372 """
373 new_vm_list = []
374 same_type_vm_dict = {}
375 for vm in vm_list:
376 fields = vm.split('_')
377 if vm.startswith(prefix) and len(fields) == 2 and len(fields[-1]) == len('201805222148') and fields[-1].isdigit():
378 if vm > same_type_vm_dict.get(fields[0], '0'):
379 same_type_vm_dict[fields[0]] = vm
380 else:
381 new_vm_list.append(vm)
382
383 new_vm_list.extend(same_type_vm_dict.values())
384 return new_vm_list
385
386 def select_subset_vm_ip(self, all_vm_ip_dict, vm_name_keyword_list):
387 vm_ip_dict = {}
388 for keyword in vm_name_keyword_list:
389 for vm, ip in all_vm_ip_dict.items():
390 if keyword in vm:
391 vm_ip_dict[keyword] = ip
392 break
393 return vm_ip_dict
394
Kang Xi11d278c2018-04-06 16:56:04 -0400395 def del_vgmux_ves_mode(self):
396 url = self.vpp_ves_url.format(self.hosts['mux']) + '/mode'
397 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
398 self.logger.debug('%s', r)
399
400 def del_vgmux_ves_collector(self):
401 url = self.vpp_ves_url.format(self.hosts['mux']) + '/config'
402 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
403 self.logger.debug('%s', r)
404
405 def set_vgmux_ves_collector(self ):
406 url = self.vpp_ves_url.format(self.hosts['mux'])
407 data = {'config':
Kang Xi268b74d2018-05-23 15:53:42 -0400408 {'server-addr': self.hosts[self.dcae_ves_collector_name],
Kang Xi0e0a1d62018-07-23 16:53:54 -0400409 'server-port': '30235' if self.oom_mode else '8081',
Kang Xi11d278c2018-04-06 16:56:04 -0400410 'read-interval': '10',
411 'is-add':'1'
412 }
413 }
414 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
415 self.logger.debug('%s', r)
416
417 def set_vgmux_packet_loss_rate(self, lossrate, vg_vnf_instance_name):
418 url = self.vpp_ves_url.format(self.hosts['mux'])
419 data = {"mode":
420 {"working-mode": "demo",
421 "base-packet-loss": str(lossrate),
422 "source-name": vg_vnf_instance_name
423 }
424 }
425 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
426 self.logger.debug('%s', r)
427
428 # return all the VxLAN interface names of BRG or vGMUX based on the IP address
429 def get_vxlan_interfaces(self, ip, print_info=False):
430 url = self.vpp_inf_url.format(ip)
431 self.logger.debug('url is this: %s', url)
432 r = requests.get(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
433 data = r.json()['interfaces']['interface']
434 if print_info:
435 for inf in data:
436 if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel':
437 print(json.dumps(inf, indent=4, sort_keys=True))
438
439 return [inf['name'] for inf in data if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel']
440
441 # delete all VxLAN interfaces of each hosts
442 def delete_vxlan_interfaces(self, host_dic):
443 for host, ip in host_dic.items():
444 deleted = False
445 self.logger.info('{0}: Getting VxLAN interfaces'.format(host))
446 inf_list = self.get_vxlan_interfaces(ip)
447 for inf in inf_list:
448 deleted = True
449 time.sleep(2)
450 self.logger.info("{0}: Deleting VxLAN crossconnect {1}".format(host, inf))
451 url = self.vpp_inf_url.format(ip) + '/interface/' + inf + '/v3po:l2'
452 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
453
454 for inf in inf_list:
455 deleted = True
456 time.sleep(2)
457 self.logger.info("{0}: Deleting VxLAN interface {1}".format(host, inf))
458 url = self.vpp_inf_url.format(ip) + '/interface/' + inf
459 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
460
461 if len(self.get_vxlan_interfaces(ip)) > 0:
462 self.logger.error("Error deleting VxLAN from {0}, try to restart the VM, IP is {1}.".format(host, ip))
463 return False
464
465 if not deleted:
466 self.logger.info("{0}: no VxLAN interface found, nothing to delete".format(host))
467 return True
468
469 @staticmethod
470 def save_object(obj, filepathname):
471 with open(filepathname, 'wb') as fout:
472 pickle.dump(obj, fout)
473
474 @staticmethod
475 def load_object(filepathname):
476 with open(filepathname, 'rb') as fin:
477 return pickle.load(fin)
478
Kang Xi6c762392018-05-30 09:27:34 -0400479 @staticmethod
480 def increase_ip_address_or_vni_in_template(vnf_template_file, vnf_parameter_name_list):
481 with open(vnf_template_file) as json_input:
482 json_data = json.load(json_input)
483 param_list = json_data['VNF-API:input']['VNF-API:vnf-topology-information']['VNF-API:vnf-parameters']
484 for param in param_list:
485 if param['vnf-parameter-name'] in vnf_parameter_name_list:
486 ipaddr_or_vni = param['vnf-parameter-value'].split('.')
487 number = int(ipaddr_or_vni[-1])
488 if 254 == number:
489 number = 10
490 else:
491 number = number + 1
492 ipaddr_or_vni[-1] = str(number)
493 param['vnf-parameter-value'] = '.'.join(ipaddr_or_vni)
494
495 assert json_data is not None
496 with open(vnf_template_file, 'w') as json_output:
497 json.dump(json_data, json_output, indent=4, sort_keys=True)
498
Kang Xi11d278c2018-04-06 16:56:04 -0400499 def save_preload_data(self, preload_data):
500 self.save_object(preload_data, self.preload_dict_file)
501
502 def load_preload_data(self):
503 return self.load_object(self.preload_dict_file)
504
505 def save_vgmux_vnf_name(self, vgmux_vnf_name):
506 self.save_object(vgmux_vnf_name, self.vgmux_vnf_name_file)
507
508 def load_vgmux_vnf_name(self):
509 return self.load_object(self.vgmux_vnf_name_file)
510