From 84fdd949fd48ea5da6939d711617c4b50b6cd2cf Mon Sep 17 00:00:00 2001 From: Gabriel Cuba Date: Thu, 16 Nov 2023 16:25:15 -0500 Subject: [PATCH] Feature 10996: Adds ns-op-cancel command Change-Id: I349cea39231338c667da4fe46857bd0b246db908 Signed-off-by: Gabriel Cuba --- osmclient/cli_commands/nslcm_ops.py | 28 ++++++++++++++++++++++++++ osmclient/common/wait.py | 6 ++++-- osmclient/scripts/osm.py | 1 + osmclient/sol005/ns.py | 31 +++++++++++++++++++++++++++-- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/osmclient/cli_commands/nslcm_ops.py b/osmclient/cli_commands/nslcm_ops.py index 46197d0..9528d08 100755 --- a/osmclient/cli_commands/nslcm_ops.py +++ b/osmclient/cli_commands/nslcm_ops.py @@ -149,3 +149,31 @@ def ns_op_show(ctx, id, filter, literal): table.add_row([k, utils.wrap_text(json.dumps(v, indent=2), 100)]) table.align = "l" print(table) + + +@click.command(name="ns-op-cancel", short_help="cancels an ongoing NS operation") +@click.argument("id") +@click.option( + "--cancel_mode", + required=False, + default="GRACEFUL", + show_default=True, + help="Mode of cancellation, can be FORCEFUL or GRACEFUL", +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) +@click.pass_context +def ns_op_cancel(ctx, id, cancel_mode, wait): + """Cancels an ongoing NS operation + + ID: operation identifier + """ + logger.debug("") + utils.check_client_version(ctx.obj, ctx.command.name) + ctx.obj.ns.cancel_op(id, cancel_mode, wait) diff --git a/osmclient/common/wait.py b/osmclient/common/wait.py index d3f673c..3f5b51f 100644 --- a/osmclient/common/wait.py +++ b/osmclient/common/wait.py @@ -58,6 +58,8 @@ def _get_finished_states(entity): """ if entity == "NS" or entity == "NSI": return ("COMPLETED", "PARTIALLY_COMPLETED"), ("FAILED_TEMP", "FAILED") + elif entity == "OPCANCEL": + return ("FAILED_TEMP"), ("COMPLETED",) else: return ("ENABLED",), ("ERROR",) @@ -72,7 +74,7 @@ def _get_operational_state(resp, entity): :param entity: can be NS, NSI, or other :return: status of the operation """ - if entity == "NS" or entity == "NSI": + if entity in ["NS", "NSI", "OPCANCEL"]: return resp.get("operationState") else: return resp.get("_admin", {}).get("operationalState") @@ -111,7 +113,7 @@ def _get_detailed_status(resp, entity): :param entity: can be NS, NSI, or other :return: """ - if entity in ("NS", "NSI"): + if entity in ("NS", "NSI", "OPCANCEL"): # For NS and NSI, 'detailed-status' is a JSON "root" member: return resp.get("detailed-status") else: diff --git a/osmclient/scripts/osm.py b/osmclient/scripts/osm.py index 74bb84b..20cddc6 100755 --- a/osmclient/scripts/osm.py +++ b/osmclient/scripts/osm.py @@ -187,6 +187,7 @@ def cli(): cli_osm.add_command(nslcm_ops.ns_op_list) cli_osm.add_command(nslcm_ops.ns_op_show) + cli_osm.add_command(nslcm_ops.ns_op_cancel) cli_osm.add_command(nslcm.ns_action) cli_osm.add_command(nslcm.vnf_scale) diff --git a/osmclient/sol005/ns.py b/osmclient/sol005/ns.py index c84d090..e8442f9 100644 --- a/osmclient/sol005/ns.py +++ b/osmclient/sol005/ns.py @@ -40,7 +40,7 @@ class Ns(object): ) # NS '--wait' option - def _wait(self, id, wait_time, deleteFlag=False): + def _wait(self, id, wait_time, deleteFlag=False, entity="NS"): self._logger.debug("") # Endpoint to get operation status apiUrlStatus = "{}{}{}".format( @@ -50,7 +50,7 @@ class Ns(object): if isinstance(wait_time, bool): wait_time = WaitForStatus.TIMEOUT_NS_OPERATION WaitForStatus.wait_for_status( - "NS", + entity, str(id), wait_time, apiUrlStatus, @@ -431,6 +431,33 @@ class Ns(object): message = "failed to exec operation {}:\nerror:\n{}".format(name, str(exc)) raise ClientException(message) + def cancel_op(self, operation_id, cancel_mode, wait=False): + """Cancels an LCM operation""" + self._client.get_token() + self._apiResource = "/ns_lcm_op_occs" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + endpoint = "{}/{}/cancel".format(self._apiBase, operation_id) + op_data = {"cancelMode": cancel_mode} + try: + http_code, resp = self._http.post_cmd( + endpoint=endpoint, postfields_dict=op_data + ) + if http_code == 202: + if wait: + self._wait(operation_id, wait, deleteFlag=True, entity="OPCANCEL") + else: + print("Cancellation in progress") + else: + msg = resp or "" + raise ClientException(msg) + except ClientException as exc: + message = "failed to exec operation {}:\nerror:\n{}".format( + operation_id, str(exc) + ) + raise ClientException(message) + def scale_vnf( self, ns_name, -- 2.25.1