13 from novaclient import client as openstackclient
14 from kubernetes import client, config
15 from netaddr import IPAddress, IPNetwork
18 #############################################################################################
19 # Start: configurations that you must change for a new ONAP installation
21 #############################################################################################
22 # Set network prefix of k8s host external address; mainly used for pod public IP autodetection
23 external_net_addr = '10.12.0.0'
24 external_net_prefix_len = 16
26 #############################################################################################
27 # set the openstack cloud access credentials here
31 '--os-auth-url': 'http://10.12.25.2:5000',
32 '--os-username': 'kxi',
33 '--os-user-domain-id': 'default',
34 '--os-project-domain-id': 'default',
35 '--os-tenant-id': 'bc43d50ffcb84750bac0c1707a9a765b' if oom_mode else '1e097c6713e74fd7ac8e4295e605ee1e',
36 '--os-region-name': 'RegionOne',
37 '--os-password': 'n3JhGMGuDzD8',
38 '--os-project-domain-name': 'Integration-SB-03' if oom_mode else 'Integration-SB-07',
39 '--os-identity-api-version': '3'
42 common_preload_config = {
43 'oam_onap_net': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
44 'oam_onap_subnet': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
45 'public_net': 'external',
46 'public_net_id': '971040b2-7059-49dc-b220-4fab50cb2ad4'
48 sdnc_controller_pod = 'dev-sdnc-sdnc-0'
50 #############################################################################################
52 template_variable_symbol = '${'
53 cpe_vm_prefix = 'zdcpe'
54 #############################################################################################
55 # preloading network config
57 # value = [subnet_start_ip, subnet_gateway_ip]
58 preload_network_config = {
59 'cpe_public': ['10.2.0.2', '10.2.0.1'],
60 'cpe_signal': ['10.4.0.2', '10.4.0.1'],
61 'brg_bng': ['10.3.0.2', '10.3.0.1'],
62 'bng_mux': ['10.1.0.10', '10.1.0.1'],
63 'mux_gw': ['10.5.0.10', '10.5.0.1']
66 dcae_ves_collector_name = 'dcae-bootstrap'
67 global_subscriber_id = 'SDN-ETHERNET-INTERNET'
68 project_name = 'Project-Demonstration'
69 owning_entity_id = '520cc603-a3c4-4ec2-9ef4-ca70facd79c0'
70 owning_entity_name = 'OE-Demonstration1'
72 def __init__(self, extra_host_names=None):
73 self.logger = logging.getLogger(__name__)
74 self.logger.setLevel(logging.DEBUG)
75 self.logger.info('Initializing configuration')
77 # CHANGEME: vgw_VfModuleModelInvariantUuid is in rescust service csar, look in service-VcpesvcRescust1118-template.yml for groups vgw module metadata. TODO: read this value automcatically
78 self.vgw_VfModuleModelInvariantUuid = '26d6a718-17b2-4ba8-8691-c44343b2ecd2'
79 # CHANGEME: 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
80 self.sdnc_oam_ip = self.get_pod_node_oam_ip('sdnc-sdnc-0')
81 # CHANGEME: OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
82 self.oom_so_sdnc_aai_ip = self.get_pod_node_public_ip('sdnc-sdnc-0')
83 # CHANGEME: OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
84 self.oom_dcae_ves_collector = self.oom_so_sdnc_aai_ip
85 # CHANGEME: OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
86 self.mr_ip_addr = self.oom_so_sdnc_aai_ip
87 self.mr_ip_port = '30227'
88 self.so_nbi_port = '30277' if self.oom_mode else '8080'
89 self.sdnc_preloading_port = '30202' if self.oom_mode else '8282'
90 self.aai_query_port = '30233' if self.oom_mode else '8443'
91 self.sniro_port = '30288' if self.oom_mode else '8080'
93 self.host_names = ['sdc', 'so', 'sdnc', 'robot', 'aai-inst1', self.dcae_ves_collector_name]
95 self.host_names.extend(extra_host_names)
97 self.hosts = self.get_vm_ip(self.host_names, self.external_net_addr, self.external_net_prefix_len)
98 # this is the keyword used to name vgw stack, must not be used in other stacks
99 self.vgw_name_keyword = 'base_vcpe_vgw'
100 # this is the file that will keep the index of last assigned SO name
101 self.vgw_vfmod_name_index_file= '__var/vgw_vfmod_name_index'
102 self.svc_instance_uuid_file = '__var/svc_instance_uuid'
103 self.preload_dict_file = '__var/preload_dict'
104 self.vgmux_vnf_name_file = '__var/vgmux_vnf_name'
105 self.product_family_id = 'f9457e8c-4afd-45da-9389-46acd9bf5116'
106 self.custom_product_family_id = 'a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb'
107 self.instance_name_prefix = {
108 'service': 'vcpe_svc',
109 'network': 'vcpe_net',
111 'vfmodule': 'vcpe_vfmodule'
113 self.aai_userpass = 'AAI', 'AAI'
114 self.pub_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKXDgoo3+WOqcUG8/5uUbk81+yczgwC4Y8ywTmuQqbNxlY1oQ0YxdMUqUnhitSXs5S/yRuAVOYHwGg2mCs20oAINrP+mxBI544AMIb9itPjCtgqtE2EWo6MmnFGbHB4Sx3XioE7F4VPsh7japsIwzOjbrQe+Mua1TGQ5d4nfEOQaaglXLLPFfuc7WbhbJbK6Q7rHqZfRcOwAMXgDoBqlyqKeiKwnumddo2RyNT8ljYmvB6buz7KnMinzo7qB0uktVT05FH9Rg0CTWH5norlG5qXgP2aukL0gk1ph8iAt7uYLf1ktp+LJI2gaF6L0/qli9EmVCSLr1uJ38Q8CBflhkh'
115 self.os_tenant_id = self.cloud['--os-tenant-id']
116 self.os_region_name = self.cloud['--os-region-name']
117 self.common_preload_config['pub_key'] = self.pub_key
118 self.sniro_url = 'http://' + self.hosts['robot'] + ':' + self.sniro_port + '/__admin/mappings'
119 self.sniro_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
120 self.homing_solution = 'sniro' # value is either 'sniro' or 'oof'
121 # self.homing_solution = 'oof'
122 self.customer_location_used_by_oof = {
123 "customerLatitude": "32.897480",
124 "customerLongitude": "-97.040443",
125 "customerName": "some_company"
128 #############################################################################################
130 self.sdc_be_port = '30205'
131 self.sdc_be_request_userpass = 'vid', 'Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
132 self.sdc_be_request_headers = {'X-ECOMP-InstanceID': 'VID'}
133 self.sdc_be_url_prefix = 'http://' + self.hosts['sdc'] + ':' + self.sdc_be_port
134 self.sdc_service_list_url = self.sdc_be_url_prefix + '/sdc/v1/catalog/services'
136 self.sdc_fe_port = '30206'
137 self.sdc_fe_request_userpass = 'beep', 'boop'
138 self.sdc_fe_request_headers = {'USER_ID': 'demo', 'Content-Type': 'application/json'}
139 self.sdc_fe_url_prefix = 'http://' + self.hosts['sdc'] + ':' + self.sdc_fe_port
140 self.sdc_get_category_list_url = self.sdc_fe_url_prefix + '/sdc1/feProxy/rest/v1/categories'
141 self.sdc_create_allotted_resource_subcategory_url = self.sdc_fe_url_prefix + '/sdc1/feProxy/rest/v1/category/resources/resourceNewCategory.allotted%20resource/subCategory'
143 #############################################################################################
145 self.sdnc_userpass = 'admin', 'Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
146 self.sdnc_db_name = 'sdnctl'
147 self.sdnc_db_user = 'sdnctl'
148 self.sdnc_db_pass = 'gamma'
149 self.sdnc_db_port = '32774'
150 self.sdnc_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
151 self.sdnc_preload_network_url = 'http://' + self.hosts['sdnc'] + \
152 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-network-topology-operation'
153 self.sdnc_preload_vnf_url = 'http://' + self.hosts['sdnc'] + \
154 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-vnf-topology-operation'
155 self.sdnc_preload_gra_url = 'http://' + self.hosts['sdnc'] + \
156 ':' + self.sdnc_preloading_port + '/restconf/operations/GENERIC-RESOURCE-API:preload-vf-module-topology-operation'
157 self.sdnc_ar_cleanup_url = 'http://' + self.hosts['sdnc'] + ':' + self.sdnc_preloading_port + \
158 '/restconf/config/GENERIC-RESOURCE-API:'
160 #############################################################################################
161 # SO urls, note: do NOT add a '/' at the end of the url
162 self.so_req_api_url = {'v4': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/serviceInstantiation/v7/serviceInstances',
163 'v5': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/serviceInstantiation/v7/serviceInstances'}
164 self.so_check_progress_api_url = 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/orchestrationRequests/v6'
165 self.so_userpass = 'InfraPortalClient', 'password1$'
166 self.so_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
167 self.so_db_name = 'catalogdb'
168 self.so_db_user = 'root'
169 self.so_db_pass = 'secretpassword'
170 self.so_db_port = '30252' if self.oom_mode else '32769'
172 self.vpp_inf_url = 'http://{0}:8183/restconf/config/ietf-interfaces:interfaces'
173 self.vpp_api_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
174 self.vpp_api_userpass = ('admin', 'admin')
175 self.vpp_ves_url= 'http://{0}:8183/restconf/config/vesagent:vesagent'
177 def headbridge(self, openstack_stack_name, svc_instance_uuid):
179 Add vserver information to AAI
181 self.logger.info('Adding vServer information to AAI for {0}'.format(openstack_stack_name))
182 if not self.oom_mode:
183 cmd = '/opt/demo.sh heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid)
184 ret = commands.getstatusoutput("ssh -i onap_dev root@{0} '{1}'".format(self.hosts['robot'], cmd))
185 self.logger.debug('%s', ret)
187 print('To add vGMUX vserver info to AAI, do the following:')
188 print('- ssh to rancher')
190 print('- cd /root/oom/kubernetes/robot')
191 print('- ./demo-k8s.sh onap heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid))
193 def get_brg_mac_from_sdnc(self):
195 Check table DHCP_MAP in the SDNC DB. Find the newly instantiated BRG MAC address.
196 Note that there might be multiple BRGs, the most recently instantiated BRG always has the largest IP address.
198 cnx = mysql.connector.connect(user=self.sdnc_db_user, password=self.sdnc_db_pass, database=self.sdnc_db_name,
199 host=self.hosts['sdnc'], port=self.sdnc_db_port)
200 cursor = cnx.cursor()
201 query = "SELECT * from DHCP_MAP"
202 cursor.execute(query)
204 self.logger.debug('DHCP_MAP table in SDNC')
207 for mac, ip in cursor:
208 self.logger.debug(mac + ':' + ip)
209 this_host = int(ip.split('.')[-1])
219 def execute_cmds_sdnc_db(self, cmds):
220 self.execute_cmds_db(cmds, self.sdnc_db_user, self.sdnc_db_pass, self.sdnc_db_name,
221 self.hosts['sdnc'], self.sdnc_db_port)
223 def execute_cmds_so_db(self, cmds):
224 self.execute_cmds_db(cmds, self.so_db_user, self.so_db_pass, self.so_db_name,
225 self.hosts['so'], self.so_db_port)
227 def execute_cmds_db(self, cmds, dbuser, dbpass, dbname, host, port):
228 cnx = mysql.connector.connect(user=dbuser, password=dbpass, database=dbname, host=host, port=port)
229 cursor = cnx.cursor()
231 self.logger.debug(cmd)
233 self.logger.debug('%s', cursor)
238 def find_file(self, file_name_keyword, file_ext, search_dir):
240 :param file_name_keyword: keyword used to look for the csar file, case insensitive matching, e.g, infra
241 :param file_ext: e.g., csar, json
242 :param search_dir path to search
243 :return: path name of the file
245 file_name_keyword = file_name_keyword.lower()
246 file_ext = file_ext.lower()
247 if not file_ext.startswith('.'):
248 file_ext = '.' + file_ext
251 for file_name in os.listdir(search_dir):
252 file_name_lower = file_name.lower()
253 if file_name_keyword in file_name_lower and file_name_lower.endswith(file_ext):
255 self.logger.error('Multiple files found for *{0}*.{1} in '
256 'directory {2}'.format(file_name_keyword, file_ext, search_dir))
258 filenamepath = os.path.abspath(os.path.join(search_dir, file_name))
263 self.logger.error("Cannot find *{0}*{1} in directory {2}".format(file_name_keyword, file_ext, search_dir))
267 def network_name_to_subnet_name(network_name):
269 :param network_name: example: vcpe_net_cpe_signal_201711281221
270 :return: vcpe_net_cpe_signal_subnet_201711281221
272 fields = network_name.split('_')
273 fields.insert(-1, 'subnet')
274 return '_'.join(fields)
276 def set_network_name(self, network_name):
277 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
278 openstackcmd = 'openstack ' + param
279 cmd = ' '.join([openstackcmd, 'network set --name', network_name, 'ONAP-NW1'])
282 def set_subnet_name(self, network_name):
284 Example: network_name = vcpe_net_cpe_signal_201711281221
285 set subnet name to vcpe_net_cpe_signal_subnet_201711281221
288 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
289 openstackcmd = 'openstack ' + param
291 # expected results: | subnets | subnet_id |
292 subnet_info = os.popen(openstackcmd + ' network show ' + network_name + ' |grep subnets').read().split('|')
293 if len(subnet_info) > 2 and subnet_info[1].strip() == 'subnets':
294 subnet_id = subnet_info[2].strip()
295 subnet_name = self.network_name_to_subnet_name(network_name)
296 cmd = ' '.join([openstackcmd, 'subnet set --name', subnet_name, subnet_id])
298 self.logger.info("Subnet name set to: " + subnet_name)
301 self.logger.error("Can't get subnet info from network name: " + network_name)
304 def is_node_in_aai(self, node_type, node_uuid):
306 search_node_type = None
307 if node_type == 'service':
308 search_node_type = 'service-instance'
309 key = 'service-instance-id'
310 elif node_type == 'vnf':
311 search_node_type = 'generic-vnf'
314 logging.error('Invalid node_type: ' + node_type)
317 url = 'https://{0}:{1}/aai/v11/search/nodes-query?search-node-type={2}&filter={3}:EQUALS:{4}'.format(
318 self.hosts['aai-inst1'], self.aai_query_port, search_node_type, key, node_uuid)
320 headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-FromAppID': 'vCPE-Robot', 'X-TransactionId': 'get_aai_subscr'}
321 requests.packages.urllib3.disable_warnings()
322 r = requests.get(url, headers=headers, auth=self.aai_userpass, verify=False)
324 self.logger.debug('aai query: ' + url)
325 self.logger.debug('aai response:\n' + json.dumps(response, indent=4, sort_keys=True))
326 return 'result-data' in response
329 def extract_ip_from_str(net_addr, net_addr_len, sz):
331 :param net_addr: e.g. 10.5.12.0
332 :param net_addr_len: e.g. 24
334 :return: the first IP address matching the network, e.g. 10.5.12.3
336 network = ipaddress.ip_network(unicode('{0}/{1}'.format(net_addr, net_addr_len)), strict=False)
337 ip_list = re.findall(r'[0-9]+(?:\.[0-9]+){3}', sz)
339 this_net = ipaddress.ip_network(unicode('{0}/{1}'.format(ip, net_addr_len)), strict=False)
340 if this_net == network:
344 def get_pod_node_oam_ip(self, pod):
346 :Assuming kubectl is available and configured by default config (~/.kube/config)
347 :param pod: pod name substring, e.g. 'sdnc-sdnc-0'
348 :return pod's cluster node oam ip (10.0.0.0/16)
351 config.load_kube_config()
352 api = client.CoreV1Api()
353 kslogger = logging.getLogger('kubernetes')
354 kslogger.setLevel(logging.INFO)
355 res = api.list_pod_for_all_namespaces()
357 if pod in i.metadata.name:
358 self.logger.debug("found {0}\t{1}\t{2}".format(i.metadata.name, i.status.host_ip, i.spec.node_name))
359 ret = i.status.host_ip
363 ret = raw_input("Enter sdnc-sdnc-0 pod cluster node OAM IP address(10.0.0.0/16): ")
366 def get_pod_node_public_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 public ip (i.e. 10.12.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 ret = self.get_vm_public_ip_by_nova(i.spec.node_name)
381 self.logger.debug("found node {0} public ip: {1}".format(i.spec.node_name, ret))
385 ret = raw_input("Enter sdnc-sdnc-0 pod cluster node public IP address(i.e. 10.12.0.0/16): ")
388 def get_vm_public_ip_by_nova(self, vm):
390 This method uses openstack nova api to retrieve vm public ip
394 subnet = IPNetwork('{0}/{1}'.format(self.external_net_addr, self.external_net_prefix_len))
395 nova = openstackclient.Client(2, self.cloud['--os-username'], self.cloud['--os-password'], self.cloud['--os-tenant-id'], self.cloud['--os-auth-url'])
396 for i in nova.servers.list():
398 for k, v in i.networks.items():
400 if IPAddress(ip) in subnet:
404 def get_vm_ip(self, keywords, net_addr=None, net_addr_len=None):
406 :param keywords: list of keywords to search for vm, e.g. ['bng', 'gmux', 'brg']
407 :param net_addr: e.g. 10.12.5.0
408 :param net_addr_len: e.g. 24
409 :return: dictionary {keyword: ip}
412 net_addr = self.external_net_addr
415 net_addr_len = self.external_net_prefix_len
417 param = ' '.join([k + ' ' + v for k, v in self.cloud.items() if 'identity' not in k])
418 openstackcmd = 'nova ' + param + ' list'
419 self.logger.debug(openstackcmd)
421 results = os.popen(openstackcmd).read()
422 all_vm_ip_dict = self.extract_vm_ip_as_dict(results, net_addr, net_addr_len)
423 latest_vm_list = self.remove_old_vms(all_vm_ip_dict.keys(), self.cpe_vm_prefix)
424 latest_vm_ip_dict = {vm: all_vm_ip_dict[vm] for vm in latest_vm_list}
425 ip_dict = self.select_subset_vm_ip(latest_vm_ip_dict, keywords)
427 ip_dict.update(self.get_oom_onap_vm_ip(keywords))
429 if len(ip_dict) != len(keywords):
430 self.logger.error('Cannot find all desired IP addresses for %s.', keywords)
431 self.logger.error(json.dumps(ip_dict, indent=4, sort_keys=True))
432 self.logger.error('Temporarily continue.. remember to check back vcpecommon.py line: 396')
436 def get_oom_onap_vm_ip(self, keywords):
438 onap_vm_list = set(['sdc', 'so', 'sdnc', 'aai-inst1', 'robot', self.dcae_ves_collector_name])
440 if vm in onap_vm_list:
441 vm_ip[vm] = self.oom_so_sdnc_aai_ip
444 def extract_vm_ip_as_dict(self, novalist_results, net_addr, net_addr_len):
446 for line in novalist_results.split('\n'):
447 fields = line.split('|')
451 ip = self.extract_ip_from_str(net_addr, net_addr_len, ip_info)
452 vm_ip_dict[vm_name] = ip
456 def remove_old_vms(self, vm_list, prefix):
458 For vms with format name_timestamp, only keep the one with the latest timestamp.
460 zdcpe1cpe01brgemu01_201805222148 (drop this)
461 zdcpe1cpe01brgemu01_201805222229 (keep this)
462 zdcpe1cpe01gw01_201805162201
465 same_type_vm_dict = {}
467 fields = vm.split('_')
468 if vm.startswith(prefix) and len(fields) == 2 and len(fields[-1]) == len('201805222148') and fields[-1].isdigit():
469 if vm > same_type_vm_dict.get(fields[0], '0'):
470 same_type_vm_dict[fields[0]] = vm
472 new_vm_list.append(vm)
474 new_vm_list.extend(same_type_vm_dict.values())
477 def select_subset_vm_ip(self, all_vm_ip_dict, vm_name_keyword_list):
479 for keyword in vm_name_keyword_list:
480 for vm, ip in all_vm_ip_dict.items():
482 vm_ip_dict[keyword] = ip
486 def del_vgmux_ves_mode(self):
487 url = self.vpp_ves_url.format(self.hosts['mux']) + '/mode'
488 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
489 self.logger.debug('%s', r)
491 def del_vgmux_ves_collector(self):
492 url = self.vpp_ves_url.format(self.hosts['mux']) + '/config'
493 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
494 self.logger.debug('%s', r)
496 def set_vgmux_ves_collector(self ):
497 url = self.vpp_ves_url.format(self.hosts['mux'])
499 {'server-addr': self.hosts[self.dcae_ves_collector_name],
500 'server-port': '30235' if self.oom_mode else '8081',
501 'read-interval': '10',
505 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
506 self.logger.debug('%s', r)
508 def set_vgmux_packet_loss_rate(self, lossrate, vg_vnf_instance_name):
509 url = self.vpp_ves_url.format(self.hosts['mux'])
511 {"working-mode": "demo",
512 "base-packet-loss": str(lossrate),
513 "source-name": vg_vnf_instance_name
516 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
517 self.logger.debug('%s', r)
519 # return all the VxLAN interface names of BRG or vGMUX based on the IP address
520 def get_vxlan_interfaces(self, ip, print_info=False):
521 url = self.vpp_inf_url.format(ip)
522 self.logger.debug('url is this: %s', url)
523 r = requests.get(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
524 data = r.json()['interfaces']['interface']
527 if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel':
528 print(json.dumps(inf, indent=4, sort_keys=True))
530 return [inf['name'] for inf in data if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel']
532 # delete all VxLAN interfaces of each hosts
533 def delete_vxlan_interfaces(self, host_dic):
534 for host, ip in host_dic.items():
536 self.logger.info('{0}: Getting VxLAN interfaces'.format(host))
537 inf_list = self.get_vxlan_interfaces(ip)
541 self.logger.info("{0}: Deleting VxLAN crossconnect {1}".format(host, inf))
542 url = self.vpp_inf_url.format(ip) + '/interface/' + inf + '/v3po:l2'
543 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
548 self.logger.info("{0}: Deleting VxLAN interface {1}".format(host, inf))
549 url = self.vpp_inf_url.format(ip) + '/interface/' + inf
550 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
552 if len(self.get_vxlan_interfaces(ip)) > 0:
553 self.logger.error("Error deleting VxLAN from {0}, try to restart the VM, IP is {1}.".format(host, ip))
557 self.logger.info("{0}: no VxLAN interface found, nothing to delete".format(host))
561 def save_object(obj, filepathname):
562 with open(filepathname, 'wb') as fout:
563 pickle.dump(obj, fout)
566 def load_object(filepathname):
567 with open(filepathname, 'rb') as fin:
568 return pickle.load(fin)
571 def increase_ip_address_or_vni_in_template(vnf_template_file, vnf_parameter_name_list):
572 with open(vnf_template_file) as json_input:
573 json_data = json.load(json_input)
574 param_list = json_data['VNF-API:input']['VNF-API:vnf-topology-information']['VNF-API:vnf-parameters']
575 for param in param_list:
576 if param['vnf-parameter-name'] in vnf_parameter_name_list:
577 ipaddr_or_vni = param['vnf-parameter-value'].split('.')
578 number = int(ipaddr_or_vni[-1])
583 ipaddr_or_vni[-1] = str(number)
584 param['vnf-parameter-value'] = '.'.join(ipaddr_or_vni)
586 assert json_data is not None
587 with open(vnf_template_file, 'w') as json_output:
588 json.dump(json_data, json_output, indent=4, sort_keys=True)
590 def save_preload_data(self, preload_data):
591 self.save_object(preload_data, self.preload_dict_file)
593 def load_preload_data(self):
594 return self.load_object(self.preload_dict_file)
596 def save_vgmux_vnf_name(self, vgmux_vnf_name):
597 self.save_object(vgmux_vnf_name, self.vgmux_vnf_name_file)
599 def load_vgmux_vnf_name(self):
600 return self.load_object(self.vgmux_vnf_name_file)