Feature 10996: Adds ns-op-cancel command 40/14040/2
authorGabriel Cuba <gcuba@whitestack.com>
Thu, 16 Nov 2023 21:25:15 +0000 (16:25 -0500)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 4 Dec 2023 14:18:44 +0000 (15:18 +0100)
Change-Id: I349cea39231338c667da4fe46857bd0b246db908
Signed-off-by: Gabriel Cuba <gcuba@whitestack.com>
osmclient/cli_commands/nslcm_ops.py
osmclient/common/wait.py
osmclient/scripts/osm.py
osmclient/sol005/ns.py

index 46197d0..9528d08 100755 (executable)
@@ -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)
index d3f673c..3f5b51f 100644 (file)
@@ -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:
index 74bb84b..20cddc6 100755 (executable)
@@ -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)
index c84d090..e8442f9 100644 (file)
@@ -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,