From: Isabel Lloret Date: Fri, 25 Apr 2025 09:27:11 +0000 (+0200) Subject: Feature 11052: support for opening a console for vCenter X-Git-Tag: v18.0.0~10 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=23aea8e35694f6ab8bec7eb8f5a575797bd50772;p=osm%2FLCM.git Feature 11052: support for opening a console for vCenter Change-Id: I63b09dc23b7fd03fd2c68219cb46b6d2e8987f42 Signed-off-by: Isabel Lloret --- diff --git a/osm_lcm/ng_ro.py b/osm_lcm/ng_ro.py index 94264882..8570d524 100644 --- a/osm_lcm/ng_ro.py +++ b/osm_lcm/ng_ro.py @@ -206,6 +206,32 @@ class NgRoClient: url, response.status, response_text[:100] ) ) + self.logger.debug("Get response text: %s", response_text) + if response.status >= 300: + raise NgRoException(response_text, http_code=response.status) + return self._parse_yaml(response_text, response=True) + + except (aiohttp.ClientOSError, aiohttp.ClientError) as e: + raise NgRoException(e, http_code=504) + except asyncio.TimeoutError: + raise NgRoException("Timeout", http_code=504) + + async def get_action_vim_info(self, nsr_id, action_id): + try: + url = "{}/ns/v1/deploy/{nsr_id}/{action_id}/viminfo".format( + self.endpoint_url, nsr_id=nsr_id, action_id=action_id + ) + async with aiohttp.ClientSession() as session: + self.logger.debug("GET %s", url) + # timeout = aiohttp.ClientTimeout(total=self.timeout_short) + async with session.get(url, headers=self.headers_req) as response: + response_text = await response.read() + self.logger.debug( + "GET {} [{}] {}".format( + url, response.status, response_text[:100] + ) + ) + self.logger.debug("Get response text: %s", response_text) if response.status >= 300: raise NgRoException(response_text, http_code=response.status) return self._parse_yaml(response_text, response=True) diff --git a/osm_lcm/ns.py b/osm_lcm/ns.py index 8906e2a8..b2c1c084 100644 --- a/osm_lcm/ns.py +++ b/osm_lcm/ns.py @@ -217,6 +217,7 @@ class NsLcm(LcmBase): "healing": self.RO.recreate_status, "verticalscale": self.RO.status, "start_stop_rebuild": self.RO.status, + "console": self.RO.status, } @staticmethod @@ -6300,9 +6301,23 @@ class NsLcm(LcmBase): additional_param = db_nslcmop["operationParams"]["operateVnfData"][ "additionalParam" ] - (result, detailed_status) = await self.rebuild_start_stop( + self.logger.debug( + "Operate VNF, operation_type: %s, params: %s", + operation_type, + additional_param, + ) + ( + result, + detailed_status, + operation_result_data, + ) = await self.process_operate_vnf( nsr_id, nslcmop_id, vnf_id, additional_param, operation_type ) + self.logger.debug("operation_result_data: %s", operation_result_data) + # In case the operation has a result store it in the ddbb + if operation_result_data: + db_nslcmop_update["operationResultData"] = operation_result_data + if result == "FAILED": nslcmop_operation_state = result error_description_nslcmop = detailed_status @@ -7910,6 +7925,126 @@ class NsLcm(LcmBase): job["vnfr_id"] = vnfr_id return job_list + async def process_operate_vnf( + self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type + ): + self.logger.debug("Process operate vnf, operation_type: %s", operation_type) + operations = {"console": self.get_console_operation} + default_operation = self.rebuild_start_stop + + operation_func = operations.get(operation_type, default_operation) + if callable(operation_func): + result = await operation_func( + nsr_id, nslcmop_id, vnf_id, additional_param, operation_type + ) + if len(result) == 2: + result = (*result, None) + return result + return "FAILED", f"Unknown operation type: {operation_type}", None + + async def get_console_operation( + self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type + ): + self.logger.debug( + "Get console operation, nsr_id: %s, nslcmop_id: %s, vnf_id: %s, additional_param: %s, operation_type: %s", + nsr_id, + nslcmop_id, + vnf_id, + additional_param, + operation_type, + ) + status = "PROCESSING" + detailed_status = "" + start_deploy = time() + try: + # Obtain vnf data from database + operation_data = self._get_vdu_operation_data( + vnf_id, additional_param["count-index"], additional_param["vdu_id"] + ) + self.logger.debug("Operation data: %s", operation_data) + + # Execute operation + desc = {"console": operation_data} + result_dict = await self.RO.operate(nsr_id, desc, operation_type) + self.logger.debug("Result dict: %s", result_dict) + + # Wait for response + action_id = result_dict["action_id"] + await self._wait_ng_ro( + nsr_id, + action_id, + nslcmop_id, + start_deploy, + self.timeout.operate, + None, + "console", + ) + + # Obtain the console vim data + result_vim_info = await self.RO.get_action_vim_info(nsr_id, action_id) + self.logger.debug("Result vim info: %s", result_vim_info) + console_data = None + if result_vim_info.get("vim_info_list"): + for vim_info in result_vim_info.get("vim_info_list"): + if vim_info.get("vim_console_data"): + console_data = vim_info.get("vim_console_data") + + self.logger.debug("console_data: %s", console_data) + if not console_data: + raise ROclient.ROClientException("console data not properly returned") + + return "COMPLETED", "Done", console_data + + except (ROclient.ROClientException, DbException, LcmException) as e: + self.logger.error("Exit Exception {}".format(e)) + status = "FAILED" + detailed_status = str(e) + except asyncio.CancelledError: + self.logger.error("Cancelled Exception obtaining console data") + exc = "Operation was cancelled" + status = "FAILED" + detailed_status = exc + except Exception as e: + exc = traceback.format_exc() + self.logger.critical( + "Processing get_console_operation, end operation Exception {} {}".format( + type(e).__name__, e + ), + exc_info=True, + ) + status = "FAILED" + detailed_status = "Error in operate VNF {}".format(exc) + + return status, detailed_status + + def _get_vdu_operation_data(self, vnf_id, count_index, vdu_id): + """ + Obtains vdu required data from database + """ + operation_data = {"vnf_id": vnf_id, "vdu_index": count_index} + # Obtain vnf from the database + db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id}) + + self.logger.debug("db_vnfr: %s", db_vnfr) + # Obtain additional data and vdu data + vim_account_id = db_vnfr.get("vim-account-id") + vim_info_key = "vim:" + vim_account_id + vdurs = [item for item in db_vnfr["vdur"] if item["vdu-id-ref"] == vdu_id] + vdur = find_in_list(vdurs, lambda vdu: vdu["count-index"] == count_index) + self.logger.debug("vdur: %s", vdur) + if vdur: + vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"] + target_vim, _ = next(k_v for k_v in vdur["vim_info"].items()) + else: + raise LcmException("Target vdu is not found") + + # Store all the needed data for the operation + operation_data["vim_vm_id"] = vim_vm_id + operation_data["vdu_id"] = vdur["id"] + operation_data["target_vim"] = target_vim + operation_data["vim_account_id"] = vim_account_id + return operation_data + async def rebuild_start_stop( self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type ):