X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_lcm%2Fns.py;h=badef36661321e982737766c8c669da6d2f3036c;hb=0d7ac8da3021aab4d859d4de869c51422ecc08d3;hp=6589e228eba894967c67392e5b1df50e7c2355fe;hpb=2e2155173c047ac2acb8a626019eda2d87f785ed;p=osm%2FLCM.git diff --git a/osm_lcm/ns.py b/osm_lcm/ns.py index 6589e22..badef36 100644 --- a/osm_lcm/ns.py +++ b/osm_lcm/ns.py @@ -69,6 +69,7 @@ def populate_dict(target_dict, key_list, value): class NsLcm(LcmBase): timeout_vca_on_error = 5 * 60 # Time for charm from first time at blocked,error status to mark as failed total_deploy_timeout = 2 * 3600 # global timeout for deployment + timeout_charm_delete = 10 * 60 def __init__(self, db, msg, fs, lcm_tasks, ro_config, vca_config, loop): """ @@ -344,6 +345,10 @@ class NsLcm(LcmBase): populate_dict(RO_ns_params, ("vnfs", vnf_params["member-vnf-index"], "networks", internal_vld_params["name"], "vim-network-name"), internal_vld_params["vim-network-name"]) + if internal_vld_params.get("vim-network-id"): + populate_dict(RO_ns_params, ("vnfs", vnf_params["member-vnf-index"], "networks", + internal_vld_params["name"], "vim-network-id"), + internal_vld_params["vim-network-id"]) if internal_vld_params.get("ip-profile"): populate_dict(RO_ns_params, ("vnfs", vnf_params["member-vnf-index"], "networks", internal_vld_params["name"], "ip-profile"), @@ -392,6 +397,18 @@ class NsLcm(LcmBase): RO_vld_sites.append({"netmap-use": vld_params["vim-network-name"]}) if RO_vld_sites: populate_dict(RO_ns_params, ("networks", vld_params["name"], "sites"), RO_vld_sites) + if vld_params.get("vim-network-id"): + RO_vld_sites = [] + if isinstance(vld_params["vim-network-id"], dict): + for vim_account, vim_net in vld_params["vim-network-id"].items(): + RO_vld_sites.append({ + "netmap-use": vim_net, + "datacenter": vim_account_2_RO(vim_account) + }) + else: # isinstance str + RO_vld_sites.append({"netmap-use": vld_params["vim-network-id"]}) + if RO_vld_sites: + populate_dict(RO_ns_params, ("networks", vld_params["name"], "sites"), RO_vld_sites) if "vnfd-connection-point-ref" in vld_params: for cp_params in vld_params["vnfd-connection-point-ref"]: # look for interface @@ -626,6 +643,10 @@ class NsLcm(LcmBase): RO = ROclient.ROClient(self.loop, **self.ro_config) + # set state to INSTANTIATED. When instantiated NBI will not delete directly + db_nsr_update["_admin.nsState"] = "INSTANTIATED" + self.update_db_2("nsrs", nsr_id, db_nsr_update) + # get vnfds, instantiate at RO for vnfd_id, vnfd in db_vnfds.items(): vnfd_ref = vnfd["id"] @@ -645,7 +666,6 @@ class NsLcm(LcmBase): vnfd_RO = self.vnfd2RO(vnfd, vnfd_id_RO) desc = await RO.create("vnfd", descriptor=vnfd_RO) db_nsr_update["_admin.deployed.RO.vnfd_id.{}".format(vnfd_id)] = desc["uuid"] - db_nsr_update["_admin.nsState"] = "INSTANTIATED" self.logger.debug(logging_text + "vnfd={} created at RO. RO_id={}".format( vnfd_ref, desc["uuid"])) self.update_db_2("nsrs", nsr_id, db_nsr_update) @@ -805,20 +825,18 @@ class NsLcm(LcmBase): # ns_name will be ignored in the current version of N2VC # but will be implemented for the next point release. - model_name = 'default' # TODO bug 581 : change to nsr_id + model_name = "default" # TODO bug 585 nsr_id if vdu_id: - vdu_id_text = vdu_id + vdu_id_text = vdu_id + "-" else: - vdu_id_text = "vnfd" # TODO bug 581 remove and add just an empty string "" + vdu_id_text = "-" application_name = self.n2vc.FormatApplicationName(nsr_name, vnf_index, vdu_id_text) - # TODO bug 581 Add "-" as a final argument vca_index = len(vca_deployed_list) # trunk name and add two char index at the end to ensure that it is unique. It is assumed no more than # 26*26 charm in the same NS - # TODO bug 581 uncoment - # application_name = application_name[0:48] - # application_name += chr(97 + vca_index / 26) + chr(97 + vca_index % 26) + application_name = application_name[0:48] + application_name += chr(97 + vca_index // 26) + chr(97 + vca_index % 26) vca_deployed_ = { "member-vnf-index": vnf_index, "vdu_id": vdu_id, @@ -1012,11 +1030,14 @@ class NsLcm(LcmBase): db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc) db_nslcmop_update["operationState"] = nslcmop_operation_state = "FAILED" db_nslcmop_update["statusEnteredTime"] = time() - if db_nsr: - db_nsr_update["_admin.nslcmop"] = None - self.update_db_2("nsrs", nsr_id, db_nsr_update) - if db_nslcmop_update: - self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + try: + if db_nsr: + db_nsr_update["_admin.nslcmop"] = None + self.update_db_2("nsrs", nsr_id, db_nsr_update) + if db_nslcmop_update: + self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + except DbException as e: + self.logger.error(logging_text + "Cannot update database: {}".format(e)) if nslcmop_operation_state: try: await self.msg.aiowrite("ns", "instantiated", {"nsr_id": nsr_id, "nslcmop_id": nslcmop_id, @@ -1027,6 +1048,34 @@ class NsLcm(LcmBase): self.logger.debug(logging_text + "Exit") self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate") + async def _destroy_charm(self, model, application): + """ + Order N2VC destroy a charm + :param model: + :param application: + :return: True if charm does not exist. False if it exist + """ + if not await self.n2vc.HasApplication(model, application): + return True # Already removed + await self.n2vc.RemoveCharms(model, application) + return False + + async def _wait_charm_destroyed(self, model, application, timeout): + """ + Wait until charm does not exist + :param model: + :param application: + :param timeout: + :return: True if not exist, False if timeout + """ + while True: + if not await self.n2vc.HasApplication(model, application): + return True + if timeout < 0: + return False + await asyncio.sleep(10) + timeout -= 10 + async def terminate(self, nsr_id, nslcmop_id): logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id) self.logger.debug(logging_text + "Enter") @@ -1034,9 +1083,7 @@ class NsLcm(LcmBase): db_nslcmop = None exc = None failed_detail = [] # annotates all failed error messages - vca_task_list = [] - vca_task_dict = {} - vca_application_name2index = {} + vca_time_destroy = None # time of where destroy charm order db_nsr_update = {"_admin.nslcmop": nslcmop_id} db_nslcmop_update = {} nslcmop_operation_state = None @@ -1049,8 +1096,6 @@ class NsLcm(LcmBase): nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED": return - # TODO ALF remove - # db_vim = self.db.get_one("vim_accounts", {"_id": db_nsr["datacenter"]}) # #TODO check if VIM is creating and wait # RO_vim_id = db_vim["_admin"]["deployed"]["RO"] @@ -1070,24 +1115,12 @@ class NsLcm(LcmBase): self.update_db_2("nsrs", nsr_id, db_nsr_update) for vca_index, vca_deployed in enumerate(nsr_deployed["VCA"]): - if vca_deployed: # TODO it would be desirable having a and deploy_info.get("deployed"): - task = asyncio.ensure_future( - self.n2vc.RemoveCharms( - vca_deployed['model'], - vca_deployed["application"], - # self.n2vc_callback, - # db_nsr, - # db_nslcmop, - ) - ) - vca_application_name2index[vca_deployed["application"]] = vca_index - vca_task_list.append(task) - vca_task_dict[vca_deployed["application"]] = task - # task.add_done_callback(functools.partial(self.n2vc_callback, vca_deployed['model'], - # vca_deployed['application'], None, db_nsr, - # db_nslcmop, vnf_index)) - self.lcm_tasks.register("ns", nsr_id, nslcmop_id, - "delete_charm:" + vca_deployed["application"], task) + if vca_deployed: + if await self._destroy_charm(vca_deployed['model'], vca_deployed["application"]): + vca_deployed.clear() + db_nsr["_admin.deployed.VCA.{}".format(vca_index)] = None + else: + vca_time_destroy = time() except Exception as e: self.logger.debug(logging_text + "Failed while deleting charms: {}".format(e)) @@ -1103,6 +1136,8 @@ class NsLcm(LcmBase): try: if RO_nsr_id: step = db_nsr_update["detailed-status"] = db_nslcmop_update["detailed-status"] = "Deleting ns at RO" + self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + self.update_db_2("nsrs", nsr_id, db_nsr_update) self.logger.debug(logging_text + step) desc = await RO.delete("ns", RO_nsr_id) RO_delete_action = desc["action_id"] @@ -1111,7 +1146,8 @@ class NsLcm(LcmBase): db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED" if RO_delete_action: # wait until NS is deleted from VIM - step = detailed_status = "Waiting ns deleted from VIM. RO_id={}".format(RO_nsr_id) + step = detailed_status = "Waiting ns deleted from VIM. RO_id={} RO_delete_action={}".\ + format(RO_nsr_id, RO_delete_action) detailed_status_old = None self.logger.debug(logging_text + step) @@ -1125,14 +1161,18 @@ class NsLcm(LcmBase): elif ns_status == "BUILD": detailed_status = step + "; {}".format(ns_status_info) elif ns_status == "ACTIVE": + db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None + db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED" break else: assert False, "ROclient.check_action_status returns unknown {}".format(ns_status) - await asyncio.sleep(5, loop=self.loop) - delete_timeout -= 5 if detailed_status != detailed_status_old: - detailed_status_old = db_nslcmop_update["detailed-status"] = detailed_status + detailed_status_old = db_nslcmop_update["detailed-status"] = \ + db_nsr_update["detailed-status"] = detailed_status self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + self.update_db_2("nsrs", nsr_id, db_nsr_update) + await asyncio.sleep(5, loop=self.loop) + delete_timeout -= 5 else: # delete_timeout <= 0: raise ROclient.ROClientException("Timeout waiting ns deleted from VIM") @@ -1140,6 +1180,7 @@ class NsLcm(LcmBase): if 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_ns_id={} already deleted".format(RO_nsr_id)) elif e.http_code == 409: # conflict failed_detail.append("RO_ns_id={} delete conflict: {}".format(RO_nsr_id, e)) @@ -1193,28 +1234,23 @@ class NsLcm(LcmBase): failed_detail.append("RO_vnfd_id={} delete error: {}".format(RO_vnfd_id, e)) self.logger.error(logging_text + failed_detail[-1]) - if vca_task_list: - db_nsr_update["detailed-status"] = db_nslcmop_update["detailed-status"] =\ + # wait until charm deleted + if vca_time_destroy: + db_nsr_update["detailed-status"] = db_nslcmop_update["detailed-status"] = step = \ "Waiting for deletion of configuration charms" self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) self.update_db_2("nsrs", nsr_id, db_nsr_update) - await asyncio.wait(vca_task_list, timeout=300) - for application_name, task in vca_task_dict.items(): - if task.cancelled(): - failed_detail.append("VCA[application_name={}] Deletion has been cancelled" - .format(application_name)) - elif task.done(): - exc = task.exception() - if exc: - failed_detail.append("VCA[application_name={}] Deletion exception: {}" - .format(application_name, exc)) + for vca_index, vca_deployed in enumerate(nsr_deployed["VCA"]): + if not vca_deployed: + continue + step = "Waiting for deletion of charm application_name={}".format(vca_deployed["application"]) + timeout = self.timeout_charm_delete - int(time() - vca_time_destroy) + if not await self._wait_charm_destroyed(vca_deployed['model'], vca_deployed["application"], + timeout): + failed_detail.append("VCA[application_name={}] Deletion timeout".format( + vca_deployed["application"])) else: - vca_index = vca_application_name2index[application_name] - db_nsr_update["_admin.deployed.VCA.{}".format(vca_index)] = None - else: # timeout - # TODO Should it be cancelled?!! - task.cancel() - failed_detail.append("VCA[application_name={}] Deletion timeout".format(application_name)) + db_nsr["_admin.deployed.VCA.{}".format(vca_index)] = None if failed_detail: self.logger.error(logging_text + " ;".join(failed_detail)) @@ -1225,8 +1261,10 @@ class NsLcm(LcmBase): db_nslcmop_update["statusEnteredTime"] = time() elif db_nslcmop["operationParams"].get("autoremove"): self.db.del_one("nsrs", {"_id": nsr_id}) + db_nsr = None db_nsr_update.clear() self.db.del_list("nslcmops", {"nsInstanceId": nsr_id}) + db_nslcmop = None nslcmop_operation_state = "COMPLETED" db_nslcmop_update.clear() self.db.del_list("vnfrs", {"nsr-id-ref": nsr_id}) @@ -1255,11 +1293,14 @@ class NsLcm(LcmBase): db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc) db_nslcmop_update["operationState"] = nslcmop_operation_state = "FAILED" db_nslcmop_update["statusEnteredTime"] = time() - if db_nslcmop_update: - self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) - if db_nsr: - db_nsr_update["_admin.nslcmop"] = None - self.update_db_2("nsrs", nsr_id, db_nsr_update) + try: + if db_nslcmop and db_nslcmop_update: + self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + if db_nsr: + db_nsr_update["_admin.nslcmop"] = None + self.update_db_2("nsrs", nsr_id, db_nsr_update) + except DbException as e: + self.logger.error(logging_text + "Cannot update database: {}".format(e)) if nslcmop_operation_state: try: await self.msg.aiowrite("ns", "terminated", {"nsr_id": nsr_id, "nslcmop_id": nslcmop_id, @@ -1393,11 +1434,14 @@ class NsLcm(LcmBase): db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc) db_nslcmop_update["operationState"] = nslcmop_operation_state = "FAILED" db_nslcmop_update["statusEnteredTime"] = time() - if db_nslcmop_update: - self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) - if db_nsr: - db_nsr_update["_admin.nslcmop"] = None - self.update_db_2("nsrs", nsr_id, db_nsr_update) + try: + if db_nslcmop_update: + self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + if db_nsr: + db_nsr_update["_admin.nslcmop"] = None + self.update_db_2("nsrs", nsr_id, db_nsr_update) + except DbException as e: + self.logger.error(logging_text + "Cannot update database: {}".format(e)) self.logger.debug(logging_text + "Exit") if nslcmop_operation_state: try: @@ -1735,11 +1779,14 @@ class NsLcm(LcmBase): db_nsr_update["operational-status"] = "failed" db_nsr_update["detailed-status"] = "FAILED scaling nslcmop={} {}: {}".format(nslcmop_id, step, exc) - if db_nslcmop_update: - self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) - if db_nsr: - db_nsr_update["_admin.nslcmop"] = None - self.update_db_2("nsrs", nsr_id, db_nsr_update) + try: + if db_nslcmop and db_nslcmop_update: + self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + if db_nsr: + db_nsr_update["_admin.nslcmop"] = None + self.update_db_2("nsrs", nsr_id, db_nsr_update) + except DbException as e: + self.logger.error(logging_text + "Cannot update database: {}".format(e)) if nslcmop_operation_state: try: await self.msg.aiowrite("ns", "scaled", {"nsr_id": nsr_id, "nslcmop_id": nslcmop_id,