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
20 external_net_addr = '10.12.0.0'
21 external_net_prefix_len = 16
22 #############################################################################################
23 # set the openstack cloud access credentials here
27 '--os-auth-url': 'http://10.12.25.2:5000',
28 '--os-username': 'kxi',
29 '--os-user-domain-id': 'default',
30 '--os-project-domain-id': 'default',
31 '--os-tenant-id': 'bc43d50ffcb84750bac0c1707a9a765b' if oom_mode else '1e097c6713e74fd7ac8e4295e605ee1e',
32 '--os-region-name': 'RegionOne',
33 '--os-password': 'n3JhGMGuDzD8',
34 '--os-project-domain-name': 'Integration-SB-03' if oom_mode else 'Integration-SB-07',
35 '--os-identity-api-version': '3'
38 common_preload_config = {
39 'oam_onap_net': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
40 'oam_onap_subnet': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
41 'public_net': 'external',
42 'public_net_id': '971040b2-7059-49dc-b220-4fab50cb2ad4'
44 sdnc_controller_pod = 'dev-sdnc-sdnc-0'
46 #############################################################################################
48 template_variable_symbol = '${'
49 cpe_vm_prefix = 'zdcpe'
50 #############################################################################################
51 # preloading network config
53 # value = [subnet_start_ip, subnet_gateway_ip]
54 preload_network_config = {
55 'cpe_public': ['10.2.0.2', '10.2.0.1'],
56 'cpe_signal': ['10.4.0.2', '10.4.0.1'],
57 'brg_bng': ['10.3.0.2', '10.3.0.1'],
58 'bng_mux': ['10.1.0.10', '10.1.0.1'],
59 'mux_gw': ['10.5.0.10', '10.5.0.1']
62 dcae_ves_collector_name = 'dcae-bootstrap'
63 global_subscriber_id = 'SDN-ETHERNET-INTERNET'
64 project_name = 'Project-Demonstration'
65 owning_entity_id = '520cc603-a3c4-4ec2-9ef4-ca70facd79c0'
66 owning_entity_name = 'OE-Demonstration1'
68 def __init__(self, extra_host_names=None):
69 rootlogger = logging.getLogger()
70 handler = logging.StreamHandler()
71 formatter = logging.Formatter('%(asctime)s %(levelname)s %(name)s.%(funcName)s(): %(message)s')
72 handler.setFormatter(formatter)
73 rootlogger.addHandler(handler)
74 rootlogger.setLevel(logging.INFO)
76 self.logger = logging.getLogger(__name__)
77 self.logger.propagate = False
78 self.logger.addHandler(handler)
79 self.logger.setLevel(logging.DEBUG)
80 self.logger.info('Initializing configuration')
82 # CHANGEME: vgw_VfModuleModelInvariantUuid is in rescust service csar, look in service-VcpesvcRescust1118-template.yml for groups vgw module metadata. TODO: read this value automcatically
83 self.vgw_VfModuleModelInvariantUuid = '26d6a718-17b2-4ba8-8691-c44343b2ecd2'
84 # 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
85 self.sdnc_oam_ip = self.get_pod_node_oam_ip('sdnc-sdnc-0')
86 # CHANGEME: OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
87 self.oom_so_sdnc_aai_ip = self.get_pod_node_public_ip('sdnc-sdnc-0')
88 # CHANGEME: OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
89 self.oom_dcae_ves_collector = self.oom_so_sdnc_aai_ip
90 # CHANGEME: OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
91 self.mr_ip_addr = self.oom_so_sdnc_aai_ip
92 self.mr_ip_port = '30227'
93 self.so_nbi_port = '30277' if self.oom_mode else '8080'
94 self.sdnc_preloading_port = '30202' if self.oom_mode else '8282'
95 self.aai_query_port = '30233' if self.oom_mode else '8443'
96 self.sniro_port = '30288' if self.oom_mode else '8080'
98 self.host_names = ['sdc', 'so', 'sdnc', 'robot', 'aai-inst1', self.dcae_ves_collector_name]
100 self.host_names.extend(extra_host_names)
102 self.hosts = self.get_vm_ip(self.host_names, self.external_net_addr, self.external_net_prefix_len)
103 # this is the keyword used to name vgw stack, must not be used in other stacks
104 self.vgw_name_keyword = 'base_vcpe_vgw'
105 # this is the file that will keep the index of last assigned SO name
106 self.vgw_vfmod_name_index_file= '__var/vgw_vfmod_name_index'
107 self.svc_instance_uuid_file = '__var/svc_instance_uuid'
108 self.preload_dict_file = '__var/preload_dict'
109 self.vgmux_vnf_name_file = '__var/vgmux_vnf_name'
110 self.product_family_id = 'f9457e8c-4afd-45da-9389-46acd9bf5116'
111 self.custom_product_family_id = 'a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb'
112 self.instance_name_prefix = {
113 'service': 'vcpe_svc',
114 'network': 'vcpe_net',
116 'vfmodule': 'vcpe_vfmodule'
118 self.aai_userpass = 'AAI', 'AAI'
119 self.pub_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKXDgoo3+WOqcUG8/5uUbk81+yczgwC4Y8ywTmuQqbNxlY1oQ0YxdMUqUnhitSXs5S/yRuAVOYHwGg2mCs20oAINrP+mxBI544AMIb9itPjCtgqtE2EWo6MmnFGbHB4Sx3XioE7F4VPsh7japsIwzOjbrQe+Mua1TGQ5d4nfEOQaaglXLLPFfuc7WbhbJbK6Q7rHqZfRcOwAMXgDoBqlyqKeiKwnumddo2RyNT8ljYmvB6buz7KnMinzo7qB0uktVT05FH9Rg0CTWH5norlG5qXgP2aukL0gk1ph8iAt7uYLf1ktp+LJI2gaF6L0/qli9EmVCSLr1uJ38Q8CBflhkh'
120 self.os_tenant_id = self.cloud['--os-tenant-id']
121 self.os_region_name = self.cloud['--os-region-name']
122 self.common_preload_config['pub_key'] = self.pub_key
123 self.sniro_url = 'http://' + self.hosts['robot'] + ':' + self.sniro_port + '/__admin/mappings'
124 self.sniro_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
125 self.homing_solution = 'sniro' # value is either 'sniro' or 'oof'
126 # self.homing_solution = 'oof'
127 self.customer_location_used_by_oof = {
128 "customerLatitude": "32.897480",
129 "customerLongitude": "-97.040443",
130 "customerName": "some_company"
133 #############################################################################################
135 self.sdc_get_request_userpass = 'vid','Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
136 self.sdc_get_request_headers = {'X-ECOMP-InstanceID': 'VID'}
137 self.sdc_port = '30205'
138 self.sdc_url_prefix = 'http://' + self.hosts['sdc'] + ':' + self.sdc_port
139 self.sdc_service_list_url = self.sdc_url_prefix + '/sdc/v1/catalog/services'
141 #############################################################################################
143 self.sdnc_userpass = 'admin', 'Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
144 self.sdnc_db_name = 'sdnctl'
145 self.sdnc_db_user = 'sdnctl'
146 self.sdnc_db_pass = 'gamma'
147 self.sdnc_db_port = '32774'
148 self.sdnc_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
149 self.sdnc_preload_network_url = 'http://' + self.hosts['sdnc'] + \
150 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-network-topology-operation'
151 self.sdnc_preload_vnf_url = 'http://' + self.hosts['sdnc'] + \
152 ':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-vnf-topology-operation'
153 self.sdnc_preload_gra_url = 'http://' + self.hosts['sdnc'] + \
154 ':' + self.sdnc_preloading_port + '/restconf/operations/GENERIC-RESOURCE-API:preload-vf-module-topology-operation'
155 self.sdnc_ar_cleanup_url = 'http://' + self.hosts['sdnc'] + ':' + self.sdnc_preloading_port + \
156 '/restconf/config/GENERIC-RESOURCE-API:'
158 #############################################################################################
159 # SO urls, note: do NOT add a '/' at the end of the url
160 self.so_req_api_url = {'v4': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/serviceInstantiation/v7/serviceInstances',
161 'v5': 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/serviceInstantiation/v7/serviceInstances'}
162 self.so_check_progress_api_url = 'http://' + self.hosts['so'] + ':' + self.so_nbi_port + '/onap/so/infra/orchestrationRequests/v6'
163 self.so_userpass = 'InfraPortalClient', 'password1$'
164 self.so_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
165 self.so_db_name = 'catalogdb'
166 self.so_db_user = 'root'
167 self.so_db_pass = 'password'
168 self.so_db_port = '30252' if self.oom_mode else '32769'
170 self.vpp_inf_url = 'http://{0}:8183/restconf/config/ietf-interfaces:interfaces'
171 self.vpp_api_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
172 self.vpp_api_userpass = ('admin', 'admin')
173 self.vpp_ves_url= 'http://{0}:8183/restconf/config/vesagent:vesagent'
175 def headbridge(self, openstack_stack_name, svc_instance_uuid):
177 Add vserver information to AAI
179 self.logger.info('Adding vServer information to AAI for {0}'.format(openstack_stack_name))
180 if not self.oom_mode:
181 cmd = '/opt/demo.sh heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid)
182 ret = commands.getstatusoutput("ssh -i onap_dev root@{0} '{1}'".format(self.hosts['robot'], cmd))
183 self.logger.debug('%s', ret)
185 print('To add vGMUX vserver info to AAI, do the following:')
186 print('- ssh to rancher')
188 print('- cd /root/oom/kubernetes/robot')
189 print('- ./demo-k8s.sh onap heatbridge {0} {1} vCPE'.format(openstack_stack_name, svc_instance_uuid))
191 def get_brg_mac_from_sdnc(self):
193 Check table DHCP_MAP in the SDNC DB. Find the newly instantiated BRG MAC address.
194 Note that there might be multiple BRGs, the most recently instantiated BRG always has the largest IP address.
196 cnx = mysql.connector.connect(user=self.sdnc_db_user, password=self.sdnc_db_pass, database=self.sdnc_db_name,
197 host=self.hosts['sdnc'], port=self.sdnc_db_port)
198 cursor = cnx.cursor()
199 query = "SELECT * from DHCP_MAP"
200 cursor.execute(query)
202 self.logger.debug('DHCP_MAP table in SDNC')
205 for mac, ip in cursor:
206 self.logger.debug(mac + ':' + ip)
207 this_host = int(ip.split('.')[-1])
217 def execute_cmds_sdnc_db(self, cmds):
218 self.execute_cmds_db(cmds, self.sdnc_db_user, self.sdnc_db_pass, self.sdnc_db_name,
219 self.hosts['sdnc'], self.sdnc_db_port)
221 def execute_cmds_so_db(self, cmds):
222 self.execute_cmds_db(cmds, self.so_db_user, self.so_db_pass, self.so_db_name,
223 self.hosts['so'], self.so_db_port)
225 def execute_cmds_db(self, cmds, dbuser, dbpass, dbname, host, port):
226 cnx = mysql.connector.connect(user=dbuser, password=dbpass, database=dbname, host=host, port=port)
227 cursor = cnx.cursor()
229 self.logger.debug(cmd)
231 self.logger.debug('%s', cursor)
236 def find_file(self, file_name_keyword, file_ext, search_dir):
238 :param file_name_keyword: keyword used to look for the csar file, case insensitive matching, e.g, infra
239 :param file_ext: e.g., csar, json
240 :param search_dir path to search
241 :return: path name of the file
243 file_name_keyword = file_name_keyword.lower()
244 file_ext = file_ext.lower()
245 if not file_ext.startswith('.'):
246 file_ext = '.' + file_ext
249 for file_name in os.listdir(search_dir):
250 file_name_lower = file_name.lower()
251 if file_name_keyword in file_name_lower and file_name_lower.endswith(file_ext):
253 self.logger.error('Multiple files found for *{0}*.{1} in '
254 'directory {2}'.format(file_name_keyword, file_ext, search_dir))
256 filenamepath = os.path.abspath(os.path.join(search_dir, file_name))
261 self.logger.error("Cannot find *{0}*{1} in directory {2}".format(file_name_keyword, file_ext, search_dir))
265 def network_name_to_subnet_name(network_name):
267 :param network_name: example: vcpe_net_cpe_signal_201711281221
268 :return: vcpe_net_cpe_signal_subnet_201711281221
270 fields = network_name.split('_')
271 fields.insert(-1, 'subnet')
272 return '_'.join(fields)
274 def set_network_name(self, network_name):
275 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
276 openstackcmd = 'openstack ' + param
277 cmd = ' '.join([openstackcmd, 'network set --name', network_name, 'ONAP-NW1'])
280 def set_subnet_name(self, network_name):
282 Example: network_name = vcpe_net_cpe_signal_201711281221
283 set subnet name to vcpe_net_cpe_signal_subnet_201711281221
286 param = ' '.join([k + ' ' + v for k, v in self.cloud.items()])
287 openstackcmd = 'openstack ' + param
289 # expected results: | subnets | subnet_id |
290 subnet_info = os.popen(openstackcmd + ' network show ' + network_name + ' |grep subnets').read().split('|')
291 if len(subnet_info) > 2 and subnet_info[1].strip() == 'subnets':
292 subnet_id = subnet_info[2].strip()
293 subnet_name = self.network_name_to_subnet_name(network_name)
294 cmd = ' '.join([openstackcmd, 'subnet set --name', subnet_name, subnet_id])
296 self.logger.info("Subnet name set to: " + subnet_name)
299 self.logger.error("Can't get subnet info from network name: " + network_name)
302 def is_node_in_aai(self, node_type, node_uuid):
304 search_node_type = None
305 if node_type == 'service':
306 search_node_type = 'service-instance'
307 key = 'service-instance-id'
308 elif node_type == 'vnf':
309 search_node_type = 'generic-vnf'
312 logging.error('Invalid node_type: ' + node_type)
315 url = 'https://{0}:{1}/aai/v11/search/nodes-query?search-node-type={2}&filter={3}:EQUALS:{4}'.format(
316 self.hosts['aai-inst1'], self.aai_query_port, search_node_type, key, node_uuid)
318 headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-FromAppID': 'vCPE-Robot', 'X-TransactionId': 'get_aai_subscr'}
319 requests.packages.urllib3.disable_warnings()
320 r = requests.get(url, headers=headers, auth=self.aai_userpass, verify=False)
322 self.logger.debug('aai query: ' + url)
323 self.logger.debug('aai response:\n' + json.dumps(response, indent=4, sort_keys=True))
324 return 'result-data' in response
327 def extract_ip_from_str(net_addr, net_addr_len, sz):
329 :param net_addr: e.g. 10.5.12.0
330 :param net_addr_len: e.g. 24
332 :return: the first IP address matching the network, e.g. 10.5.12.3
334 network = ipaddress.ip_network(unicode('{0}/{1}'.format(net_addr, net_addr_len)), strict=False)
335 ip_list = re.findall(r'[0-9]+(?:\.[0-9]+){3}', sz)
337 this_net = ipaddress.ip_network(unicode('{0}/{1}'.format(ip, net_addr_len)), strict=False)
338 if this_net == network:
342 def get_pod_node_oam_ip(self, pod):
344 :Assuming kubectl is available and configured by default config (~/.kube/config)
345 :param pod: pod name substring, e.g. 'sdnc-sdnc-0'
346 :return pod's cluster node oam ip (10.0.0.0/16)
349 config.load_kube_config()
350 api = client.CoreV1Api()
351 kslogger = logging.getLogger('kubernetes')
352 kslogger.setLevel(logging.INFO)
353 res = api.list_pod_for_all_namespaces()
355 if pod in i.metadata.name:
356 self.logger.debug("found {0}\t{1}\t{2}".format(i.metadata.name, i.status.host_ip, i.spec.node_name))
357 ret = i.status.host_ip
361 ret = raw_input("Enter sdnc-sdnc-0 pod cluster node OAM IP address(10.0.0.0/16): ")
364 def get_pod_node_public_ip(self, pod):
366 :Assuming kubectl is available and configured by default config (~/.kube/config)
367 :param pod: pod name substring, e.g. 'sdnc-sdnc-0'
368 :return pod's cluster node public ip (i.e. 10.12.0.0/16)
371 config.load_kube_config()
372 api = client.CoreV1Api()
373 kslogger = logging.getLogger('kubernetes')
374 kslogger.setLevel(logging.INFO)
375 res = api.list_pod_for_all_namespaces()
377 if pod in i.metadata.name:
378 ret = self.get_vm_public_ip_by_nova(i.spec.node_name)
379 self.logger.debug("found node {0} public ip: {1}".format(i.spec.node_name, ret))
383 ret = raw_input("Enter sdnc-sdnc-0 pod cluster node public IP address(i.e. 10.12.0.0/16): ")
386 def get_vm_public_ip_by_nova(self, vm):
388 This method uses openstack nova api to retrieve vm public ip
392 subnet = IPNetwork('{0}/{1}'.format(self.external_net_addr, self.external_net_prefix_len))
393 nova = openstackclient.Client(2, self.cloud['--os-username'], self.cloud['--os-password'], self.cloud['--os-tenant-id'], self.cloud['--os-auth-url'])
394 for i in nova.servers.list():
396 for k, v in i.networks.items():
398 if IPAddress(ip) in subnet:
402 def get_vm_ip(self, keywords, net_addr=None, net_addr_len=None):
404 :param keywords: list of keywords to search for vm, e.g. ['bng', 'gmux', 'brg']
405 :param net_addr: e.g. 10.12.5.0
406 :param net_addr_len: e.g. 24
407 :return: dictionary {keyword: ip}
410 net_addr = self.external_net_addr
413 net_addr_len = self.external_net_prefix_len
415 param = ' '.join([k + ' ' + v for k, v in self.cloud.items() if 'identity' not in k])
416 openstackcmd = 'nova ' + param + ' list'
417 self.logger.debug(openstackcmd)
419 results = os.popen(openstackcmd).read()
420 all_vm_ip_dict = self.extract_vm_ip_as_dict(results, net_addr, net_addr_len)
421 latest_vm_list = self.remove_old_vms(all_vm_ip_dict.keys(), self.cpe_vm_prefix)
422 latest_vm_ip_dict = {vm: all_vm_ip_dict[vm] for vm in latest_vm_list}
423 ip_dict = self.select_subset_vm_ip(latest_vm_ip_dict, keywords)
425 ip_dict.update(self.get_oom_onap_vm_ip(keywords))
427 if len(ip_dict) != len(keywords):
428 self.logger.error('Cannot find all desired IP addresses for %s.', keywords)
429 self.logger.error(json.dumps(ip_dict, indent=4, sort_keys=True))
430 self.logger.error('Temporarily continue.. remember to check back vcpecommon.py line: 396')
434 def get_oom_onap_vm_ip(self, keywords):
436 onap_vm_list = set(['sdc', 'so', 'sdnc', 'aai-inst1', 'robot', self.dcae_ves_collector_name])
438 if vm in onap_vm_list:
439 vm_ip[vm] = self.oom_so_sdnc_aai_ip
442 def extract_vm_ip_as_dict(self, novalist_results, net_addr, net_addr_len):
444 for line in novalist_results.split('\n'):
445 fields = line.split('|')
449 ip = self.extract_ip_from_str(net_addr, net_addr_len, ip_info)
450 vm_ip_dict[vm_name] = ip
454 def remove_old_vms(self, vm_list, prefix):
456 For vms with format name_timestamp, only keep the one with the latest timestamp.
458 zdcpe1cpe01brgemu01_201805222148 (drop this)
459 zdcpe1cpe01brgemu01_201805222229 (keep this)
460 zdcpe1cpe01gw01_201805162201
463 same_type_vm_dict = {}
465 fields = vm.split('_')
466 if vm.startswith(prefix) and len(fields) == 2 and len(fields[-1]) == len('201805222148') and fields[-1].isdigit():
467 if vm > same_type_vm_dict.get(fields[0], '0'):
468 same_type_vm_dict[fields[0]] = vm
470 new_vm_list.append(vm)
472 new_vm_list.extend(same_type_vm_dict.values())
475 def select_subset_vm_ip(self, all_vm_ip_dict, vm_name_keyword_list):
477 for keyword in vm_name_keyword_list:
478 for vm, ip in all_vm_ip_dict.items():
480 vm_ip_dict[keyword] = ip
484 def del_vgmux_ves_mode(self):
485 url = self.vpp_ves_url.format(self.hosts['mux']) + '/mode'
486 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
487 self.logger.debug('%s', r)
489 def del_vgmux_ves_collector(self):
490 url = self.vpp_ves_url.format(self.hosts['mux']) + '/config'
491 r = requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
492 self.logger.debug('%s', r)
494 def set_vgmux_ves_collector(self ):
495 url = self.vpp_ves_url.format(self.hosts['mux'])
497 {'server-addr': self.hosts[self.dcae_ves_collector_name],
498 'server-port': '30235' if self.oom_mode else '8081',
499 'read-interval': '10',
503 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
504 self.logger.debug('%s', r)
506 def set_vgmux_packet_loss_rate(self, lossrate, vg_vnf_instance_name):
507 url = self.vpp_ves_url.format(self.hosts['mux'])
509 {"working-mode": "demo",
510 "base-packet-loss": str(lossrate),
511 "source-name": vg_vnf_instance_name
514 r = requests.post(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass, json=data)
515 self.logger.debug('%s', r)
517 # return all the VxLAN interface names of BRG or vGMUX based on the IP address
518 def get_vxlan_interfaces(self, ip, print_info=False):
519 url = self.vpp_inf_url.format(ip)
520 self.logger.debug('url is this: %s', url)
521 r = requests.get(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
522 data = r.json()['interfaces']['interface']
525 if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel':
526 print(json.dumps(inf, indent=4, sort_keys=True))
528 return [inf['name'] for inf in data if 'name' in inf and 'type' in inf and inf['type'] == 'v3po:vxlan-tunnel']
530 # delete all VxLAN interfaces of each hosts
531 def delete_vxlan_interfaces(self, host_dic):
532 for host, ip in host_dic.items():
534 self.logger.info('{0}: Getting VxLAN interfaces'.format(host))
535 inf_list = self.get_vxlan_interfaces(ip)
539 self.logger.info("{0}: Deleting VxLAN crossconnect {1}".format(host, inf))
540 url = self.vpp_inf_url.format(ip) + '/interface/' + inf + '/v3po:l2'
541 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
546 self.logger.info("{0}: Deleting VxLAN interface {1}".format(host, inf))
547 url = self.vpp_inf_url.format(ip) + '/interface/' + inf
548 requests.delete(url, headers=self.vpp_api_headers, auth=self.vpp_api_userpass)
550 if len(self.get_vxlan_interfaces(ip)) > 0:
551 self.logger.error("Error deleting VxLAN from {0}, try to restart the VM, IP is {1}.".format(host, ip))
555 self.logger.info("{0}: no VxLAN interface found, nothing to delete".format(host))
559 def save_object(obj, filepathname):
560 with open(filepathname, 'wb') as fout:
561 pickle.dump(obj, fout)
564 def load_object(filepathname):
565 with open(filepathname, 'rb') as fin:
566 return pickle.load(fin)
569 def increase_ip_address_or_vni_in_template(vnf_template_file, vnf_parameter_name_list):
570 with open(vnf_template_file) as json_input:
571 json_data = json.load(json_input)
572 param_list = json_data['VNF-API:input']['VNF-API:vnf-topology-information']['VNF-API:vnf-parameters']
573 for param in param_list:
574 if param['vnf-parameter-name'] in vnf_parameter_name_list:
575 ipaddr_or_vni = param['vnf-parameter-value'].split('.')
576 number = int(ipaddr_or_vni[-1])
581 ipaddr_or_vni[-1] = str(number)
582 param['vnf-parameter-value'] = '.'.join(ipaddr_or_vni)
584 assert json_data is not None
585 with open(vnf_template_file, 'w') as json_output:
586 json.dump(json_data, json_output, indent=4, sort_keys=True)
588 def save_preload_data(self, preload_data):
589 self.save_object(preload_data, self.preload_dict_file)
591 def load_preload_data(self):
592 return self.load_object(self.preload_dict_file)
594 def save_vgmux_vnf_name(self, vgmux_vnf_name):
595 self.save_object(vgmux_vnf_name, self.vgmux_vnf_name_file)
597 def load_vgmux_vnf_name(self):
598 return self.load_object(self.vgmux_vnf_name_file)