3 * ============LICENSE_START=======================================================
4 * Copyright (C) 2019 Orange
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * ============LICENSE_END=========================================================
34 from datetime import datetime
35 from datetime import timedelta
36 from simple_rest_client.api import API
37 from simple_rest_client.resource import Resource
38 from basicauth import encode
39 from urllib3.exceptions import InsecureRequestWarning
42 old_merge_environment_settings = requests.Session.merge_environment_settings
46 ansible_inventory = {}
47 osdf_response = {"last": { "id": "id", "data": None}}
48 print_performance=False
49 stats = open("stats.csv", "w")
50 stats.write("operation;time\n")
53 class BaseServer(http.server.BaseHTTPRequestHandler):
55 def __init__(self, one, two, three):
56 self.osdf_resp = osdf_response
57 super().__init__(one, two, three)
59 def _set_headers(self):
60 self.send_response(200)
61 self.send_header('Content-type', 'application/json')
72 self.data_string = self.rfile.read(int(self.headers['Content-Length']))
73 self.send_response(200)
76 data = simplejson.loads(self.data_string)
77 #print(json.dumps(data, indent=4))
78 self.osdf_resp["last"]["data"] = data
79 self.osdf_resp["last"]["id"] = data["requestId"]
80 with open("response.json", "w") as outfile:
81 simplejson.dump(data, outfile)
86 def __init__(self, description):
87 self.description = description
89 def __call__(self, f):
90 def wrap(*args, **kwargs):
92 if f.__name__ == "appc_lcm_request" or f.__name__ == "confirm_appc_lcm_action":
94 description = self.description
96 description = self.description + ' ' + req['input']['action']
97 if description.find('>') < 0 and print_performance:
98 print (('> {} START').format(description))
101 ret = f(*args, **kwargs)
104 if print_performance:
105 print ('> {} DONE {:0.3f} ms'.format(description, (time2-time1)*1000.0))
106 stats.write("{};{:0.3f}\n".format(description, (time2-time1)*1000.0).replace(".", ","))
111 def _run_osdf_resp_server():
112 server_address = ('', 9000)
113 httpd = http.server.HTTPServer(server_address, BaseServer)
114 print('Starting OSDF Response Server...')
115 httpd.serve_forever()
118 @contextlib.contextmanager
119 def _no_ssl_verification():
120 opened_adapters = set()
121 def merge_environment_settings(self, url, proxies, stream, verify, cert):
122 # Verification happens only once per connection so we need to close
123 # all the opened adapters once we're done. Otherwise, the effects of
124 # verify=False persist beyond the end of this context manager.
125 opened_adapters.add(self.get_adapter(url))
127 settings = old_merge_environment_settings(self, url, proxies, stream, verify, cert)
128 settings['verify'] = False
132 requests.Session.merge_environment_settings = merge_environment_settings
134 with warnings.catch_warnings():
135 warnings.simplefilter('ignore', InsecureRequestWarning)
138 requests.Session.merge_environment_settings = old_merge_environment_settings
140 for adapter in opened_adapters:
147 def _get_aai_rel_link_data(data, related_to, search_key=None, match_dict=None):
148 # some strings that we will encounter frequently
149 rel_lst = "relationship-list"
150 rkey = "relationship-key"
151 rval = "relationship-value"
152 rdata = "relationship-data"
155 m_key = match_dict.get('key')
156 m_value = match_dict.get('value')
160 rel_dict = data.get(rel_lst)
161 if rel_dict: # check if data has relationship lists
162 for key, rel_list in rel_dict.items(): # pylint: disable=W0612
164 if rel.get("related-to") == related_to:
167 link = rel.get("related-link")
169 if rel.get("related-to-property") is not None:
170 property = rel.get("related-to-property")[0]['property-value']
171 r_data = rel.get(rdata, [])
174 if rd.get(rkey) == search_key:
176 if not match_dict: # return first match
178 {"link": link, "property": property, "d_value": dval}
180 break # go to next relation
181 if rd.get(rkey) == m_key \
182 and rd.get(rval) == m_value:
184 if match_dict and matched: # if matching required
186 {"link": link, "property": property, "d_value": dval}
188 # matched, return search value corresponding
189 # to the matched r_data group
190 else: # no search key; just return the link
192 {"link": link, "property": property, "d_value": dval}
196 {"link": None, "property": None, "d_value": None}
201 class AAIApiResource(Resource):
203 'generic_vnf': {'method': 'GET', 'url': 'network/generic-vnfs/generic-vnf/{}'},
204 'vf_module': {'method': 'GET', 'url': 'network/generic-vnfs/generic-vnf/{}/vf-modules/vf-module/{}'},
205 'vnfc': {'method': 'GET', 'url': 'network/vnfcs/vnfc/{}'},
206 'vnfc_put': {'method': 'PUT', 'url': 'network/vnfcs/vnfc/{}'},
207 'vnfc_patch': {'method': 'PATCH', 'url': 'network/vnfcs/vnfc/{}'},
208 'link': {'method': 'GET', 'url': '{}'},
209 'service_instance': {'method': 'GET',
210 'url': 'business/customers/customer/{}/service-subscriptions/service-subscription/{}/service-instances/service-instance/{}'}
214 class HASApiResource(Resource):
216 'plans': {'method': 'POST', 'url': 'plans/'},
217 'plan': {'method': 'GET', 'url': 'plans/{}'}
221 class OSDFApiResource(Resource):
223 'placement': {'method': 'POST', 'url': 'placement'}
227 class APPCLcmApiResource(Resource):
229 'distribute_traffic': {'method': 'POST', 'url': 'appc-provider-lcm:distribute-traffic/'},
230 'distribute_traffic_check': {'method': 'POST', 'url': 'appc-provider-lcm:distribute-traffic-check/'},
231 'upgrade_software': {'method': 'POST', 'url': 'appc-provider-lcm:upgrade-software/'},
232 'upgrade_pre_check': {'method': 'POST', 'url': 'appc-provider-lcm:upgrade-pre-check/'},
233 'upgrade_post_check': {'method': 'POST', 'url': 'appc-provider-lcm:upgrade-post-check/'},
234 'action_status': {'method': 'POST', 'url': 'appc-provider-lcm:action-status/'},
235 'check_lock': {'method': 'POST', 'url': 'appc-provider-lcm:check-lock/'},
236 'lock': {'method': 'POST', 'url': 'appc-provider-lcm:lock/'},
237 'unlock': {'method': 'POST', 'url': 'appc-provider-lcm:unlock/'}
241 def _init_python_aai_api(onap_ip, content_type='application/json'):
243 api_root_url="https://{}:30233/aai/v14/".format(onap_ip),
246 'Authorization': encode("AAI", "AAI"),
247 'X-FromAppId': 'SCRIPT',
248 'Accept': 'application/json',
249 'Content-Type': content_type,
250 'X-TransactionId': str(uuid.uuid4()),
254 json_encode_body=True # encode body as json
256 api.add_resource(resource_name='aai', resource_class=AAIApiResource)
260 def _init_python_has_api(onap_ip):
262 api_root_url="https://{}:30275/v1/".format(onap_ip),
265 'Authorization': encode("admin1", "plan.15"),
266 'X-FromAppId': 'SCRIPT',
267 'Accept': 'application/json',
268 'Content-Type': 'application/json',
269 'X-TransactionId': str(uuid.uuid4()),
273 json_encode_body=True # encode body as json
275 api.add_resource(resource_name='has', resource_class=HASApiResource)
279 def _init_python_osdf_api(onap_ip):
281 api_root_url="https://{}:30248/api/oof/v1/".format(onap_ip),
284 'Authorization': encode("test", "testpwd"),
285 'X-FromAppId': 'SCRIPT',
286 'Accept': 'application/json',
287 'Content-Type': 'application/json',
288 'X-TransactionId': str(uuid.uuid4()),
292 json_encode_body=True # encode body as json
294 api.add_resource(resource_name='osdf', resource_class=OSDFApiResource)
298 def _init_python_appc_lcm_api(onap_ip):
300 api_root_url="https://{}:30230/restconf/operations/".format(onap_ip),
303 'Authorization': encode("admin", "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"),
304 'X-FromAppId': 'SCRIPT',
305 'Accept': 'application/json',
306 'Content-Type': 'application/json',
310 json_encode_body=True # encode body as json
312 api.add_resource(resource_name='lcm', resource_class=APPCLcmApiResource)
316 @timing("Load AAI Data")
317 def load_aai_data(vfw_vnf_id, onap_ip):
318 api = _init_python_aai_api(onap_ip)
320 aai_data['service-info'] = {'global-customer-id': '', 'service-instance-id': '', 'service-type': ''}
321 aai_data['vfw-model-info'] = {'model-invariant-id': '', 'model-version-id': '', 'vnf-name': '', 'vnf-type': ''}
322 aai_data['vpgn-model-info'] = {'model-invariant-id': '', 'model-version-id': '', 'vnf-name': '', 'vnf-type': ''}
323 with _no_ssl_verification():
324 response = api.aai.generic_vnf(vfw_vnf_id, body=None, params={'depth': 2}, headers={})
325 aai_data['vfw-model-info']['model-invariant-id'] = response.body.get('model-invariant-id')
326 aai_data['vfw-model-info']['model-version-id'] = response.body.get('model-version-id')
327 aai_data['vfw-model-info']['vnf-name'] = response.body.get('vnf-name')
328 aai_data['vfw-model-info']['vnf-type'] = response.body.get('vnf-type')
329 aai_data['vf-module-id'] = response.body['vf-modules']['vf-module'][0]['vf-module-id']
331 related_to = "service-instance"
332 search_key = "customer.global-customer-id"
333 rl_data_list = _get_aai_rel_link_data(data=response.body, related_to=related_to, search_key=search_key)
334 aai_data['service-info']['global-customer-id'] = rl_data_list[0]['d_value']
336 search_key = "service-subscription.service-type"
337 rl_data_list = _get_aai_rel_link_data(data=response.body, related_to=related_to, search_key=search_key)
338 aai_data['service-info']['service-type'] = rl_data_list[0]['d_value']
340 search_key = "service-instance.service-instance-id"
341 rl_data_list = _get_aai_rel_link_data(data=response.body, related_to=related_to, search_key=search_key)
342 aai_data['service-info']['service-instance-id'] = rl_data_list[0]['d_value']
344 service_link = rl_data_list[0]['link']
345 response = api.aai.link(service_link, body=None, params={}, headers={})
347 related_to = "generic-vnf"
348 search_key = "generic-vnf.vnf-id"
349 rl_data_list = _get_aai_rel_link_data(data=response.body, related_to=related_to, search_key=search_key)
350 for i in range(0, len(rl_data_list)):
351 vnf_id = rl_data_list[i]['d_value']
353 if vnf_id != vfw_vnf_id:
354 vnf_link = rl_data_list[i]['link']
355 response = api.aai.link(vnf_link, body=None, params={}, headers={})
356 if aai_data['vfw-model-info']['model-invariant-id'] != response.body.get('model-invariant-id'):
357 aai_data['vpgn-model-info']['model-invariant-id'] = response.body.get('model-invariant-id')
358 aai_data['vpgn-model-info']['model-version-id'] = response.body.get('model-version-id')
359 aai_data['vpgn-model-info']['vnf-name'] = response.body.get('vnf-name')
360 aai_data['vpgn-model-info']['vnf-type'] = response.body.get('vnf-type')
365 @timing("> OSDF REQ")
366 def _osdf_request(rancher_ip, onap_ip, aai_data, exclude, use_oof_cache):
367 dirname = os.path.join('templates/oof-cache/', aai_data['vf-module-id'])
369 file = os.path.join(dirname, 'sample-osdf-excluded.json')
371 file = os.path.join(dirname, 'sample-osdf-required.json')
372 if use_oof_cache and os.path.exists(file):
373 migrate_from = json.loads(open(file).read())
376 print('Making OSDF request for excluded {}'.format(str(exclude)))
377 api = _init_python_osdf_api(onap_ip)
378 request_id = str(uuid.uuid4())
379 transaction_id = str(uuid.uuid4())
380 callback_url = "http://{}:9000/osdfCallback/".format(str(rancher_ip))
381 template = json.loads(open('templates/osdfRequest.json').read())
382 template["requestInfo"]["transactionId"] = transaction_id
383 template["requestInfo"]["requestId"] = request_id
384 template["requestInfo"]["callbackUrl"] = callback_url
385 template["serviceInfo"]["serviceInstanceId"] = aai_data['service-info']['service-instance-id']
386 template["placementInfo"]["requestParameters"]["chosenCustomerId"] = aai_data['service-info']['global-customer-id']
387 template["placementInfo"]["placementDemands"][0]["resourceModelInfo"]["modelInvariantId"] =\
388 aai_data['vfw-model-info']['model-invariant-id']
389 template["placementInfo"]["placementDemands"][0]["resourceModelInfo"]["modelVersionId"] =\
390 aai_data['vfw-model-info']['model-version-id']
391 template["placementInfo"]["placementDemands"][1]["resourceModelInfo"]["modelInvariantId"] =\
392 aai_data['vpgn-model-info']['model-invariant-id']
393 template["placementInfo"]["placementDemands"][1]["resourceModelInfo"]["modelVersionId"] =\
394 aai_data['vpgn-model-info']['model-version-id']
396 template["placementInfo"]["placementDemands"][0]["excludedCandidates"][0]["identifiers"].\
397 append(aai_data['vf-module-id'])
398 del template["placementInfo"]["placementDemands"][0]["requiredCandidates"]
400 template["placementInfo"]["placementDemands"][0]["requiredCandidates"][0]["identifiers"].\
401 append(aai_data['vf-module-id'])
402 del template["placementInfo"]["placementDemands"][0]["excludedCandidates"]
404 #print(json.dumps(template, indent=4))
406 with _no_ssl_verification():
407 response = api.osdf.placement(body=template, params={}, headers={}) # pylint: disable=W0612
408 #if response.body.get('error_message') is not None:
409 # raise Exception(response.body['error_message']['explanation'])
412 while counter < 600 and osdf_response["last"]["id"] != request_id:
414 if counter % 20 == 0:
418 if osdf_response["last"]["id"] == request_id:
419 status = osdf_response["last"]["data"]["requestStatus"]
420 if status == "completed":
422 "solution": osdf_response["last"]["data"]["solutions"]["placementSolutions"]
424 if not os.path.exists(dirname):
427 f.write(json.dumps(result, indent=4))
431 message = osdf_response["last"]["data"]["statusMessage"]
432 raise Exception("OOF request {}: {}".format(status, message))
434 raise Exception("No response for OOF request")
438 def _has_request(onap_ip, aai_data, exclude, use_oof_cache):
439 dirname = os.path.join('templates/oof-cache/', aai_data['vf-module-id'])
441 file = os.path.join(dirname, 'sample-has-excluded.json')
443 file = os.path.join(dirname, 'sample-has-required.json')
444 if use_oof_cache and os.path.exists(file):
445 migrate_from = json.loads(open(file).read())
448 print('Making HAS request for excluded {}'.format(str(exclude)))
449 api = _init_python_has_api(onap_ip)
450 request_id = str(uuid.uuid4())
451 template = json.loads(open('templates/hasRequest.json').read())
453 template['name'] = request_id
454 node = template['template']['parameters']
455 node['chosen_customer_id'] = aai_data['service-info']['global-customer-id']
456 node['service_id'] = aai_data['service-info']['service-instance-id']
457 node = template['template']['demands']['vFW-SINK'][0]
458 node['filtering_attributes']['model-invariant-id'] = aai_data['vfw-model-info']['model-invariant-id']
459 node['filtering_attributes']['model-version-id'] = aai_data['vfw-model-info']['model-version-id']
461 node['excluded_candidates'][0]['candidate_id'][0] = aai_data['vf-module-id']
462 del node['required_candidates']
464 node['required_candidates'][0]['candidate_id'][0] = aai_data['vf-module-id']
465 del node['excluded_candidates']
466 node = template['template']['demands']['vPGN'][0]
467 node['filtering_attributes']['model-invariant-id'] = aai_data['vpgn-model-info']['model-invariant-id']
468 node['filtering_attributes']['model-version-id'] = aai_data['vpgn-model-info']['model-version-id']
470 #print(json.dumps(template, indent=4))
472 with _no_ssl_verification():
473 response = api.has.plans(body=template, params={}, headers={})
474 if response.body.get('error_message') is not None:
475 raise Exception(response.body['error_message']['explanation'])
477 plan_id = response.body['id']
478 response = api.has.plan(plan_id, body=None, params={}, headers={})
479 status = response.body['plans'][0]['status']
480 while status != 'done' and status != 'error':
482 response = api.has.plan(plan_id, body=None, params={}, headers={})
483 status = response.body['plans'][0]['status']
485 result = response.body['plans'][0]['recommendations'][0]
487 raise Exception(response.body['plans'][0]['message'])
489 if not os.path.exists(dirname):
492 f.write(json.dumps(result, indent=4))
497 def _extract_has_appc_identifiers(has_result, demand, onap_ip):
499 v_server = has_result[demand]['attributes']['vservers'][0]
501 if len(has_result[demand]['attributes']['vservers'][0]['l-interfaces']) == 4:
502 v_server = has_result[demand]['attributes']['vservers'][0]
504 v_server = has_result[demand]['attributes']['vservers'][1]
505 for itf in v_server['l-interfaces']:
506 if itf['ipv4-addresses'][0].startswith("10.0."):
507 ip = itf['ipv4-addresses'][0]
510 if v_server['vserver-name'] in hostname_cache and demand != 'vPGN':
511 v_server['vserver-name'] = v_server['vserver-name'].replace("01", "02")
512 hostname_cache.append(v_server['vserver-name'])
514 api = _init_python_aai_api(onap_ip) # pylint: disable=W0612
515 vnfc_type = demand.lower()
516 # with _no_ssl_verification():
517 # response = api.aai.vnfc(v_server['vserver-name'], body=None, params={}, headers={})
518 # vnfc_type = response.body.get('nfc-naming-code')
521 'vnf-id': has_result[demand]['attributes']['nf-id'],
522 'vf-module-id': has_result[demand]['attributes']['vf-module-id'],
524 'vserver-id': v_server['vserver-id'],
525 'vserver-name': v_server['vserver-name'],
526 'vnfc-type': vnfc_type,
527 'physical-location-id': has_result[demand]['attributes']['physical-location-id']
529 ansible_inventory_entry = "{} ansible_ssh_host={} ansible_ssh_user=ubuntu".format(config['vserver-name'], config['ip'])
530 if demand.lower() not in ansible_inventory:
531 ansible_inventory[demand.lower()] = {}
532 ansible_inventory[demand.lower()][config['vserver-name']] = ansible_inventory_entry
534 _verify_vnfc_data(api, onap_ip, config)
538 def _verify_vnfc_data(aai_api, onap_ip, config, root=None):
539 vnfc_name = config['vserver-name']
540 oam_ip = config['ip']
541 with _no_ssl_verification():
542 response = aai_api.aai.vnfc(vnfc_name, body=None, params=None, headers={})
543 #print(json.dumps(response.body))
544 if "ipaddress-v4-oam-vip" not in response.body and oam_ip != "":
545 print("VNFC IP information update for {}".format(vnfc_name))
546 api = _init_python_aai_api(onap_ip, 'application/merge-patch+json')
547 with _no_ssl_verification():
548 response = api.aai.vnfc_patch(vnfc_name, body={"ipaddress-v4-oam-vip": oam_ip, "vnfc-name": vnfc_name}, params=None, headers={})
549 if "relationship-list" not in response.body:
550 print("VNFC REL information update for {}".format(vnfc_name))
558 with _no_ssl_verification():
559 vf_module = aai_api.aai.vf_module(config['vnf-id'], config['vf-module-id'], body=None, params={'depth': 2}, headers={}).body
560 related_to = "vserver"
561 search_key = "cloud-region.cloud-owner"
562 rl_data_list = _get_aai_rel_link_data(data=vf_module, related_to=related_to, search_key=search_key)
563 vserver_info["owner"] = rl_data_list[0]['d_value']
565 search_key = "cloud-region.cloud-region-id"
566 rl_data_list = _get_aai_rel_link_data(data=vf_module, related_to=related_to, search_key=search_key)
567 vserver_info["region"] = rl_data_list[0]['d_value']
569 search_key = "tenant.tenant-id"
570 rl_data_list = _get_aai_rel_link_data(data=vf_module, related_to=related_to, search_key=search_key)
571 vserver_info["tenant"] = rl_data_list[0]['d_value']
573 search_key = "vserver.vserver-id"
574 rl_data_list = _get_aai_rel_link_data(data=vf_module, related_to=related_to, search_key=search_key)
575 for relation in rl_data_list:
576 vserver_info["id"] = relation['d_value']
577 vserver_info["link"] = relation['link']
580 "related-to": "vserver",
581 "related-link": vserver_info["link"],
582 "relationship-data": [
584 "relationship-key": "cloud-region.cloud-owner",
585 "relationship-value": vserver_info["owner"]
588 "relationship-key": "cloud-region.cloud-region-id",
589 "relationship-value": vserver_info["region"]
592 "relationship-key": "tenant.tenant-id",
593 "relationship-value": vserver_info["tenant"]
596 "relationship-key": "vserver.vserver-id",
597 "relationship-value": vserver_info["id"]
601 #print(json.dumps(rel_data, indent=4))
602 if config['vserver-id'] == relation['d_value']:
603 with _no_ssl_verification():
604 response = aai_api.aai.vnfc_put("{}/relationship-list/relationship".format(vnfc_name), body=rel_data, params=None, headers={})
605 elif root is None and relation['d_value'] is not None:
606 new_config = copy.deepcopy(config)
607 new_config['vserver-name'] = relation['property']
608 new_config['vserver-id'] = relation['d_value']
609 new_config['ip'] = ""
610 _verify_vnfc_data(aai_api, onap_ip, new_config, vnfc_name)
611 with _no_ssl_verification():
612 response = aai_api.aai.vnfc(vnfc_name, body=None, params=None, headers={})
613 #print(json.dumps(response.body))
616 def _extract_osdf_appc_identifiers(has_result, demand, onap_ip):
618 v_server = has_result[demand]['vservers'][0]
620 if len(has_result[demand]['vservers'][0]['l-interfaces']) == 4:
621 v_server = has_result[demand]['vservers'][0]
623 v_server = has_result[demand]['vservers'][1]
624 for itf in v_server['l-interfaces']:
625 if itf['ipv4-addresses'][0].startswith("10.0."):
626 ip = itf['ipv4-addresses'][0]
629 if v_server['vserver-name'] in hostname_cache and demand != 'vPGN':
630 v_server['vserver-name'] = v_server['vserver-name'].replace("01", "02")
631 hostname_cache.append(v_server['vserver-name'])
633 api = _init_python_aai_api(onap_ip)
634 vnfc_type = demand.lower(),
635 with _no_ssl_verification():
636 response = api.aai.vnfc(v_server['vserver-name'], body=None, params={}, headers={})
637 vnfc_type = response.body.get('nfc-naming-code')
640 'vnf-id': has_result[demand]['nf-id'],
641 'vf-module-id': has_result[demand]['vf-module-id'],
643 'vserver-id': v_server['vserver-id'],
644 'vserver-name': v_server['vserver-name'],
645 'vnfc-type': vnfc_type,
646 'physical-location-id': has_result[demand]['locationId']
648 ansible_inventory_entry = "{} ansible_ssh_host={} ansible_ssh_user=ubuntu".format(config['vserver-name'], config['ip'])
649 if demand.lower() not in ansible_inventory:
650 ansible_inventory[demand.lower()] = {}
651 ansible_inventory[demand.lower()][config['vserver-name']] = ansible_inventory_entry
653 _verify_vnfc_data(api, onap_ip, config)
658 def _extract_has_appc_dt_config(has_result, demand):
663 "nf-type": has_result[demand]['attributes']['nf-type'],
664 "nf-name": has_result[demand]['attributes']['nf-name'],
665 "vf-module-name": has_result[demand]['attributes']['vf-module-name'],
666 "vnf-type": has_result[demand]['attributes']['vnf-type'],
667 "service_instance_id": "319e60ef-08b1-47aa-ae92-51b97f05e1bc",
668 "cloudClli": has_result[demand]['attributes']['physical-location-id'],
669 "nf-id": has_result[demand]['attributes']['nf-id'],
670 "vf-module-id": has_result[demand]['attributes']['vf-module-id'],
671 "aic_version": has_result[demand]['attributes']['aic_version'],
672 "ipv4-oam-address": has_result[demand]['attributes']['ipv4-oam-address'],
673 "vnfHostName": has_result[demand]['candidate']['host_id'],
674 "cloudOwner": has_result[demand]['candidate']['cloud_owner'],
675 "isRehome": has_result[demand]['candidate']['is_rehome'],
676 "locationId": has_result[demand]['candidate']['location_id'],
677 "locationType": has_result[demand]['candidate']['location_type'],
678 'vservers': has_result[demand]['attributes']['vservers']
683 def _extract_osdf_appc_dt_config(osdf_result, demand):
687 return osdf_result[demand]
690 def _build_config_from_has(has_result, onap_ip):
691 v_pgn_result = _extract_has_appc_identifiers(has_result, 'vPGN', onap_ip)
692 v_fw_result = _extract_has_appc_identifiers(has_result, 'vFW-SINK', onap_ip)
693 dt_config = _extract_has_appc_dt_config(has_result, 'vFW-SINK')
696 'vPGN': v_pgn_result,
697 'vFW-SINK': v_fw_result
699 #print(json.dumps(config, indent=4))
700 config['dt-config'] = {
701 'destinations': [dt_config]
706 def _adapt_osdf_result(osdf_result):
708 demand = _build_osdf_result_demand(osdf_result["solution"][0][0])
709 result[demand["name"]] = demand["value"]
710 demand = _build_osdf_result_demand(osdf_result["solution"][0][1])
711 result[demand["name"]] = demand["value"]
715 def _build_osdf_result_demand(solution):
717 result["name"] = solution["resourceModuleName"]
718 value = {"candidateId": solution["solution"]["identifiers"][0]}
719 for info in solution["assignmentInfo"]:
720 value[info["key"]] = info["value"]
721 result["value"] = value
725 def _build_config_from_osdf(osdf_result, onap_ip):
726 osdf_result = _adapt_osdf_result(osdf_result)
727 v_pgn_result = _extract_osdf_appc_identifiers(osdf_result, 'vPGN', onap_ip)
728 v_fw_result = _extract_osdf_appc_identifiers(osdf_result, 'vFW-SINK', onap_ip)
729 dt_config = _extract_osdf_appc_dt_config(osdf_result, 'vFW-SINK')
732 'vPGN': v_pgn_result,
733 'vFW-SINK': v_fw_result
735 #print(json.dumps(config, indent=4))
736 config['dt-config'] = {
737 'destinations': [dt_config]
742 def _build_appc_lcm_dt_payload(demand, oof_config, action, traffic_presence):
743 is_check = traffic_presence is not None
744 oof_config = copy.deepcopy(oof_config)
746 # node_list = "[ {} ]".format(oof_config['vPGN']['vserver-id'])
748 # node_list = "[ {} ]".format(oof_config['vFW-SINK']['vserver-id'])
749 book_name = "{}/latest/ansible/{}/site.yml".format(demand.lower(), action.lower())
750 config = oof_config[demand]
752 # 'site': config['physical-location-id'],
753 # 'vnfc_type': config['vnfc-type'],
755 # 'ne_id': config['vserver-name'],
756 # 'fixed_ip_address': config['ip']
760 #node_list.append(node)
763 oof_config['dt-config']['trafficpresence'] = traffic_presence
765 file_content = oof_config['dt-config']
768 "configuration-parameters": {
769 "file_parameter_content": json.dumps(file_content)
771 "request-parameters": {
772 "vserver-id": config['vserver-id']
776 config["configuration-parameters"]["book_name"] = book_name
777 payload = json.dumps(config)
781 def _build_appc_lcm_upgrade_payload(demand, oof_config, action, old_version, new_version):
782 oof_config = copy.deepcopy(oof_config)
783 book_name = "{}/latest/ansible/{}/site.yml".format(demand.lower(), action.lower())
784 config = oof_config[demand]
786 file_content = {} #oof_config['dt-config']
789 "configuration-parameters": {
790 "file_parameter_content": json.dumps(file_content),
791 "existing-software-version": old_version,
792 "new-software-version": new_version
794 "request-parameters": {
795 "vserver-id": config['vserver-id']
799 config["configuration-parameters"]["book_name"] = book_name
800 payload = json.dumps(config)
804 def _build_appc_lcm_status_body(req):
806 'request-id': req['input']['common-header']['request-id'],
807 'sub-request-id': req['input']['common-header']['sub-request-id'],
808 'originator-id': req['input']['common-header']['originator-id']
810 payload = json.dumps(payload)
811 template = json.loads(open('templates/appcRestconfLcm.json').read())
812 template['input']['action'] = 'ActionStatus'
813 template['input']['payload'] = payload
814 template['input']['common-header']['request-id'] = req['input']['common-header']['request-id']
815 template['input']['common-header']['sub-request-id'] = str(uuid.uuid4())
816 template['input']['action-identifiers']['vnf-id'] = req['input']['action-identifiers']['vnf-id']
820 @timing("> DT REQ BODY")
821 def _build_appc_lcm_lock_request_body(is_vpkg, config, req_id, action):
826 return _build_appc_lcm_request_body(None, demand, config, req_id, action)
829 @timing("> DT REQ BODY")
830 def _build_appc_lcm_dt_request_body(is_vpkg, config, req_id, action, traffic_presence=None):
835 payload = _build_appc_lcm_dt_payload(demand, config, action, traffic_presence)
836 return _build_appc_lcm_request_body(payload, demand, config, req_id, action)
839 @timing("> UP REQ BODY")
840 def _build_appc_lcm_upgrade_request_body(config, req_id, action, old_version, new_version):
842 payload = _build_appc_lcm_upgrade_payload(demand, config, action, old_version, new_version)
843 return _build_appc_lcm_request_body(payload, demand, config, req_id, action)
846 def _build_appc_lcm_request_body(payload, demand, config, req_id, action):
847 #print(config[demand])
848 template = json.loads(open('templates/appcRestconfLcm.json').read())
849 template['input']['action'] = action
850 if payload is not None:
851 template['input']['payload'] = payload
853 del template['input']['payload']
854 template['input']['common-header']['request-id'] = req_id
855 template['input']['common-header']['sub-request-id'] = str(uuid.uuid4())
856 template['input']['action-identifiers']['vnf-id'] = config[demand]['vnf-id']
860 def _set_appc_lcm_timestamp(body, timestamp=None):
861 if timestamp is None:
862 t = datetime.utcnow() + timedelta(seconds=-10)
863 timestamp = t.strftime('%Y-%m-%dT%H:%M:%S.244Z')
864 body['input']['common-header']['timestamp'] = timestamp
867 @timing("Load OOF Data and Build APPC REQ")
868 def build_appc_lcms_requests_body(rancher_ip, onap_ip, aai_data, use_oof_cache, if_close_loop_vfw, new_version=None):
872 migrate_from = _has_request(onap_ip, aai_data, False, use_oof_cache)
874 if if_close_loop_vfw:
875 migrate_to = migrate_from
877 migrate_to = _has_request(onap_ip, aai_data, True, use_oof_cache)
879 migrate_from = _build_config_from_has(migrate_from, onap_ip)
880 migrate_to = _build_config_from_has(migrate_to, onap_ip)
882 migrate_from = _osdf_request(rancher_ip, onap_ip, aai_data, False, use_oof_cache)
884 if if_close_loop_vfw:
885 migrate_to = migrate_from
887 migrate_to = _osdf_request(rancher_ip, onap_ip, aai_data, True, use_oof_cache)
889 migrate_from = _build_config_from_osdf(migrate_from, onap_ip)
890 migrate_to = _build_config_from_osdf(migrate_to, onap_ip)
892 #print(json.dumps(migrate_from, indent=4))
893 #print(json.dumps(migrate_to, indent=4))
894 req_id = str(uuid.uuid4())
897 if_dt_only = new_version is None
898 if new_version is not None and new_version != "1.0":
905 result.append({"payload": _build_appc_lcm_lock_request_body(True, migrate_from, req_id, 'CheckLock'), "breakOnFailure": True,
906 "description": "Check vPGN Lock Status"})
907 result.append({"payload": _build_appc_lcm_lock_request_body(False, migrate_from, req_id, 'CheckLock'), "breakOnFailure": True,
908 "description": "Check vFW-1 Lock Status"})
909 result.append({"payload": _build_appc_lcm_lock_request_body(False, migrate_to, req_id, 'CheckLock'), "breakOnFailure": True,
910 "description": "Check vFW-2 Lock "})
912 result.append({"payload": _build_appc_lcm_lock_request_body(True, migrate_from, req_id, 'Lock'), "breakOnFailure": True,
913 "description": "Lock vPGN"})
914 result.append({"payload": _build_appc_lcm_lock_request_body(False, migrate_from, req_id, 'Lock'), "breakOnFailure": True,
915 "description": "Lock vFW-1"})
916 result.append({"payload": _build_appc_lcm_lock_request_body(False, migrate_to, req_id, 'Lock'), "breakOnFailure": True,
917 "description": "Lock vFW-2"})
920 payload_dt_check_vpkg = _build_appc_lcm_dt_request_body(True, migrate_from, req_id, 'DistributeTrafficCheck', True)
921 payload_dt_vpkg_to = _build_appc_lcm_dt_request_body(True, migrate_to, req_id, 'DistributeTraffic')
922 payload_dt_check_vfw_from = _build_appc_lcm_dt_request_body(False, migrate_from, req_id, 'DistributeTrafficCheck',
924 payload_dt_check_vfw_to = _build_appc_lcm_dt_request_body(False, migrate_to, req_id, 'DistributeTrafficCheck', True)
926 requests.append({"payload": payload_dt_vpkg_to, "breakOnFailure": True, "description": "Migrating source vFW traffic to destination vFW"})
927 requests.append({"payload": payload_dt_check_vfw_from, "breakOnFailure": True, "description": "Checking traffic has been stopped on the source vFW"})
928 requests.append({"payload": payload_dt_check_vfw_to, "breakOnFailure": True, "description": "Checking traffic has appeared on the destination vFW"})
929 result.append({"payload": payload_dt_check_vpkg, "breakOnFailure": False, "description": "Check current traffic destination on vPGN",
930 "workflow": {"requests": requests, "description": "Migrate Traffic and Verify"}})
932 #_build_appc_lcm_dt_request_body(is_vpkg, config, req_id, action, traffic_presence=None):
933 payload_dt_check_vpkg = _build_appc_lcm_dt_request_body(True, migrate_from, req_id, 'DistributeTrafficCheck', True)
934 payload_dt_vpkg_to = _build_appc_lcm_dt_request_body(True, migrate_to, req_id, 'DistributeTraffic')
935 payload_dt_vpkg_from = _build_appc_lcm_dt_request_body(True, migrate_from, req_id, 'DistributeTraffic')
937 payload_dt_check_vfw_from_absent = _build_appc_lcm_dt_request_body(False, migrate_from, req_id, 'DistributeTrafficCheck', False)
938 payload_dt_check_vfw_to_present = _build_appc_lcm_dt_request_body(False, migrate_to, req_id, 'DistributeTrafficCheck', True)
939 payload_dt_check_vfw_to_absent = _build_appc_lcm_dt_request_body(False, migrate_to, req_id, 'DistributeTrafficCheck', False)
940 payload_dt_check_vfw_from_present = _build_appc_lcm_dt_request_body(False, migrate_from, req_id, 'DistributeTrafficCheck', True)
942 payload_old_version_check_vfw_from = _build_appc_lcm_upgrade_request_body(migrate_from, req_id, 'UpgradePreCheck', old_version, new_version)
943 payload_new_version_check_vfw_from = _build_appc_lcm_upgrade_request_body(migrate_from, req_id, 'UpgradePostCheck', old_version, new_version)
944 payload_upgrade_vfw_from = _build_appc_lcm_upgrade_request_body(migrate_from, req_id, 'UpgradeSoftware', old_version, new_version)
946 migrate_requests = list()
947 migrate_requests.append({"payload": payload_dt_vpkg_to, "breakOnFailure": True, "description": "Migrating source vFW traffic to destination vFW"})
948 migrate_requests.append({"payload": payload_dt_check_vfw_from_absent, "breakOnFailure": True, "description": "Checking traffic has been stopped on the source vFW"})
949 migrate_requests.append({"payload": payload_dt_check_vfw_to_present, "breakOnFailure": True, "description": "Checking traffic has appeared on the destination vFW"})
951 requests.append({"payload": payload_dt_check_vpkg, "breakOnFailure": False, "description": "Check current traffic destination on vPGN",
952 "workflow": {"requests": migrate_requests, "description": "Migrate Traffic and Verify"}})
953 requests.append({"payload": payload_upgrade_vfw_from, "breakOnFailure": True, "description": "Upgrading Software on source vFW"})
954 requests.append({"payload": payload_new_version_check_vfw_from, "breakOnFailure": True, "description": "Check current software version on source vFW"})
955 requests.append({"payload": payload_dt_vpkg_from, "breakOnFailure": True, "description": "Migrating destination vFW traffic to source vFW"})
956 requests.append({"payload": payload_dt_check_vfw_to_absent, "breakOnFailure": True, "description": "Checking traffic has been stopped on the destination vFW"})
957 requests.append({"payload": payload_dt_check_vfw_from_present, "breakOnFailure": True, "description": "Checking traffic has appeared on the source vFW"})
959 result.append({"payload": payload_old_version_check_vfw_from, "breakOnFailure": False, "description": "Check current software version on source vFW",
960 "workflow": {"requests": requests, "description": "Migrate Traffic and Upgrade Software"}})
963 result.append({"payload": _build_appc_lcm_lock_request_body(True, migrate_from, req_id, 'Unlock'), "breakOnFailure": False,
964 "description": "Unlock vPGN"})
965 result.append({"payload": _build_appc_lcm_lock_request_body(False, migrate_from, req_id, 'Unlock'), "breakOnFailure": False,
966 "description": "Unlock vFW-1"})
967 result.append({"payload": _build_appc_lcm_lock_request_body(False, migrate_to, req_id, 'Unlock'), "breakOnFailure": False,
968 "description": "Unlock vFW-2"})
973 @timing("> Execute APPC REQ")
974 def appc_lcm_request(onap_ip, req):
976 api = _init_python_appc_lcm_api(onap_ip)
977 with _no_ssl_verification():
978 #print(json.dumps(req, indent=4))
979 if req['input']['action'] == "DistributeTraffic":
980 result = api.lcm.distribute_traffic(body=req, params={}, headers={})
981 elif req['input']['action'] == "DistributeTrafficCheck":
982 result = api.lcm.distribute_traffic_check(body=req, params={}, headers={})
983 elif req['input']['action'] == "UpgradeSoftware":
984 result = api.lcm.upgrade_software(body=req, params={}, headers={})
985 elif req['input']['action'] == "UpgradePreCheck":
986 result = api.lcm.upgrade_pre_check(body=req, params={}, headers={})
987 elif req['input']['action'] == "UpgradePostCheck":
988 result = api.lcm.upgrade_post_check(body=req, params={}, headers={})
989 elif req['input']['action'] == "CheckLock":
990 result = api.lcm.check_lock(body=req, params={}, headers={})
991 elif req['input']['action'] == "Lock":
992 result = api.lcm.lock(body=req, params={}, headers={})
993 elif req['input']['action'] == "Unlock":
994 result = api.lcm.unlock(body=req, params={}, headers={})
996 raise Exception("{} action not supported".format(req['input']['action']))
998 if result.body['output']['status']['code'] == 400:
999 if req['input']['action'] == "CheckLock":
1000 if result.body['output']['locked'] == "FALSE":
1004 result.body['output']['status']['code'] = 401
1007 elif result.body['output']['status']['code'] == 100:
1009 elif result.body['output']['status']['code'] >= 300 and result.body['output']['status']['code'] < 400:
1010 print("APPC LCM <<{}>> REJECTED [{} - {}]".format(req['input']['action'], result.body['output']['status']['code'],
1011 result.body['output']['status']['message']))
1012 elif result.body['output']['status']['code'] > 400 and result.body['output']['status']['code'] < 500:
1013 print("APPC LCM <<{}>> FAILED [{} - {}]".format(req['input']['action'], result.body['output']['status']['code'],
1014 result.body['output']['status']['message']))
1015 # elif result.body['output']['status']['code'] == 311:
1016 # timestamp = result.body['output']['common-header']['timestamp']
1017 # _set_appc_lcm_timestamp(req, timestamp)
1018 # appc_lcm_request(onap_ip, req)
1021 raise Exception("{} - {}".format(result.body['output']['status']['code'],
1022 result.body['output']['status']['message']))
1024 return result.body['output']['status']['code']
1027 def appc_lcm_status_request(onap_ip, req):
1028 api = _init_python_appc_lcm_api(onap_ip)
1029 status_body = _build_appc_lcm_status_body(req)
1030 _set_appc_lcm_timestamp(status_body)
1031 #print("CHECK STATUS")
1032 with _no_ssl_verification():
1033 result = api.lcm.action_status(body=status_body, params={}, headers={})
1035 if result.body['output']['status']['code'] == 400:
1036 status = json.loads(result.body['output']['payload'])
1039 raise Exception("{} - {}".format(result.body['output']['status']['code'],
1040 result.body['output']['status']['message']))
1043 @timing("> Confirm APPC REQ")
1044 def confirm_appc_lcm_action(onap_ip, req, check_appc_result):
1045 print("APPC LCM << {} >> [Status]".format(req['input']['action']))
1049 status = appc_lcm_status_request(onap_ip, req)
1050 print(status['status'])
1051 if status['status'] == 'SUCCESSFUL':
1053 elif status['status'] == 'IN_PROGRESS':
1055 elif check_appc_result:
1056 print("APPC LCM <<{}>> [{} - {}]".format(req['input']['action'], status['status'], status['status-reason']))
1062 @timing("Execute APPC LCM REQs")
1063 def _execute_lcm_requests(workflow, onap_ip, check_result):
1064 lcm_requests = workflow["requests"]
1065 print("WORKFLOW << {} >>".format(workflow["description"]))
1066 for i in range(len(lcm_requests)):
1067 req = lcm_requests[i]["payload"]
1068 #print(json.dumps(req, indent=4))
1069 print("APPC LCM << {} >> [{}]".format(req['input']['action'], lcm_requests[i]["description"]))
1070 _set_appc_lcm_timestamp(req)
1072 result = appc_lcm_request(onap_ip, req)
1073 #print("Result {}".format(result))
1076 conf_result = confirm_appc_lcm_action(onap_ip, req, check_result)
1082 if lcm_requests[i]["breakOnFailure"]:
1083 raise Exception("APPC LCM << {} >> FAILED".format(req['input']['action']))
1084 elif "workflow" in lcm_requests[i]:
1085 print("WORKFLOW << {} >> SKIP".format(lcm_requests[i]["workflow"]["description"]))
1086 elif "workflow" in lcm_requests[i]:
1087 _execute_lcm_requests(lcm_requests[i]["workflow"], onap_ip, check_result)
1090 def _generate_cdt_artifact_request(req_id, artifact, action, vnfc_type):
1094 'request-id': req_id,
1095 'action': "uploadArtifact",
1096 'payload': json.dumps(artifact['payload'])
1101 file = "{}_{}_{}.json".format(artifact['type'], action.lower(), vnfc_type)
1102 dirname = "templates/cdt-requests"
1104 if not os.path.exists(dirname):
1105 os.makedirs(dirname)
1106 f = open("{}/{}".format(dirname, file), 'w')
1107 f.write(json.dumps(req, indent=4))
1113 def _get_name_of_artifact(prefix, action, vnf_type):
1114 return "{}_{}_{}_0.0.1V.json".format(prefix, action, vnf_type)
1117 def _set_artifact_payload(vnf_type, vnfc_type, action, artifact):
1119 if action == "DistributeTraffic" or action == "DistributeTrafficCheck" or action == "AllAction":
1121 elif action == "UpgradeSoftware" or action == "UpgradePreCheck" or action == "UpgradePostCheck":
1124 raise Exception("{} action not supported".format(action))
1126 artifact_contents = ''
1127 if artifact['type'] == 'config_template':
1128 file = 'templates/cdt-templates/templates/action-template.json'
1129 template_file = 'templates/cdt-templates/{}/{}'
1131 template_file = template_file.format(vnfc_type, 'upgrade.json')
1133 template_file = template_file.format(vnfc_type, 'traffic.json')
1134 #print("Template for action {} in {}".format(action, template_file))
1135 #print(json.dumps(json.loads(open(template_file).read()), indent=4))
1136 artifact_contents = json.dumps(json.loads(open(template_file).read()), indent=4).replace("\n", "\r\n")
1137 elif artifact['type'] == 'parameter_definitions':
1138 file = 'templates/cdt-templates/templates/{}'
1140 file = file.format('upgrade-params.json')
1142 file = file.format('traffic-params.json')
1143 elif artifact['type'] == 'param_values':
1144 file = 'templates/cdt-templates/templates/{}'
1146 file = file.format('upgrade-params-list.json')
1148 file = file.format('traffic-params-list.json')
1149 elif artifact['type'] == 'reference_template':
1150 file = 'templates/cdt-templates/templates/reference-all-actions.json'
1152 raise Exception("{} not supported artifact type".format(artifact['type']))
1154 payload = json.loads(open(file).read())
1155 payload['vnf-type'] = vnf_type
1156 payload['artifact-name'] = artifact['name']
1157 payload['action'] = action
1159 if artifact['type'] == 'config_template':
1160 payload['artifact-contents'] = artifact_contents
1161 artifact['payload'] = payload
1164 def _generate_artifacts_for_cdt(vnf_type, vnf_type_formatted, vnfc_type, action):
1167 'name': _get_name_of_artifact("template", action, vnf_type_formatted),
1168 'type': 'config_template',
1169 'payload': {'test': 'test'}
1172 'name': _get_name_of_artifact("pd", action, vnf_type_formatted),
1173 'type': 'parameter_definitions',
1174 'payload': {'test': 'test'}
1177 'name': _get_name_of_artifact("param", action, vnf_type_formatted),
1178 'type': 'param_values',
1179 'payload': {'test': 'test'}
1182 _set_artifact_payload(vnf_type, vnfc_type, action, artifacts[0])
1183 _set_artifact_payload(vnf_type, vnfc_type, action, artifacts[1])
1184 _set_artifact_payload(vnf_type, vnfc_type, action, artifacts[2])
1189 def _generate_cdt_payloads_for_vnf(vnf_info, vnfc_type, actions):
1190 req_id = str(uuid.uuid4()).replace('-','')
1191 vnf_type_formatted = vnf_info['vnf-type'].replace(' ','').replace('/', '_')
1194 'name': _get_name_of_artifact("reference", 'AllAction', vnf_type_formatted),
1195 'type': 'reference_template'
1199 all_action_artifact = artifacts['AllAction'][0]
1201 _set_artifact_payload(vnf_info['vnf-type'], vnfc_type, 'AllAction', all_action_artifact)
1203 for action in actions:
1204 action_artifacts = _generate_artifacts_for_cdt(vnf_info['vnf-type'], vnf_type_formatted, vnfc_type, action)
1205 artifacts[action] = action_artifacts
1207 all_action_artifacts = list()
1209 for action in artifacts:
1210 artifact_list = list()
1213 'action-level': "vnf",
1215 'vnf-type': vnf_info['vnf-type'],
1216 'vnfc-type-list': [],
1219 'artifact-list': artifact_list
1222 if action != 'AllAction':
1223 action_info.update({
1226 'device-protocol': "ANSIBLE",
1227 'user-name': "admin",
1228 'port-number': "8000",
1229 'scopeType': "vnf-type"
1232 for action_artifact in artifacts[action]:
1233 artifact_list.append({'artifact-name': action_artifact['name'], 'artifact-type': action_artifact['type']})
1234 if action != 'AllAction':
1235 req = _generate_cdt_artifact_request(req_id, action_artifact, action, vnfc_type) # pylint: disable=W0612
1236 #print(json.dumps(req, indent=4))
1238 #print(json.dumps(action_info, indent=4))
1239 all_action_artifacts.append(action_info)
1241 all_action_artifact['payload']['artifact-contents'] = json.dumps({'reference_data': all_action_artifacts})
1242 req = _generate_cdt_artifact_request(req_id, all_action_artifact, 'AllAction', vnfc_type)
1243 #print(json.dumps(req, indent=4))
1246 def _generate_cdt_payloads(aai_data):
1247 vfw_actions = ["DistributeTrafficCheck", "UpgradeSoftware", "UpgradePreCheck", "UpgradePostCheck", "UpgradeSoftware"]
1248 vpgn_actions = ["DistributeTraffic", "DistributeTrafficCheck"]
1249 _generate_cdt_payloads_for_vnf(aai_data["vfw-model-info"], "vfw-sink", vfw_actions)
1250 _generate_cdt_payloads_for_vnf(aai_data["vpgn-model-info"], "vpgn", vpgn_actions)
1253 def execute_workflow(vfw_vnf_id, rancher_ip, onap_ip, use_oof_cache, if_close_loop_vfw, info_only, check_result, new_version=None):
1254 print("\nExecuting workflow for VNF ID '{}' on Rancher with IP {} and ONAP with IP {}".format(
1255 vfw_vnf_id, rancher_ip, onap_ip))
1256 print("\nOOF Cache {}, is CL vFW {}, only info {}, check LCM result {}".format(use_oof_cache, if_close_loop_vfw,
1257 info_only, check_result))
1258 if new_version is not None:
1259 print("\nNew vFW software version {}\n".format(new_version))
1261 x = threading.Thread(target=_run_osdf_resp_server, daemon=True)
1263 aai_data = load_aai_data(vfw_vnf_id, onap_ip)
1264 print("\nvFWDT Service Information:")
1265 print(json.dumps(aai_data, indent=4))
1266 lcm_requests = build_appc_lcms_requests_body(rancher_ip, onap_ip, aai_data, use_oof_cache, if_close_loop_vfw, new_version)
1267 print("\nAnsible Inventory:")
1268 inventory = "[host]\nlocalhost ansible_connection=local\n"
1269 for key in ansible_inventory:
1270 inventory += str("[{}]\n").format(key)
1271 for host in ansible_inventory[key]:
1272 inventory += str("{}\n").format(ansible_inventory[key][host])
1275 f = open("Ansible_inventory", 'w+')
1279 _generate_cdt_payloads(aai_data)
1283 print("\nDistribute Traffic Workflow Execution:")
1285 _execute_lcm_requests({"requests": lcm_requests, "description": "Migrate vFW Traffic Conditionally"}, onap_ip, check_result)
1289 help = """\npython3 workflow.py <VNF-ID> <RANCHER-NODE-IP> <K8S-NODE-IP> <IF-CACHE> <IF-VFWCL> <INITIAL-ONLY> <CHECK-STATUS> <VERSION>
1290 \n<VNF-ID> - vnf-id of vFW VNF instance that traffic should be migrated out from
1291 <RANCHER-NODE-IP> - External IP of ONAP Rancher Node i.e. 10.12.5.160 (If Rancher Node is missing this is NFS node)
1292 <K8S-NODE-IP> - External IP of ONAP K8s Worker Node i.e. 10.12.5.212
1293 <IF-CACHE> - If script should use and build OOF response cache (cache it speed-ups further executions of script)
1294 <IF-VFWCL> - If instead of vFWDT service instance vFW or vFWCL one is used (should be False always)
1295 <INITIAL-ONLY> - If only configuration information will be collected (True for initial phase and False for full execution of workflow)
1296 <CHECK-STATUS> - If APPC LCM action status should be verified and FAILURE should stop workflow (when False FAILED status of LCM action does not stop execution of further LCM actions)
1297 <VERSION> - New version of vFW - for tests '1.0' or '2.0'. Ommit when traffic distribution only\n"""
1299 for key in sys.argv:
1300 if key == "-h" or key == "--help":
1305 if len(sys.argv) > 8:
1306 new_version = sys.argv[8]
1309 #vnf_id, Rancher node IP, K8s node IP, use OOF cache, if close loop vfw, if info_only, if check APPC result
1310 execute_workflow(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4].lower() == 'true', sys.argv[5].lower() == 'true',
1311 sys.argv[6].lower() == 'true', sys.argv[7].lower() == 'true', new_version)