X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_lcm%2Fns.py;h=5141f6d019cf9f900136144c9231f9593a563dcf;hb=588547c4feb0d220d8ab648304da60aac9a98dec;hp=dc53b98eb1b43406b3ead2299b66572b332c5985;hpb=a17d4f4dec424eecdf34ec3efe39a1795bcf2aea;p=osm%2FLCM.git diff --git a/osm_lcm/ns.py b/osm_lcm/ns.py index dc53b98..5141f6d 100644 --- a/osm_lcm/ns.py +++ b/osm_lcm/ns.py @@ -25,6 +25,7 @@ import json from jinja2 import Environment, Template, meta, TemplateError, TemplateNotFound, TemplateSyntaxError from osm_lcm import ROclient +from osm_lcm.ng_ro import NgRoClient, NgRoException from osm_lcm.lcm_utils import LcmException, LcmExceptionNoMgmtIP, LcmBase, deep_get, get_iterable, populate_dict from n2vc.k8s_helm_conn import K8sHelmConnector from n2vc.k8s_juju_conn import K8sJujuConnector @@ -35,13 +36,43 @@ from osm_common.fsbase import FsException from n2vc.n2vc_juju_conn import N2VCJujuConnector from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException +from osm_lcm.lcm_helm_conn import LCMHelmConn + from copy import copy, deepcopy from http import HTTPStatus from time import time from uuid import uuid4 from functools import partial -__author__ = "Alfonso Tierno" +__author__ = "Alfonso Tierno " + + +class N2VCJujuConnectorLCM(N2VCJujuConnector): + + async def create_execution_environment(self, namespace: str, db_dict: dict, reuse_ee_id: str = None, + progress_timeout: float = None, total_timeout: float = None, + artifact_path: str = None, vca_type: str = None) -> (str, dict): + # admit two new parameters, artifact_path and vca_type + if vca_type == "k8s_proxy_charm": + ee_id = await self.n2vc.install_k8s_proxy_charm( + charm_name=artifact_path[artifact_path.rfind("/") + 1:], + namespace=namespace, + artifact_path=artifact_path, + db_dict=db_dict) + return ee_id, None + else: + return await super().create_execution_environment( + namespace=namespace, db_dict=db_dict, reuse_ee_id=reuse_ee_id, + progress_timeout=progress_timeout, total_timeout=total_timeout) + + async def install_configuration_sw(self, ee_id: str, artifact_path: str, db_dict: dict, + progress_timeout: float = None, total_timeout: float = None, + config: dict = None, num_units: int = 1, vca_type: str = "lxc_proxy_charm"): + if vca_type == "k8s_proxy_charm": + return + return await super().install_configuration_sw( + ee_id=ee_id, artifact_path=artifact_path, db_dict=db_dict, progress_timeout=progress_timeout, + total_timeout=total_timeout, config=config, num_units=num_units) class NsLcm(LcmBase): @@ -49,8 +80,8 @@ class NsLcm(LcmBase): timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns timeout_ns_terminate = 1800 # default global timeout for un deployment a ns timeout_charm_delete = 10 * 60 - timeout_primitive = 10 * 60 # timeout for primitive execution - timeout_progress_primitive = 2 * 60 # timeout for some progress in a primitive execution + timeout_primitive = 30 * 60 # timeout for primitive execution + timeout_progress_primitive = 10 * 60 # timeout for some progress in a primitive execution SUBOPERATION_STATUS_NOT_FOUND = -1 SUBOPERATION_STATUS_NEW = -2 @@ -74,10 +105,11 @@ class NsLcm(LcmBase): self.lcm_tasks = lcm_tasks self.timeout = config["timeout"] self.ro_config = config["ro_config"] + self.ng_ro = config["ro_config"].get("ng") self.vca_config = config["VCA"].copy() # create N2VC connector - self.n2vc = N2VCJujuConnector( + self.n2vc = N2VCJujuConnectorLCM( db=self.db, fs=self.fs, log=self.logger, @@ -88,6 +120,17 @@ class NsLcm(LcmBase): on_update_db=self._on_update_n2vc_db ) + self.conn_helm_ee = LCMHelmConn( + db=self.db, + fs=self.fs, + log=self.logger, + loop=self.loop, + url=None, + username=None, + vca_config=self.vca_config, + on_update_db=self._on_update_n2vc_db + ) + self.k8sclusterhelm = K8sHelmConnector( kubectl_command=self.vca_config.get("kubectlpath"), helm_command=self.vca_config.get("helmpath"), @@ -112,8 +155,19 @@ class NsLcm(LcmBase): "juju-bundle": self.k8sclusterjuju, "juju": self.k8sclusterjuju, } + + self.vca_map = { + "lxc_proxy_charm": self.n2vc, + "native_charm": self.n2vc, + "k8s_proxy_charm": self.n2vc, + "helm": self.conn_helm_ee + } + # create RO client - self.RO = ROclient.ROClient(self.loop, **self.ro_config) + if self.ng_ro: + self.RO = NgRoClient(self.loop, **self.ro_config) + else: + self.RO = ROclient.ROClient(self.loop, **self.ro_config) def _on_update_ro_db(self, nsrs_id, ro_descriptor): @@ -756,6 +810,179 @@ class NsLcm(LcmBase): primitive_list.insert(config_position + 1, {"name": "verify-ssh-credentials", "parameter": []}) return primitive_list + async def _instantiate_ng_ro(self, logging_text, nsr_id, nsd, db_nsr, db_nslcmop, db_vnfrs, db_vnfds_ref, + n2vc_key_list, stage, start_deploy, timeout_ns_deploy): + nslcmop_id = db_nslcmop["_id"] + target = { + "name": db_nsr["name"], + "ns": {"vld": []}, + "vnf": [], + "image": deepcopy(db_nsr["image"]), + "flavor": deepcopy(db_nsr["flavor"]), + "action_id": nslcmop_id, + } + for image in target["image"]: + image["vim_info"] = [] + for flavor in target["flavor"]: + flavor["vim_info"] = [] + + ns_params = db_nslcmop.get("operationParams") + ssh_keys = [] + if ns_params.get("ssh_keys"): + ssh_keys += ns_params.get("ssh_keys") + if n2vc_key_list: + ssh_keys += n2vc_key_list + + cp2target = {} + for vld_index, vld in enumerate(nsd.get("vld")): + target_vld = {"id": vld["id"], + "name": vld["name"], + "mgmt-network": vld.get("mgmt-network", False), + "type": vld.get("type"), + "vim_info": [{"vim-network-name": vld.get("vim-network-name"), + "vim_account_id": ns_params["vimAccountId"]}], + } + for cp in vld["vnfd-connection-point-ref"]: + cp2target["member_vnf:{}.{}".format(cp["member-vnf-index-ref"], cp["vnfd-connection-point-ref"])] = \ + "nsrs:{}:vld.{}".format(nsr_id, vld_index) + target["ns"]["vld"].append(target_vld) + for vnfr in db_vnfrs.values(): + vnfd = db_vnfds_ref[vnfr["vnfd-ref"]] + target_vnf = deepcopy(vnfr) + for vld in target_vnf.get("vld", ()): + # check if connected to a ns.vld + vnf_cp = next((cp for cp in vnfd.get("connection-point", ()) if + cp.get("internal-vld-ref") == vld["id"]), None) + if vnf_cp: + ns_cp = "member_vnf:{}.{}".format(vnfr["member-vnf-index-ref"], vnf_cp["id"]) + if cp2target.get(ns_cp): + vld["target"] = cp2target[ns_cp] + vld["vim_info"] = [{"vim-network-name": vld.get("vim-network-name"), + "vim_account_id": vnfr["vim-account-id"]}] + + for vdur in target_vnf.get("vdur", ()): + vdur["vim_info"] = [{"vim_account_id": vnfr["vim-account-id"]}] + vdud_index, vdud = next(k for k in enumerate(vnfd["vdu"]) if k[1]["id"] == vdur["vdu-id-ref"]) + # vdur["additionalParams"] = vnfr.get("additionalParamsForVnf") # TODO additional params for VDU + + if ssh_keys: + if deep_get(vdud, ("vdu-configuration", "config-access", "ssh-access", "required")): + vdur["ssh-keys"] = ssh_keys + vdur["ssh-access-required"] = True + elif deep_get(vnfd, ("vnf-configuration", "config-access", "ssh-access", "required")) and \ + any(iface.get("mgmt-vnf") for iface in vdur["interfaces"]): + vdur["ssh-keys"] = ssh_keys + vdur["ssh-access-required"] = True + + # cloud-init + if vdud.get("cloud-init-file"): + vdur["cloud-init"] = "{}:file:{}".format(vnfd["_id"], vdud.get("cloud-init-file")) + elif vdud.get("cloud-init"): + vdur["cloud-init"] = "{}:vdu:{}".format(vnfd["_id"], vdud_index) + + # flavor + ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])] + if not next((vi for vi in ns_flavor["vim_info"] if + vi and vi.get("vim_account_id") == vnfr["vim-account-id"]), None): + ns_flavor["vim_info"].append({"vim_account_id": vnfr["vim-account-id"]}) + # image + ns_image = target["image"][int(vdur["ns-image-id"])] + if not next((vi for vi in ns_image["vim_info"] if + vi and vi.get("vim_account_id") == vnfr["vim-account-id"]), None): + ns_image["vim_info"].append({"vim_account_id": vnfr["vim-account-id"]}) + + vdur["vim_info"] = [{"vim_account_id": vnfr["vim-account-id"]}] + target["vnf"].append(target_vnf) + + desc = await self.RO.deploy(nsr_id, target) + action_id = desc["action_id"] + await self._wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage) + + # Updating NSR + db_nsr_update = { + "_admin.deployed.RO.operational-status": "running", + "detailed-status": " ".join(stage) + } + # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM" + self.update_db_2("nsrs", nsr_id, db_nsr_update) + self._write_op_status(nslcmop_id, stage) + self.logger.debug(logging_text + "ns deployed at RO. RO_id={}".format(action_id)) + return + + async def _wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_time, timeout, stage): + detailed_status_old = None + db_nsr_update = {} + while time() <= start_time + timeout: + desc_status = await self.RO.status(nsr_id, action_id) + if desc_status["status"] == "FAILED": + raise NgRoException(desc_status["details"]) + elif desc_status["status"] == "BUILD": + stage[2] = "VIM: ({})".format(desc_status["details"]) + elif desc_status["status"] == "DONE": + stage[2] = "Deployed at VIM" + break + else: + assert False, "ROclient.check_ns_status returns unknown {}".format(desc_status["status"]) + if stage[2] != detailed_status_old: + detailed_status_old = stage[2] + db_nsr_update["detailed-status"] = " ".join(stage) + self.update_db_2("nsrs", nsr_id, db_nsr_update) + self._write_op_status(nslcmop_id, stage) + await asyncio.sleep(5, loop=self.loop) + else: # timeout_ns_deploy + raise NgRoException("Timeout waiting ns to deploy") + + async def _terminate_ng_ro(self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage): + db_nsr_update = {} + failed_detail = [] + action_id = None + start_deploy = time() + try: + target = { + "ns": {"vld": []}, + "vnf": [], + "image": [], + "flavor": [], + } + desc = await self.RO.deploy(nsr_id, target) + action_id = desc["action_id"] + db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id + db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING" + self.logger.debug(logging_text + "ns terminate action at RO. action_id={}".format(action_id)) + + # wait until done + delete_timeout = 20 * 60 # 20 minutes + await self._wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage) + + db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None + db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED" + # delete all nsr + await self.RO.delete(nsr_id) + except Exception as e: + if isinstance(e, NgRoException) and e.http_code == 404: # not found + db_nsr_update["_admin.deployed.RO.nsr_id"] = None + db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED" + db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None + self.logger.debug(logging_text + "RO_action_id={} already deleted".format(action_id)) + elif isinstance(e, NgRoException) and e.http_code == 409: # conflict + failed_detail.append("delete conflict: {}".format(e)) + self.logger.debug(logging_text + "RO_action_id={} delete conflict: {}".format(action_id, e)) + else: + failed_detail.append("delete error: {}".format(e)) + self.logger.error(logging_text + "RO_action_id={} delete error: {}".format(action_id, e)) + + if failed_detail: + stage[2] = "Error deleting from VIM" + else: + stage[2] = "Deleted from VIM" + db_nsr_update["detailed-status"] = " ".join(stage) + self.update_db_2("nsrs", nsr_id, db_nsr_update) + self._write_op_status(nslcmop_id, stage) + + if failed_detail: + raise LcmException("; ".join(failed_detail)) + return + async def instantiate_RO(self, logging_text, nsr_id, nsd, db_nsr, db_nslcmop, db_vnfrs, db_vnfds_ref, n2vc_key_list, stage): """ @@ -793,6 +1020,10 @@ class NsLcm(LcmBase): else: ns_params["vimAccountId"] == vnfr["vim-account-id"] + if self.ng_ro: + return await self._instantiate_ng_ro(logging_text, nsr_id, nsd, db_nsr, db_nslcmop, db_vnfrs, + db_vnfds_ref, n2vc_key_list, stage, start_deploy, + timeout_ns_deploy) # deploy RO # get vnfds, instantiate at RO for c_vnf in nsd.get("constituent-vnfd", ()): @@ -988,7 +1219,7 @@ class NsLcm(LcmBase): self._write_op_status(nslcmop_id, stage) # await self._on_update_n2vc_db("nsrs", {"_id": nsr_id}, "_admin.deployed", db_nsr_update) # self.logger.debug(logging_text + "Deployed at VIM") - except (ROclient.ROClientException, LcmException, DbException) as e: + except (ROclient.ROClientException, LcmException, DbException, NgRoException) as e: stage[2] = "ERROR deploying at VIM" self.set_vnfr_at_error(db_vnfrs, str(e)) raise @@ -1068,21 +1299,29 @@ class NsLcm(LcmBase): return ip_address try: ro_vm_id = "{}-{}".format(db_vnfr["member-vnf-index-ref"], target_vdu_id) # TODO add vdu_index - result_dict = await self.RO.create_action( - item="ns", - item_id_name=ro_nsr_id, - descriptor={"add_public_key": pub_key, "vms": [ro_vm_id], "user": user} - ) - # result_dict contains the format {VM-id: {vim_result: 200, description: text}} - if not result_dict or not isinstance(result_dict, dict): - raise LcmException("Unknown response from RO when injecting key") - for result in result_dict.values(): - if result.get("vim_result") == 200: - break - else: - raise ROclient.ROClientException("error injecting key: {}".format( - result.get("description"))) - break + if self.ng_ro: + target = {"action": "inject_ssh_key", "key": pub_key, "user": user, + "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdu_id}]}], + } + await self.RO.deploy(nsr_id, target) + else: + result_dict = await self.RO.create_action( + item="ns", + item_id_name=ro_nsr_id, + descriptor={"add_public_key": pub_key, "vms": [ro_vm_id], "user": user} + ) + # result_dict contains the format {VM-id: {vim_result: 200, description: text}} + if not result_dict or not isinstance(result_dict, dict): + raise LcmException("Unknown response from RO when injecting key") + for result in result_dict.values(): + if result.get("vim_result") == 200: + break + else: + raise ROclient.ROClientException("error injecting key: {}".format( + result.get("description"))) + break + except NgRoException as e: + raise LcmException("Reaching max tries injecting key. Error: {}".format(e)) except ROclient.ROClientException as e: if not nb_tries: self.logger.debug(logging_text + "error injecting key: {}. Retrying until {} seconds". @@ -1130,7 +1369,7 @@ class NsLcm(LcmBase): raise LcmException("Configuration aborted because dependent charm/s timeout") async def instantiate_N2VC(self, logging_text, vca_index, nsi_id, db_nsr, db_vnfr, vdu_id, kdu_name, vdu_index, - config_descriptor, deploy_params, base_folder, nslcmop_id, stage): + config_descriptor, deploy_params, base_folder, nslcmop_id, stage, vca_type, vca_name): nsr_id = db_nsr["_id"] db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index) vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"] @@ -1168,24 +1407,20 @@ class NsLcm(LcmBase): element_under_configuration = kdu_name # Get artifact path - self.fs.sync() # Sync from FSMongo - artifact_path = "{}/{}/charms/{}".format( + artifact_path = "{}/{}/{}/{}".format( base_folder["folder"], base_folder["pkg-dir"], - config_descriptor["juju"]["charm"] + "charms" if vca_type in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm") else "helm-charts", + vca_name ) - is_proxy_charm = deep_get(config_descriptor, ('juju', 'charm')) is not None - if deep_get(config_descriptor, ('juju', 'proxy')) is False: - is_proxy_charm = False - # n2vc_redesign STEP 3.1 # find old ee_id if exists ee_id = vca_deployed.get("ee_id") # create or register execution environment in VCA - if is_proxy_charm: + if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm"): self._write_configuration_status( nsr_id=nsr_id, @@ -1197,11 +1432,14 @@ class NsLcm(LcmBase): step = "create execution environment" self.logger.debug(logging_text + step) - ee_id, credentials = await self.n2vc.create_execution_environment(namespace=namespace, - reuse_ee_id=ee_id, - db_dict=db_dict) - - else: + ee_id, credentials = await self.vca_map[vca_type].create_execution_environment( + namespace=namespace, + reuse_ee_id=ee_id, + db_dict=db_dict, + artifact_path=artifact_path, + vca_type=vca_type) + + elif vca_type == "native_charm": step = "Waiting to VM being up and getting IP address" self.logger.debug(logging_text + step) rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, @@ -1233,20 +1471,20 @@ class NsLcm(LcmBase): step = "register execution environment {}".format(credentials) self.logger.debug(logging_text + step) - ee_id = await self.n2vc.register_execution_environment(credentials=credentials, namespace=namespace, - db_dict=db_dict) + ee_id = await self.vca_map[vca_type].register_execution_environment( + credentials=credentials, namespace=namespace, db_dict=db_dict) # for compatibility with MON/POL modules, the need model and application name at database - # TODO ask to N2VC instead of assuming the format "model_name.application_name" + # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name" ee_id_parts = ee_id.split('.') - model_name = ee_id_parts[0] - application_name = ee_id_parts[1] - db_nsr_update = {db_update_entry + "model": model_name, - db_update_entry + "application": application_name, - db_update_entry + "ee_id": ee_id} + db_nsr_update = {db_update_entry + "ee_id": ee_id} + if len(ee_id_parts) >= 2: + model_name = ee_id_parts[0] + application_name = ee_id_parts[1] + db_nsr_update[db_update_entry + "model"] = model_name + db_nsr_update[db_update_entry + "application"] = application_name # n2vc_redesign STEP 3.3 - step = "Install configuration Software" self._write_configuration_status( @@ -1261,7 +1499,7 @@ class NsLcm(LcmBase): # TODO check if already done self.logger.debug(logging_text + step) config = None - if not is_proxy_charm: + if vca_type == "native_charm": initial_config_primitive_list = config_descriptor.get('initial-config-primitive') if initial_config_primitive_list: for primitive in initial_config_primitive_list: @@ -1272,31 +1510,49 @@ class NsLcm(LcmBase): deploy_params ) break - await self.n2vc.install_configuration_sw( + num_units = 1 + if vca_type == "lxc_proxy_charm": + if element_type == "NS": + num_units = db_nsr.get("config-units") or 1 + elif element_type == "VNF": + num_units = db_vnfr.get("config-units") or 1 + elif element_type == "VDU": + for v in db_vnfr["vdur"]: + if vdu_id == v["vdu-id-ref"]: + num_units = v.get("config-units") or 1 + break + + await self.vca_map[vca_type].install_configuration_sw( ee_id=ee_id, artifact_path=artifact_path, db_dict=db_dict, - config=config + config=config, + num_units=num_units, + vca_type=vca_type ) # write in db flag of configuration_sw already installed self.update_db_2("nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}) # add relations for this VCA (wait for other peers related with this VCA) - await self._add_vca_relations(logging_text=logging_text, nsr_id=nsr_id, vca_index=vca_index) + await self._add_vca_relations(logging_text=logging_text, nsr_id=nsr_id, + vca_index=vca_index, vca_type=vca_type) # if SSH access is required, then get execution environment SSH public - if is_proxy_charm: # if native charm we have waited already to VM be UP + if vca_type in ("lxc_proxy_charm", "helm"): # if native charm we have waited already to VM be UP pub_key = None user = None + # self.logger.debug("get ssh key block") if deep_get(config_descriptor, ("config-access", "ssh-access", "required")): + # self.logger.debug("ssh key needed") # Needed to inject a ssh key user = deep_get(config_descriptor, ("config-access", "ssh-access", "default-user")) step = "Install configuration Software, getting public ssh key" - pub_key = await self.n2vc.get_ee_ssh_public__key(ee_id=ee_id, db_dict=db_dict) + pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(ee_id=ee_id, db_dict=db_dict) step = "Insert public key into VM user={} ssh_key={}".format(user, pub_key) else: + # self.logger.debug("no need to get ssh key") step = "Waiting to VM being up and getting IP address" self.logger.debug(logging_text + step) @@ -1367,7 +1623,7 @@ class NsLcm(LcmBase): step = "execute primitive '{}' params '{}'".format(initial_config_primitive["name"], primitive_params_) self.logger.debug(logging_text + step) - await self.n2vc.exec_primitive( + await self.vca_map[vca_type].exec_primitive( ee_id=ee_id, primitive_name=initial_config_primitive["name"], params_dict=primitive_params_, @@ -1548,6 +1804,9 @@ class NsLcm(LcmBase): logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id) self.logger.debug(logging_text + "Enter") + # Sync from FSMongo + self.fs.sync() + # get all needed from database # database nsrs record @@ -1603,8 +1862,9 @@ class NsLcm(LcmBase): # read from db: ns stage[1] = "Getting nsr={} from db".format(nsr_id) db_nsr = self.db.get_one("nsrs", {"_id": nsr_id}) - # nsd is replicated into ns (no db read) - nsd = db_nsr["nsd"] + stage[1] = "Getting nsd={} from db".format(db_nsr["nsd-id"]) + nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]}) + db_nsr["nsd"] = nsd # nsr_name = db_nsr["name"] # TODO short-name?? # read from db: vnf's of this ns @@ -1726,7 +1986,7 @@ class NsLcm(LcmBase): deploy_params = self._format_additional_params(db_vnfr["additionalParamsForVnf"].copy()) descriptor_config = vnfd.get("vnf-configuration") - if descriptor_config and descriptor_config.get("juju"): + if descriptor_config: self._deploy_n2vc( logging_text=logging_text + "member_vnf_index={} ".format(member_vnf_index), db_nsr=db_nsr, @@ -1756,7 +2016,7 @@ class NsLcm(LcmBase): deploy_params_vdu = self._format_additional_params(vdur["additionalParams"]) else: deploy_params_vdu = deploy_params - if descriptor_config and descriptor_config.get("juju"): + if descriptor_config: # look for vdu index in the db_vnfr["vdu"] section # for vdur_index, vdur in enumerate(db_vnfr["vdur"]): # if vdur["vdu-id-ref"] == vdu_id: @@ -1792,7 +2052,7 @@ class NsLcm(LcmBase): for kdud in get_iterable(vnfd, 'kdu'): kdu_name = kdud["name"] descriptor_config = kdud.get('kdu-configuration') - if descriptor_config and descriptor_config.get("juju"): + if descriptor_config: vdu_id = None vdu_index = 0 vdu_name = None @@ -1951,7 +2211,8 @@ class NsLcm(LcmBase): self.logger.debug(logging_text + "Exit") self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate") - async def _add_vca_relations(self, logging_text, nsr_id, vca_index: int, timeout: int = 3600) -> bool: + async def _add_vca_relations(self, logging_text, nsr_id, vca_index: int, + timeout: int = 3600, vca_type: str = None) -> bool: # steps: # 1. find all relations for this VCA @@ -1959,18 +2220,20 @@ class NsLcm(LcmBase): # 3. add relations try: + vca_type = vca_type or "lxc_proxy_charm" # STEP 1: find all relations for this VCA # read nsr record db_nsr = self.db.get_one("nsrs", {"_id": nsr_id}) + nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]}) # this VCA data my_vca = deep_get(db_nsr, ('_admin', 'deployed', 'VCA'))[vca_index] # read all ns-configuration relations ns_relations = list() - db_ns_relations = deep_get(db_nsr, ('nsd', 'ns-configuration', 'relation')) + db_ns_relations = deep_get(nsd, ('ns-configuration', 'relation')) if db_ns_relations: for r in db_ns_relations: # check if this VCA is in the relation @@ -2028,7 +2291,7 @@ class NsLcm(LcmBase): to_vca_endpoint = r.get('entities')[1].get('endpoint') if from_vca_ee_id and to_vca_ee_id: # add relation - await self.n2vc.add_relation( + await self.vca_map[vca_type].add_relation( ee_id_1=from_vca_ee_id, ee_id_2=to_vca_ee_id, endpoint_1=from_vca_endpoint, @@ -2071,7 +2334,7 @@ class NsLcm(LcmBase): to_vca_endpoint = r.get('entities')[1].get('endpoint') if from_vca_ee_id and to_vca_ee_id: # add relation - await self.n2vc.add_relation( + await self.vca_map[vca_type].add_relation( ee_id_1=from_vca_ee_id, ee_id_2=to_vca_ee_id, endpoint_1=from_vca_endpoint, @@ -2178,7 +2441,7 @@ class NsLcm(LcmBase): storage = deep_get(db_vnfds.get(vnfd_id), ('_admin', 'storage')) if storage and storage.get('pkg-dir'): # may be not present if vnfd has not artifacts # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel - filename = '{}/{}/{}s/{}'.format(storage["folder"], storage["'pkg-dir"], k8sclustertype, + filename = '{}/{}/{}s/{}'.format(storage["folder"], storage["pkg-dir"], k8sclustertype, kdumodel) if self.fs.file_exists(filename, mode='file') or self.fs.file_exists(filename, mode='dir'): kdumodel = self.fs.path + filename @@ -2255,62 +2518,90 @@ class NsLcm(LcmBase): # launch instantiate_N2VC in a asyncio task and register task object # Look where information of this charm is at database ._admin.deployed.VCA # if not found, create one entry and update database - # fill db_nsr._admin.deployed.VCA. - vca_index = -1 - for vca_index, vca_deployed in enumerate(db_nsr["_admin"]["deployed"]["VCA"]): - if not vca_deployed: - continue - if vca_deployed.get("member-vnf-index") == member_vnf_index and \ - vca_deployed.get("vdu_id") == vdu_id and \ - vca_deployed.get("kdu_name") == kdu_name and \ - vca_deployed.get("vdu_count_index", 0) == vdu_index: - break - else: - # not found, create one. - vca_deployed = { - "member-vnf-index": member_vnf_index, - "vdu_id": vdu_id, - "kdu_name": kdu_name, - "vdu_count_index": vdu_index, - "operational-status": "init", # TODO revise - "detailed-status": "", # TODO revise - "step": "initial-deploy", # TODO revise - "vnfd_id": vnfd_id, - "vdu_name": vdu_name, - } - vca_index += 1 - - # create VCA and configurationStatus in db - db_dict = { - "_admin.deployed.VCA.{}".format(vca_index): vca_deployed, - "configurationStatus.{}".format(vca_index): dict() - } - self.update_db_2("nsrs", nsr_id, db_dict) - db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed) + self.logger.debug(logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)) + if descriptor_config.get("juju"): # There is one execution envioronment of type juju + ee_list = [descriptor_config] + elif descriptor_config.get("execution-environment-list"): + ee_list = descriptor_config.get("execution-environment-list") + else: # other types as script are not supported + ee_list = [] + + for ee_item in ee_list: + self.logger.debug(logging_text + "_deploy_n2vc ee_item juju={}, helm={}".format(ee_item.get('juju'), + ee_item.get("helm-chart"))) + if ee_item.get("juju"): + vca_name = ee_item['juju'].get('charm') + vca_type = "lxc_proxy_charm" if ee_item['juju'].get('charm') is not None else "native_charm" + if ee_item['juju'].get('cloud') == "k8s": + vca_type = "k8s_proxy_charm" + elif ee_item['juju'].get('proxy') is False: + vca_type = "native_charm" + elif ee_item.get("helm-chart"): + vca_name = ee_item['helm-chart'] + vca_type = "helm" + else: + self.logger.debug(logging_text + "skipping non juju neither charm configuration") + continue - # Launch task - task_n2vc = asyncio.ensure_future( - self.instantiate_N2VC( - logging_text=logging_text, - vca_index=vca_index, - nsi_id=nsi_id, - db_nsr=db_nsr, - db_vnfr=db_vnfr, - vdu_id=vdu_id, - kdu_name=kdu_name, - vdu_index=vdu_index, - deploy_params=deploy_params, - config_descriptor=descriptor_config, - base_folder=base_folder, - nslcmop_id=nslcmop_id, - stage=stage + vca_index = -1 + for vca_index, vca_deployed in enumerate(db_nsr["_admin"]["deployed"]["VCA"]): + if not vca_deployed: + continue + if vca_deployed.get("member-vnf-index") == member_vnf_index and \ + vca_deployed.get("vdu_id") == vdu_id and \ + vca_deployed.get("kdu_name") == kdu_name and \ + vca_deployed.get("vdu_count_index", 0) == vdu_index: + break + else: + # not found, create one. + vca_deployed = { + "member-vnf-index": member_vnf_index, + "vdu_id": vdu_id, + "kdu_name": kdu_name, + "vdu_count_index": vdu_index, + "operational-status": "init", # TODO revise + "detailed-status": "", # TODO revise + "step": "initial-deploy", # TODO revise + "vnfd_id": vnfd_id, + "vdu_name": vdu_name, + "type": vca_type + } + vca_index += 1 + + # create VCA and configurationStatus in db + db_dict = { + "_admin.deployed.VCA.{}".format(vca_index): vca_deployed, + "configurationStatus.{}".format(vca_index): dict() + } + self.update_db_2("nsrs", nsr_id, db_dict) + + db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed) + + # Launch task + task_n2vc = asyncio.ensure_future( + self.instantiate_N2VC( + logging_text=logging_text, + vca_index=vca_index, + nsi_id=nsi_id, + db_nsr=db_nsr, + db_vnfr=db_vnfr, + vdu_id=vdu_id, + kdu_name=kdu_name, + vdu_index=vdu_index, + deploy_params=deploy_params, + config_descriptor=descriptor_config, + base_folder=base_folder, + nslcmop_id=nslcmop_id, + stage=stage, + vca_type=vca_type, + vca_name=vca_name + ) ) - ) - self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_N2VC-{}".format(vca_index), task_n2vc) - task_instantiation_info[task_n2vc] = self.task_name_deploy_vca + " {}.{}".format( - member_vnf_index or "", vdu_id or "") + self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_N2VC-{}".format(vca_index), task_n2vc) + task_instantiation_info[task_n2vc] = self.task_name_deploy_vca + " {}.{}".format( + member_vnf_index or "", vdu_id or "") # Check if this VNFD has a configured terminate action def _has_terminate_config_primitive(self, vnfd): @@ -2391,9 +2682,9 @@ class NsLcm(LcmBase): # _ns_execute_primitive() or RO.create_action() will NOT be executed return self.SUBOPERATION_STATUS_SKIP else: - # c. Reintent executing sub-operation + # c. retry executing sub-operation # The sub-operation exists, and operationState != 'COMPLETED' - # Update operationState = 'PROCESSING' to indicate a reintent. + # Update operationState = 'PROCESSING' to indicate a retry. operationState = 'PROCESSING' detailed_status = 'In progress' self._update_suboperation_status( @@ -2406,7 +2697,7 @@ class NsLcm(LcmBase): # Find a sub-operation where all keys in a matching dictionary must match # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match def _find_suboperation(self, db_nslcmop, match): - if (db_nslcmop and match): + if db_nslcmop and match: op_list = db_nslcmop.get('_admin', {}).get('operations', []) for i, op in enumerate(op_list): if all(op.get(k) == match[k] for k in match): @@ -2474,11 +2765,11 @@ class NsLcm(LcmBase): # Check for 3 different cases: # a. New: First time execution, return SUBOPERATION_STATUS_NEW # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP - # c. Reintent: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute + # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute def _check_or_add_scale_suboperation(self, db_nslcmop, vnf_index, vnf_config_primitive, primitive_params, operationType, RO_nsr_id=None, RO_scaling_info=None): # Find this sub-operation - if (RO_nsr_id and RO_scaling_info): + if RO_nsr_id and RO_scaling_info: operationType = 'SCALE-RO' match = { 'member_vnf_index': vnf_index, @@ -2537,7 +2828,8 @@ class NsLcm(LcmBase): if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id: return vca["ee_id"] - async def destroy_N2VC(self, logging_text, db_nslcmop, vca_deployed, config_descriptor, vca_index, destroy_ee=True): + async def destroy_N2VC(self, logging_text, db_nslcmop, vca_deployed, config_descriptor, + vca_index, destroy_ee=True, exec_primitives=True): """ Execute the terminate primitives and destroy the execution environment (if destroy_ee=False :param logging_text: @@ -2546,53 +2838,66 @@ class NsLcm(LcmBase): :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu :param vca_index: index in the database _admin.deployed.VCA :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once + :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has + not executed properly :return: None or exception """ + + self.logger.debug( + logging_text + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format( + vca_index, vca_deployed, config_descriptor, destroy_ee + ) + ) + + vca_type = vca_deployed.get("type", "lxc_proxy_charm") + # execute terminate_primitives - terminate_primitives = config_descriptor.get("terminate-config-primitive") - vdu_id = vca_deployed.get("vdu_id") - vdu_count_index = vca_deployed.get("vdu_count_index") - vdu_name = vca_deployed.get("vdu_name") - vnf_index = vca_deployed.get("member-vnf-index") - if terminate_primitives and vca_deployed.get("needed_terminate"): - # Get all 'seq' tags in seq_list, order sequences numerically, ascending. - terminate_primitives = sorted(terminate_primitives, key=lambda x: int(x['seq'])) - for seq in terminate_primitives: - # For each sequence in list, get primitive and call _ns_execute_primitive() - step = "Calling terminate action for vnf_member_index={} primitive={}".format( - vnf_index, seq.get("name")) - self.logger.debug(logging_text + step) - # Create the primitive for each sequence, i.e. "primitive": "touch" - primitive = seq.get('name') - mapped_primitive_params = self._get_terminate_primitive_params(seq, vnf_index) - # The following 3 parameters are currently set to None for 'terminate': - # vdu_id, vdu_count_index, vdu_name - - # Add sub-operation - self._add_suboperation(db_nslcmop, - vnf_index, - vdu_id, - vdu_count_index, - vdu_name, - primitive, - mapped_primitive_params) - # Sub-operations: Call _ns_execute_primitive() instead of action() - try: - result, result_detail = await self._ns_execute_primitive(vca_deployed["ee_id"], primitive, - mapped_primitive_params) - except LcmException: - # this happens when VCA is not deployed. In this case it is not needed to terminate - continue - result_ok = ['COMPLETED', 'PARTIALLY_COMPLETED'] - if result not in result_ok: - raise LcmException("terminate_primitive {} for vnf_member_index={} fails with " - "error {}".format(seq.get("name"), vnf_index, result_detail)) - # set that this VCA do not need terminated - db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(vca_index) - self.update_db_2("nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}) + if exec_primitives: + terminate_primitives = config_descriptor.get("terminate-config-primitive") + vdu_id = vca_deployed.get("vdu_id") + vdu_count_index = vca_deployed.get("vdu_count_index") + vdu_name = vca_deployed.get("vdu_name") + vnf_index = vca_deployed.get("member-vnf-index") + if terminate_primitives and vca_deployed.get("needed_terminate"): + # Get all 'seq' tags in seq_list, order sequences numerically, ascending. + terminate_primitives = sorted(terminate_primitives, key=lambda x: int(x['seq'])) + for seq in terminate_primitives: + # For each sequence in list, get primitive and call _ns_execute_primitive() + step = "Calling terminate action for vnf_member_index={} primitive={}".format( + vnf_index, seq.get("name")) + self.logger.debug(logging_text + step) + # Create the primitive for each sequence, i.e. "primitive": "touch" + primitive = seq.get('name') + mapped_primitive_params = self._get_terminate_primitive_params(seq, vnf_index) + # The following 3 parameters are currently set to None for 'terminate': + # vdu_id, vdu_count_index, vdu_name + + # Add sub-operation + self._add_suboperation(db_nslcmop, + vnf_index, + vdu_id, + vdu_count_index, + vdu_name, + primitive, + mapped_primitive_params) + # Sub-operations: Call _ns_execute_primitive() instead of action() + try: + result, result_detail = await self._ns_execute_primitive(vca_deployed["ee_id"], primitive, + mapped_primitive_params, + vca_type=vca_type) + except LcmException: + # this happens when VCA is not deployed. In this case it is not needed to terminate + continue + result_ok = ['COMPLETED', 'PARTIALLY_COMPLETED'] + if result not in result_ok: + raise LcmException("terminate_primitive {} for vnf_member_index={} fails with " + "error {}".format(seq.get("name"), vnf_index, result_detail)) + # set that this VCA do not need terminated + db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(vca_index) + self.update_db_2("nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}) if destroy_ee: - await self.n2vc.delete_execution_environment(vca_deployed["ee_id"]) + await self.vca_map[vca_type].delete_execution_environment(vca_deployed["ee_id"]) async def _delete_all_N2VC(self, db_nsr: dict): self._write_all_config_status(db_nsr=db_nsr, status='TERMINATING') @@ -2810,42 +3115,56 @@ class NsLcm(LcmBase): # Destroy individual execution environments when there are terminating primitives. # Rest of EE will be deleted at once - if not operation_params.get("skip_terminate_primitives"): - stage[0] = "Stage 2/3 execute terminating primitives." - stage[1] = "Looking execution environment that needs terminate." - self.logger.debug(logging_text + stage[1]) - for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")): - config_descriptor = None - if not vca or not vca.get("ee_id") or not vca.get("needed_terminate"): - continue - if not vca.get("member-vnf-index"): - # ns - config_descriptor = db_nsr.get("ns-configuration") - elif vca.get("vdu_id"): - db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]] - vdud = next((vdu for vdu in db_vnfd.get("vdu", ()) if vdu["id"] == vca.get("vdu_id")), None) - if vdud: - config_descriptor = vdud.get("vdu-configuration") - elif vca.get("kdu_name"): - db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]] - kdud = next((kdu for kdu in db_vnfd.get("kdu", ()) if kdu["name"] == vca.get("kdu_name")), None) - if kdud: - config_descriptor = kdud.get("kdu-configuration") - else: - config_descriptor = db_vnfds_from_member_index[vca["member-vnf-index"]].get("vnf-configuration") + # TODO - check before calling _destroy_N2VC + # if not operation_params.get("skip_terminate_primitives"):# + # or not vca.get("needed_terminate"): + stage[0] = "Stage 2/3 execute terminating primitives." + self.logger.debug(logging_text + stage[0]) + stage[1] = "Looking execution environment that needs terminate." + self.logger.debug(logging_text + stage[1]) + self.logger.debug("nsr_deployed: {}".format(nsr_deployed)) + for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")): + self.logger.debug("vca_index: {}, vca: {}".format(vca_index, vca)) + config_descriptor = None + if not vca or not vca.get("ee_id"): + continue + if not vca.get("member-vnf-index"): + # ns + config_descriptor = db_nsr.get("ns-configuration") + elif vca.get("vdu_id"): + db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]] + vdud = next((vdu for vdu in db_vnfd.get("vdu", ()) if vdu["id"] == vca.get("vdu_id")), None) + if vdud: + config_descriptor = vdud.get("vdu-configuration") + elif vca.get("kdu_name"): + db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]] + kdud = next((kdu for kdu in db_vnfd.get("kdu", ()) if kdu["name"] == vca.get("kdu_name")), None) + if kdud: + config_descriptor = kdud.get("kdu-configuration") + else: + config_descriptor = db_vnfds_from_member_index[vca["member-vnf-index"]].get("vnf-configuration") + # For helm we must destroy_ee + vca_type = vca.get("type") + exec_terminate_primitives = (not operation_params.get("skip_terminate_primitives") and + vca.get("needed_terminate")) + self.logger.debug("vca type: {}".format(vca_type)) + if not vca_type == "helm": task = asyncio.ensure_future(self.destroy_N2VC(logging_text, db_nslcmop, vca, config_descriptor, - vca_index, False)) - tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id")) - - # wait for pending tasks of terminate primitives - if tasks_dict_info: - self.logger.debug(logging_text + 'Waiting for terminate primitive pending tasks...') - error_list = await self._wait_for_tasks(logging_text, tasks_dict_info, - min(self.timeout_charm_delete, timeout_ns_terminate), - stage, nslcmop_id) - if error_list: - return # raise LcmException("; ".join(error_list)) - tasks_dict_info.clear() + vca_index, False, exec_terminate_primitives)) + else: + task = asyncio.ensure_future(self.destroy_N2VC(logging_text, db_nslcmop, vca, config_descriptor, + vca_index, True, exec_terminate_primitives)) + tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id")) + + # wait for pending tasks of terminate primitives + if tasks_dict_info: + self.logger.debug(logging_text + 'Waiting for terminate primitive pending tasks...') + error_list = await self._wait_for_tasks(logging_text, tasks_dict_info, + min(self.timeout_charm_delete, timeout_ns_terminate), + stage, nslcmop_id) + if error_list: + return # raise LcmException("; ".join(error_list)) + tasks_dict_info.clear() # remove All execution environments at once stage[0] = "Stage 3/3 delete all." @@ -2879,8 +3198,12 @@ class NsLcm(LcmBase): # remove from RO stage[1] = "Deleting ns from VIM." - task_delete_ro = asyncio.ensure_future( - self._terminate_RO(logging_text, nsr_deployed, nsr_id, nslcmop_id, stage)) + if self.ng_ro: + task_delete_ro = asyncio.ensure_future( + self._terminate_ng_ro(logging_text, nsr_deployed, nsr_id, nslcmop_id, stage)) + else: + task_delete_ro = asyncio.ensure_future( + self._terminate_RO(logging_text, nsr_deployed, nsr_id, nslcmop_id, stage)) tasks_dict_info[task_delete_ro] = "Removing deployment from VIM" # rest of staff will be done at finally @@ -3074,27 +3397,32 @@ class NsLcm(LcmBase): # get ee_id ee_id = vca.get("ee_id") + vca_type = vca.get("type", "lxc_proxy_charm") # default value for backward compatibility - proxy charm if not ee_id: raise LcmException("charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not " "execution environment" .format(member_vnf_index, vdu_id, kdu_name, vdu_count_index)) - return ee_id + return ee_id, vca_type async def _ns_execute_primitive(self, ee_id, primitive, primitive_params, retries=0, - retries_interval=30, timeout=None) -> (str, str): + retries_interval=30, timeout=None, + vca_type=None, db_dict=None) -> (str, str): try: if primitive == "config": primitive_params = {"params": primitive_params} + vca_type = vca_type or "lxc_proxy_charm" + while retries >= 0: try: output = await asyncio.wait_for( - self.n2vc.exec_primitive( + self.vca_map[vca_type].exec_primitive( ee_id=ee_id, primitive_name=primitive, params_dict=primitive_params, progress_timeout=self.timeout_progress_primitive, - total_timeout=self.timeout_primitive), + total_timeout=self.timeout_primitive, + db_dict=db_dict), timeout=timeout or self.timeout_primitive) # execution was OK break @@ -3295,14 +3623,20 @@ class NsLcm(LcmBase): detailed_status = '' nslcmop_operation_state = 'FAILED' else: + ee_id, vca_type = self._look_for_deployed_vca(nsr_deployed["VCA"], + member_vnf_index=vnf_index, + vdu_id=vdu_id, + vdu_count_index=vdu_count_index) + db_nslcmop_notif = {"collection": "nslcmops", + "filter": {"_id": nslcmop_id}, + "path": "admin.VCA"} nslcmop_operation_state, detailed_status = await self._ns_execute_primitive( - self._look_for_deployed_vca(nsr_deployed["VCA"], - member_vnf_index=vnf_index, - vdu_id=vdu_id, - vdu_count_index=vdu_count_index), + ee_id, primitive=primitive, primitive_params=self._map_primitive_params(config_primitive_desc, primitive_params, desc_params), - timeout=timeout_ns_action) + timeout=timeout_ns_action, + vca_type=vca_type, + db_dict=db_nslcmop_notif) db_nslcmop_update["detailed-status"] = detailed_status error_description_nslcmop = detailed_status if nslcmop_operation_state == "FAILED" else "" @@ -3540,10 +3874,10 @@ class NsLcm(LcmBase): db_nsr_update["config-status"] = "configuring pre-scaling" primitive_params = self._map_primitive_params(config_primitive, {}, vnfr_params) - # Pre-scale reintent check: Check if this sub-operation has been executed before + # Pre-scale retry check: Check if this sub-operation has been executed before op_index = self._check_or_add_scale_suboperation( db_nslcmop, nslcmop_id, vnf_index, vnf_config_primitive, primitive_params, 'PRE-SCALE') - if (op_index == self.SUBOPERATION_STATUS_SKIP): + if op_index == self.SUBOPERATION_STATUS_SKIP: # Skip sub-operation result = 'COMPLETED' result_detail = 'Done' @@ -3551,26 +3885,26 @@ class NsLcm(LcmBase): "vnf_config_primitive={} Skipped sub-operation, result {} {}".format( vnf_config_primitive, result, result_detail)) else: - if (op_index == self.SUBOPERATION_STATUS_NEW): + if op_index == self.SUBOPERATION_STATUS_NEW: # New sub-operation: Get index of this sub-operation op_index = len(db_nslcmop.get('_admin', {}).get('operations')) - 1 self.logger.debug(logging_text + "vnf_config_primitive={} New sub-operation". format(vnf_config_primitive)) else: - # Reintent: Get registered params for this existing sub-operation + # retry: Get registered params for this existing sub-operation op = db_nslcmop.get('_admin', {}).get('operations', [])[op_index] vnf_index = op.get('member_vnf_index') vnf_config_primitive = op.get('primitive') primitive_params = op.get('primitive_params') - self.logger.debug(logging_text + "vnf_config_primitive={} Sub-operation reintent". + self.logger.debug(logging_text + "vnf_config_primitive={} Sub-operation retry". format(vnf_config_primitive)) # Execute the primitive, either with new (first-time) or registered (reintent) args + ee_id, vca_type = self._look_for_deployed_vca(nsr_deployed["VCA"], + member_vnf_index=vnf_index, + vdu_id=None, + vdu_count_index=None) result, result_detail = await self._ns_execute_primitive( - self._look_for_deployed_vca(nsr_deployed["VCA"], - member_vnf_index=vnf_index, - vdu_id=None, - vdu_count_index=None), - vnf_config_primitive, primitive_params) + ee_id, vnf_config_primitive, primitive_params, vca_type) self.logger.debug(logging_text + "vnf_config_primitive={} Done with result {} {}".format( vnf_config_primitive, result, result_detail)) # Update operationState = COMPLETED | FAILED @@ -3588,26 +3922,26 @@ class NsLcm(LcmBase): # if (RO_nsr_id and RO_scaling_info): if RO_scaling_info: scale_process = "RO" - # Scale RO reintent check: Check if this sub-operation has been executed before + # Scale RO retry check: Check if this sub-operation has been executed before op_index = self._check_or_add_scale_suboperation( db_nslcmop, vnf_index, None, None, 'SCALE-RO', RO_nsr_id, RO_scaling_info) - if (op_index == self.SUBOPERATION_STATUS_SKIP): + if op_index == self.SUBOPERATION_STATUS_SKIP: # Skip sub-operation result = 'COMPLETED' result_detail = 'Done' self.logger.debug(logging_text + "Skipped sub-operation RO, result {} {}".format( result, result_detail)) else: - if (op_index == self.SUBOPERATION_STATUS_NEW): + if op_index == self.SUBOPERATION_STATUS_NEW: # New sub-operation: Get index of this sub-operation op_index = len(db_nslcmop.get('_admin', {}).get('operations')) - 1 self.logger.debug(logging_text + "New sub-operation RO") else: - # Reintent: Get registered params for this existing sub-operation + # retry: Get registered params for this existing sub-operation op = db_nslcmop.get('_admin', {}).get('operations', [])[op_index] RO_nsr_id = op.get('RO_nsr_id') RO_scaling_info = op.get('RO_scaling_info') - self.logger.debug(logging_text + "Sub-operation RO reintent".format( + self.logger.debug(logging_text + "Sub-operation RO retry for primitive {}".format( vnf_config_primitive)) RO_desc = await self.RO.create_action("ns", RO_nsr_id, {"vdu-scaling": RO_scaling_info}) @@ -3733,7 +4067,7 @@ class NsLcm(LcmBase): db_nsr_update["config-status"] = "configuring post-scaling" primitive_params = self._map_primitive_params(config_primitive, {}, vnfr_params) - # Post-scale reintent check: Check if this sub-operation has been executed before + # Post-scale retry check: Check if this sub-operation has been executed before op_index = self._check_or_add_scale_suboperation( db_nslcmop, nslcmop_id, vnf_index, vnf_config_primitive, primitive_params, 'POST-SCALE') if op_index == self.SUBOPERATION_STATUS_SKIP: @@ -3750,20 +4084,20 @@ class NsLcm(LcmBase): self.logger.debug(logging_text + "vnf_config_primitive={} New sub-operation". format(vnf_config_primitive)) else: - # Reintent: Get registered params for this existing sub-operation + # retry: Get registered params for this existing sub-operation op = db_nslcmop.get('_admin', {}).get('operations', [])[op_index] vnf_index = op.get('member_vnf_index') vnf_config_primitive = op.get('primitive') primitive_params = op.get('primitive_params') - self.logger.debug(logging_text + "vnf_config_primitive={} Sub-operation reintent". + self.logger.debug(logging_text + "vnf_config_primitive={} Sub-operation retry". format(vnf_config_primitive)) # Execute the primitive, either with new (first-time) or registered (reintent) args + ee_id, vca_type = self._look_for_deployed_vca(nsr_deployed["VCA"], + member_vnf_index=vnf_index, + vdu_id=None, + vdu_count_index=None) result, result_detail = await self._ns_execute_primitive( - self._look_for_deployed_vca(nsr_deployed["VCA"], - member_vnf_index=vnf_index, - vdu_id=None, - vdu_count_index=None), - vnf_config_primitive, primitive_params) + ee_id, vnf_config_primitive, primitive_params, vca_type) self.logger.debug(logging_text + "vnf_config_primitive={} Done with result {} {}".format( vnf_config_primitive, result, result_detail)) # Update operationState = COMPLETED | FAILED