13 from novaclient import client as openstackclient
14 from kubernetes import client, config
15 from netaddr import IPAddress, IPNetwork
17 ######################################################################
18 # Parts which must be updated / cross-checked during each deployment #
19 # are marked as CHANGEME #
20 ######################################################################
23 #############################################################################################
24 # Set network prefix of k8s host external address; it's used for pod public IP autodetection
25 # but can be overriden from user in case of autodetection failure
26 external_net_addr = '10.12.0.0'
27 external_net_prefix_len = 16
29 #############################################################################################
30 # set the openstack cloud access credentials here
33 ###########################
34 # set Openstack credentials
37 '--os-auth-url': 'http://10.12.25.2:5000',
38 '--os-username': 'kxi',
39 '--os-user-domain-id': 'default',
40 '--os-project-domain-id': 'default',
41 '--os-tenant-id': 'bc43d50ffcb84750bac0c1707a9a765b' if oom_mode else '1e097c6713e74fd7ac8e4295e605ee1e',
42 '--os-region-name': 'RegionOne',
43 '--os-password': 'n3JhGMGuDzD8',
44 '--os-project-domain-name': 'Integration-SB-03' if oom_mode else 'Integration-SB-07',
45 '--os-identity-api-version': '3'
48 ############################################################################
49 # set oam and public network which must exist in openstack before deployment
51 common_preload_config = {
52 'oam_onap_net': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
53 'oam_onap_subnet': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
54 'public_net': 'external',
55 'public_net_id': '971040b2-7059-49dc-b220-4fab50cb2ad4'
58 #############################################################################
59 # set name of sdnc controller pod, prefix is taken from helm environment name
61 sdnc_controller_pod = 'dev-sdnc-sdnc-0'
63 template_variable_symbol = '${'
64 cpe_vm_prefix = 'zdcpe'
66 #############################################################################################
67 # preloading network config
69 # value = [subnet_start_ip, subnet_gateway_ip]
70 preload_network_config = {
71 'cpe_public': ['10.2.0.2', '10.2.0.1'],
72 'cpe_signal': ['10.4.0.2', '10.4.0.1'],
73 'brg_bng': ['10.3.0.2', '10.3.0.1'],
74 'bng_mux': ['10.1.0.10', '10.1.0.1'],
75 'mux_gw': ['10.5.0.10', '10.5.0.1']
78 dcae_ves_collector_name = 'dcae-bootstrap'
79 global_subscriber_id = 'SDN-ETHERNET-INTERNET'
80 project_name = 'Project-Demonstration'
81 owning_entity_id = '520cc603-a3c4-4ec2-9ef4-ca70facd79c0'
82 owning_entity_name = 'OE-Demonstration1'
84 def __init__(self, extra_host_names=None):
85 self.logger = logging.getLogger(__name__)
86 self.logger.setLevel(logging.DEBUG)
87 self.logger.info('Initializing configuration')
89 ##################################################################################################################################
90 # following param must be updated e.g. from csar file (grep for VfModuleModelInvariantUuid string) before vcpe.py customer call !!
91 # vgw_VfModuleModelInvariantUuid is in rescust service csar,
92 # look in service-VcpesvcRescust1118-template.yml for groups vgw module metadata. TODO: read this value automatically
94 self.vgw_VfModuleModelInvariantUuid = '26d6a718-17b2-4ba8-8691-c44343b2ecd2'
96 # OOM: this is the address that the brg and bng will nat for sdnc access - 10.0.0.x address of k8 host for sdnc-0 container
97 self.sdnc_oam_ip = self.get_pod_node_oam_ip(self.sdnc_controller_pod)
98 # OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
99 self.oom_so_sdnc_aai_ip = self.get_pod_node_public_ip(self.sdnc_controller_pod)
100 # OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
101 self.oom_dcae_ves_collector = self.oom_so_sdnc_aai_ip
102 # OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
103 self.mr_ip_addr = self.oom_so_sdnc_aai_ip
104 self.mr_ip_port = '30227'
105 self.so_nbi_port = '30277' if self.oom_mode else '8080'
106 self.sdnc_preloading_port = '30202' if self.oom_mode else '8282'
107 self.aai_query_port = '30233' if self.oom_mode else '8443'
108 self.sniro_port = '30288' if self.oom_mode else '8080'
110 self.host_names = ['sdc', 'so', 'sdnc', 'robot', 'aai-inst1', self.dcae_ves_collector_name]
112 self.host_names.extend(extra_host_names)
114 self.hosts = self.get_vm_ip(self.host_names, self.external_net_addr, self.external_net_prefix_len)
115 # this is the keyword used to name vgw stack, must not be used in other stacks
116 self.vgw_name_keyword = 'base_vcpe_vgw'
117 # this is the file that will keep the index of last assigned SO name
118 self.vgw_vfmod_name_index_file= '__var/vgw_vfmod_name_index'
119 self.svc_instance_uuid_file = '__var/svc_instance_uuid'
120 self.preload_dict_file = '__var/preload_dict'
121 self.vgmux_vnf_name_file = '__var/vgmux_vnf_name'
122 self.product_family_id = 'f9457e8c-4afd-45da-9389-46acd9bf5116'
123 self.custom_product_family_id = 'a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb'
124 self.instance_name_prefix = {
125 'service': 'vcpe_svc',
126 'network': 'vcpe_net',
128 'vfmodule': 'vcpe_vfmodule'
130 self.aai_userpass = 'AAI', 'AAI'
132 ############################################################################################################
133 # following key is overriding public key from vCPE heat templates, it's important to use correct one in here
135 self.pub_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKXDgoo3+WOqcUG8/5uUbk81+yczgwC4Y8ywTmuQqbNxlY1oQ0YxdMUqUnhitSXs5S/yRuAVOYHwGg2mCs20oAINrP+mxBI544AMIb9itPjCtgqtE2EWo6MmnFGbHB4Sx3XioE7F4VPsh7japsIwzOjbrQe+Mua1TGQ5d4nfEOQaaglXLLPFfuc7WbhbJbK6Q7rHqZfRcOwAMXgDoBqlyqKeiKwnumddo2RyNT8ljYmvB6buz7KnMinzo7qB0uktVT05FH9Rg0CTWH5norlG5qXgP2aukL0gk1ph8iAt7uYLf1ktp+LJI2gaF6L0/qli9EmVCSLr1uJ38Q8CBflhkh'
137 self.os_tenant_id = self.cloud['--os-tenant-id']
138 self.os_region_name = self.cloud['--os-region-name']
139 self.common_preload_config['pub_key'] = self.pub_key
140 self.sniro_url = 'http://' + self.hosts['robot'] + ':' + self.sniro_port + '/__admin/mappings'
141 self.sniro_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
142 self.homing_solution = 'sniro' # value is either 'sniro' or 'oof'
143 # self.homing_solution = 'oof'
144 self.customer_location_used_by_oof = {
145 "customerLatitude": "32.897480",
146 "customerLongitude": "-97.040443",
147 "customerName": "some_company"
150 #############################################################################################
152 self.sdc_be_port = '30205'
153 self.sdc_be_request_userpass = 'vid', 'Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
154 self.sdc_be_request_headers = {'X-ECOMP-InstanceID': 'VID'}
155 self.sdc_be_url_prefix = 'http://' + self.hosts['sdc'] + ':' + self.sdc_be_port
156 self.sdc_service_list_url = self.sdc_be_url_prefix + '/sdc/v1/catalog/services'
158 self.sdc_fe_port = '30206'
159 self.sdc_fe_request_userpass = 'beep', 'boop'
160 self.sdc_fe_request_headers = {'USER_ID': 'demo', 'Content-Type': 'application/json'}
161 self.sdc_fe_url_prefix = 'http://' + self.hosts['sdc'] + ':' + self.sdc_fe_port
162 self.sdc_get_category_list_url = self.sdc_fe_url_prefix + '/sdc1/feProxy/rest/v1/categories'
163 self.sdc_create_allotted_resource_subcategory_url = self.sdc_fe_url_prefix + '/sdc1/feProxy/rest/v1/category/resources/resourceNewCategory.allotted%20resource/subCategory'
165 #############################################################################################
167 self.sdnc_userpass = 'admin', 'Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
168 self.sdnc_db_name = 'sdnctl'
169 self.sdnc_db_user = 'sdnctl'
170 self.sdnc_db_pass = 'gamma'
171 self.sdnc_db_port = '32774'
172 self.sdnc_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
173 self.sdnc_preload_network_url = 'http://' + self.hosts['sdnc'] + \
174 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-network-topology-operation'
175 self.sdnc_preload_vnf_url = 'http://' + self.hosts['sdnc'] + \
176 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-vnf-topology-operation'
177 self.sdnc_preload_gra_url = 'http://' + self.hosts['sdnc'] + \
178 ':' + self.sdnc_preloading_port + '/restconf/operations/GENERIC-RESOURCE-API:preload-vf-module-topology-operation'
179 self.sdnc_ar_cleanup_url = 'http://' + self.hosts['sdnc'] + ':' + self.sdnc_preloading_port + \
180 '/restconf/config/GENERIC-RESOURCE-API:'
182 #############################################################################################
183 # SO urls, note: do NOT add a '/' at the end of the url
184 self.so_req_api_url = {'v4': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/serviceInstantiation/v7/serviceInstances',
185 'v5': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/serviceInstantiation/v7/serviceInstances'}
186 self.so_check_progress_api_url = 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/orchestrationRequests/v6'
187 self.so_userpass = 'InfraPortalClient', 'password1$'
188 self.so_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
189 self.so_db_name = 'catalogdb'
190 self.so_db_user = 'root'
191 self.so_db_pass = 'secretpassword'
192 self.so_db_port = '30252' if self.oom_mode else '32769'
194 self.vpp_inf_url = 'http://{0}:8183/restconf/config/ietf-interfaces:interfaces'
195 self.vpp_api_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
196 self.vpp_api_userpass = ('admin', 'admin')
197 self.vpp_ves_url= 'http://{0}:8183/restconf/config/vesagent:vesagent'
199 def heatbridge(self, openstack_stack_name, svc_instance_uuid):
201 Add vserver information to AAI
203 self.logger.info('Adding vServer information to AAI for {0}'.format(openstack_stack_name))
204 if not self.oom_mode:
205 cmd = '/opt/demo.sh heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid)
206 ret = commands.getstatusoutput("ssh -i onap_dev root@{0} '{1}'".format(self.hosts['robot'], cmd))
207 self.logger.debug('%s', ret)
209 print('To add vGMUX vserver info to AAI, do the following:')
210 print('- ssh to rancher')
212 print('- cd /root/oom/kubernetes/robot')
213 print('- ./demo-k8s.sh onap heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid))
215 def get_brg_mac_from_sdnc(self):
217 Check table DHCP_MAP in the SDNC DB. Find the newly instantiated BRG MAC address.
218 Note that there might be multiple BRGs, the most recently instantiated BRG always has the largest IP address.
220 cnx = mysql.connector.connect(user=self.sdnc_db_user, password=self.sdnc_db_pass, database=self.sdnc_db_name,
221 host=self.hosts['sdnc'], port=self.sdnc_db_port)
222 cursor = cnx.cursor()
223 query = "SELECT * from DHCP_MAP"
224 cursor.execute(query)
226 self.logger.debug('DHCP_MAP table in SDNC')
229 for mac, ip in cursor:
230 self.logger.debug(mac + ':' + ip)
231 this_host = int(ip.split('.')[-1])
241 def execute_cmds_sdnc_db(self, cmds):
242 self.execute_cmds_db(cmds, self.sdnc_db_user, self.sdnc_db_pass, self.sdnc_db_name,
243 self.hosts['sdnc'], self.sdnc_db_port)
245 def execute_cmds_so_db(self, cmds):
246 self.execute_cmds_db(cmds, self.so_db_user, self.so_db_pass, self.so_db_name,
247 self.hosts['so'], self.so_db_port)
249 def execute_cmds_db(self, cmds, dbuser, dbpass, dbname, host, port):
250 cnx = mysql.connector.connect(user=dbuser, password=dbpass, database=dbname, host=host, port=port)
251 cursor = cnx.cursor()
253 self.logger.debug(cmd)
255 self.logger.debug('%s', cursor)
260 def find_file(self, file_name_keyword, file_ext, search_dir):
262 :param file_name_keyword: keyword used to look for the csar file, case insensitive matching, e.g, infra
263 :param file_ext: e.g., csar, json
264 :param search_dir path to search
265 :return: path name of the file
267 file_name_keyword = file_name_keyword.lower()
268 file_ext = file_ext.lower()
269 if not file_ext.startswith('.'):
270 file_ext = '.' + file_ext
273 for file_name in os.listdir(search_dir):
274 file_name_lower = file_name.lower()
275 if file_name_keyword in file_name_lower and file_name_lower.endswith(file_ext):
277 self.logger.error('Multiple files found for *{0}*.{1} in '
278 'directory {2}'.format(file_name_keyword, file_ext, search_dir))
280 filenamepath = os.path.abspath(os.path.join(search_dir, file_name))
285 self.logger.error("Cannot find *{0}*{1} in directory {2}".format(file_name_keyword, file_ext, search_dir))
289 def network_name_to_subnet_name(network_name):
291 :param network_name: example: vcpe_net_cpe_signal_201711281221
292 :return: vcpe_net_cpe_signal_subnet_201711281221
294 fields = network_name.split('_')
295 fields.insert(-1, 'subnet')
296 return '_'.join(fields)
298 def set_network_name(self, network_name):
299 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
300 openstackcmd = 'openstack ' + param
301 cmd = ' '.join([openstackcmd, 'network set --name', network_name, 'ONAP-NW1'])
304 def set_subnet_name(self, network_name):
306 Example: network_name = vcpe_net_cpe_signal_201711281221
307 set subnet name to vcpe_net_cpe_signal_subnet_201711281221
310 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
311 openstackcmd = 'openstack ' + param
313 # expected results: | subnets | subnet_id |
314 subnet_info = os.popen(openstackcmd + ' network show ' + network_name + ' |grep subnets').read().split('|')
315 if len(subnet_info) > 2 and subnet_info[1].strip() == 'subnets':
316 subnet_id = subnet_info[2].strip()
317 subnet_name = self.network_name_to_subnet_name(network_name)
318 cmd = ' '.join([openstackcmd, 'subnet set --name', subnet_name, subnet_id])
320 self.logger.info("Subnet name set to: " + subnet_name)
323 self.logger.error("Can't get subnet info from network name: " + network_name)
326 def is_node_in_aai(self, node_type, node_uuid):
328 search_node_type = None
329 if node_type == 'service':
330 search_node_type = 'service-instance'
331 key = 'service-instance-id'
332 elif node_type == 'vnf':
333 search_node_type = 'generic-vnf'
336 logging.error('Invalid node_type: ' + node_type)
339 url = 'https://{0}:{1}/aai/v11/search/nodes-query?search-node-type={2}&filter={3}:EQUALS:{4}'.format(
340 self.hosts['aai-inst1'], self.aai_query_port, search_node_type, key, node_uuid)
342 headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-FromAppID': 'vCPE-Robot', 'X-TransactionId': 'get_aai_subscr'}
343 requests.packages.urllib3.disable_warnings()
344 r = requests.get(url, headers=headers, auth=self.aai_userpass, verify=False)
346 self.logger.debug('aai query: ' + url)
347 self.logger.debug('aai response:\n' + json.dumps(response, indent=4, sort_keys=True))
348 return 'result-data' in response
351 def extract_ip_from_str(net_addr, net_addr_len, sz):
353 :param net_addr: e.g. 10.5.12.0
354 :param net_addr_len: e.g. 24
356 :return: the first IP address matching the network, e.g. 10.5.12.3
358 network = ipaddress.ip_network(unicode('{0}/{1}'.format(net_addr, net_addr_len)), strict=False)
359 ip_list = re.findall(r'[0-9]+(?:\.[0-9]+){3}', sz)
361 this_net = ipaddress.ip_network(unicode('{0}/{1}'.format(ip, net_addr_len)), strict=False)
362 if this_net == network:
366 def get_pod_node_oam_ip(self, pod):
368 :Assuming kubectl is available and configured by default config (~/.kube/config)
369 :param pod: pod name substring, e.g. 'sdnc-sdnc-0'
370 :return pod's cluster node oam ip (10.0.0.0/16)
373 config.load_kube_config()
374 api = client.CoreV1Api()
375 kslogger = logging.getLogger('kubernetes')
376 kslogger.setLevel(logging.INFO)
377 res = api.list_pod_for_all_namespaces()
379 if pod in i.metadata.name:
380 self.logger.debug("found {0}\t{1}\t{2}".format(i.metadata.name, i.status.host_ip, i.spec.node_name))
381 ret = i.status.host_ip
385 ret = raw_input("Enter " + self.sdnc_controller_pod + " pod cluster node OAM IP address(10.0.0.0/16): ")
388 def get_pod_node_public_ip(self, pod):
390 :Assuming kubectl is available and configured by default config (~/.kube/config)
391 :param pod: pod name substring, e.g. 'sdnc-sdnc-0'
392 :return pod's cluster node public ip (i.e. 10.12.0.0/16)
395 config.load_kube_config()
396 api = client.CoreV1Api()
397 kslogger = logging.getLogger('kubernetes')
398 kslogger.setLevel(logging.INFO)
399 res = api.list_pod_for_all_namespaces()
401 if pod in i.metadata.name:
402 ret = self.get_vm_public_ip_by_nova(i.spec.node_name)
403 self.logger.debug("found node {0} public ip: {1}".format(i.spec.node_name, ret))
407 ret = raw_input("Enter " + self.sdnc_controller_pod + " pod cluster node public IP address(i.e. " + self.external_net_addr + "): ")
410 def get_vm_public_ip_by_nova(self, vm):
412 This method uses openstack nova api to retrieve vm public ip
416 subnet = IPNetwork('{0}/{1}'.format(self.external_net_addr, self.external_net_prefix_len))
417 nova = openstackclient.Client(2, self.cloud['--os-username'], self.cloud['--os-password'], self.cloud['--os-tenant-id'], self.cloud['--os-auth-url'])
418 for i in nova.servers.list():
420 for k, v in i.networks.items():
422 if IPAddress(ip) in subnet:
426 def get_vm_ip(self, keywords, net_addr=None, net_addr_len=None):
428 :param keywords: list of keywords to search for vm, e.g. ['bng', 'gmux', 'brg']
429 :param net_addr: e.g. 10.12.5.0
430 :param net_addr_len: e.g. 24
431 :return: dictionary {keyword: ip}
434 net_addr = self.external_net_addr
437 net_addr_len = self.external_net_prefix_len
439 param = ' '.join([k + ' ' + v for k, v in self.cloud.items() if 'identity' not in k])
440 openstackcmd = 'nova ' + param + ' list'
441 self.logger.debug(openstackcmd)
443 results = os.popen(openstackcmd).read()
444 all_vm_ip_dict = self.extract_vm_ip_as_dict(results, net_addr, net_addr_len)
445 latest_vm_list = self.remove_old_vms(all_vm_ip_dict.keys(), self.cpe_vm_prefix)
446 latest_vm_ip_dict = {vm: all_vm_ip_dict[vm] for vm in latest_vm_list}
447 ip_dict = self.select_subset_vm_ip(latest_vm_ip_dict, keywords)
449 ip_dict.update(self.get_oom_onap_vm_ip(keywords))
451 if len(ip_dict) != len(keywords):
452 self.logger.error('Cannot find all desired IP addresses for %s.', keywords)
453 self.logger.error(json.dumps(ip_dict, indent=4, sort_keys=True))
454 self.logger.error('Temporarily continue.. remember to check back vcpecommon.py line: 396')
458 def get_oom_onap_vm_ip(self, keywords):
460 onap_vm_list = set(['sdc', 'so', 'sdnc', 'aai-inst1', 'robot', self.dcae_ves_collector_name])
462 if vm in onap_vm_list:
463 vm_ip[vm] = self.oom_so_sdnc_aai_ip
466 def extract_vm_ip_as_dict(self, novalist_results, net_addr, net_addr_len):
468 for line in novalist_results.split('\n'):
469 fields = line.split('|')
473 ip = self.extract_ip_from_str(net_addr, net_addr_len, ip_info)
474 vm_ip_dict[vm_name] = ip
478 def remove_old_vms(self, vm_list, prefix):
480 For vms with format name_timestamp, only keep the one with the latest timestamp.
482 zdcpe1cpe01brgemu01_201805222148 (drop this)
483 zdcpe1cpe01brgemu01_201805222229 (keep this)
484 zdcpe1cpe01gw01_201805162201
487 same_type_vm_dict = {}
489 fields = vm.split('_')
490 if vm.startswith(prefix) and len(fields) == 2 and len(fields[-1]) == len('201805222148') and fields[-1].isdigit():
491 if vm > same_type_vm_dict.get(fields[0], '0'):
492 same_type_vm_dict[fields[0]] = vm
494 new_vm_list.append(vm)
496 new_vm_list.extend(same_type_vm_dict.values())
499 def select_subset_vm_ip(self, all_vm_ip_dict, vm_name_keyword_list):
501 for keyword in vm_name_keyword_list:
502 for vm, ip in all_vm_ip_dict.items():
504 vm_ip_dict[keyword] = ip
508 def del_vgmux_ves_mode(self):
509 url = self.vpp_ves_url.format(self.hosts['mux']) + '/mode'
510 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
511 self.logger.debug('%s', r)
513 def del_vgmux_ves_collector(self):
514 url = self.vpp_ves_url.format(self.hosts['mux']) + '/config'
515 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
516 self.logger.debug('%s', r)
518 def set_vgmux_ves_collector(self ):
519 url = self.vpp_ves_url.format(self.hosts['mux'])
521 {'server-addr': self.hosts[self.dcae_ves_collector_name],
522 'server-port': '30235' if self.oom_mode else '8081',
523 'read-interval': '10',
527 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
528 self.logger.debug('%s', r)
530 def set_vgmux_packet_loss_rate(self, lossrate, vg_vnf_instance_name):
531 url = self.vpp_ves_url.format(self.hosts['mux'])
533 {"working-mode": "demo",
534 "base-packet-loss": str(lossrate),
535 "source-name": vg_vnf_instance_name
538 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
539 self.logger.debug('%s', r)
541 # return all the VxLAN interface names of BRG or vGMUX based on the IP address
542 def get_vxlan_interfaces(self, ip, print_info=False):
543 url = self.vpp_inf_url.format(ip)
544 self.logger.debug('url is this: %s', url)
545 r = requests.get(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
546 data = r.json()['interfaces']['interface']
549 if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel':
550 print(json.dumps(inf, indent=4, sort_keys=True))
552 return [inf['name'] for inf in data if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel']
554 # delete all VxLAN interfaces of each hosts
555 def delete_vxlan_interfaces(self, host_dic):
556 for host, ip in host_dic.items():
558 self.logger.info('{0}: Getting VxLAN interfaces'.format(host))
559 inf_list = self.get_vxlan_interfaces(ip)
563 self.logger.info("{0}: Deleting VxLAN crossconnect {1}".format(host, inf))
564 url = self.vpp_inf_url.format(ip) + '/interface/' + inf + '/v3po:l2'
565 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
570 self.logger.info("{0}: Deleting VxLAN interface {1}".format(host, inf))
571 url = self.vpp_inf_url.format(ip) + '/interface/' + inf
572 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
574 if len(self.get_vxlan_interfaces(ip)) > 0:
575 self.logger.error("Error deleting VxLAN from {0}, try to restart the VM, IP is {1}.".format(host, ip))
579 self.logger.info("{0}: no VxLAN interface found, nothing to delete".format(host))
583 def save_object(obj, filepathname):
584 with open(filepathname, 'wb') as fout:
585 pickle.dump(obj, fout)
588 def load_object(filepathname):
589 with open(filepathname, 'rb') as fin:
590 return pickle.load(fin)
593 def increase_ip_address_or_vni_in_template(vnf_template_file, vnf_parameter_name_list):
594 with open(vnf_template_file) as json_input:
595 json_data = json.load(json_input)
596 param_list = json_data['VNF-API:input']['VNF-API:vnf-topology-information']['VNF-API:vnf-parameters']
597 for param in param_list:
598 if param['vnf-parameter-name'] in vnf_parameter_name_list:
599 ipaddr_or_vni = param['vnf-parameter-value'].split('.')
600 number = int(ipaddr_or_vni[-1])
605 ipaddr_or_vni[-1] = str(number)
606 param['vnf-parameter-value'] = '.'.join(ipaddr_or_vni)
608 assert json_data is not None
609 with open(vnf_template_file, 'w') as json_output:
610 json.dump(json_data, json_output, indent=4, sort_keys=True)
612 def save_preload_data(self, preload_data):
613 self.save_object(preload_data, self.preload_dict_file)
615 def load_preload_data(self):
616 return self.load_object(self.preload_dict_file)
618 def save_vgmux_vnf_name(self, vgmux_vnf_name):
619 self.save_object(vgmux_vnf_name, self.vgmux_vnf_name_file)
621 def load_vgmux_vnf_name(self):
622 return self.load_object(self.vgmux_vnf_name_file)