Feature 10922: Stop, start and rebuild 86/11986/11
authork4.rahul <rahul.k4@tataelxsi.co.in>
Mon, 2 May 2022 15:47:57 +0000 (15:47 +0000)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Tue, 21 Jun 2022 11:10:22 +0000 (13:10 +0200)
Added support for feature start stop rebuild of VNF instances
Added unit test case for start stop rebuil of VNF instances

Change-Id: I09d2512084268c190f5ae9cfdaae41269c6bc069
Signed-off-by: k4.rahul <rahul.k4@tataelxsi.co.in>
NG-RO/osm_ng_ro/ns.py
NG-RO/osm_ng_ro/ns_thread.py
NG-RO/osm_ng_ro/ro_main.py
NG-RO/osm_ng_ro/tests/test_ns.py
NG-RO/osm_ng_ro/validation.py
RO-VIM-openstack/osm_rovim_openstack/vimconn_openstack.py
releasenotes/notes/feature_10922_stop_start_rebuild-917f01116bc078e3.yaml [new file with mode: 0644]

index d2dc46b..3f14c58 100644 (file)
@@ -2379,6 +2379,99 @@ class Ns(object):
 
         return None, None, True
 
+    def rebuild_start_stop_task(
+        self,
+        vdu_id,
+        vnf_id,
+        vdu_index,
+        action_id,
+        nsr_id,
+        task_index,
+        target_vim,
+        extra_dict,
+    ):
+        self._assign_vim(target_vim)
+        target_record = "vnfrs:{}:vdur.{}".format(vnf_id, vdu_index)
+        target_record_id = "vnfrs:{}:vdur.{}".format(vnf_id, vdu_id)
+        deployment_info = {
+            "action_id": action_id,
+            "nsr_id": nsr_id,
+            "task_index": task_index,
+        }
+
+        task = Ns._create_task(
+            deployment_info=deployment_info,
+            target_id=target_vim,
+            item="update",
+            action="EXEC",
+            target_record=target_record,
+            target_record_id=target_record_id,
+            extra_dict=extra_dict,
+        )
+        return task
+
+    def rebuild_start_stop(
+        self, session, action_dict, version, nsr_id, *args, **kwargs
+    ):
+        task_index = 0
+        extra_dict = {}
+        now = time()
+        action_id = action_dict.get("action_id", str(uuid4()))
+        step = ""
+        logging_text = "Task deploy nsr_id={} action_id={} ".format(nsr_id, action_id)
+        self.logger.debug(logging_text + "Enter")
+
+        action = list(action_dict.keys())[0]
+        task_dict = action_dict.get(action)
+        vim_vm_id = action_dict.get(action).get("vim_vm_id")
+
+        if action_dict.get("stop"):
+            action = "shutoff"
+        db_new_tasks = []
+        try:
+            step = "lock the operation & do task creation"
+            with self.write_lock:
+                extra_dict["params"] = {
+                    "vim_vm_id": vim_vm_id,
+                    "action": action,
+                }
+                task = self.rebuild_start_stop_task(
+                    task_dict["vdu_id"],
+                    task_dict["vnf_id"],
+                    task_dict["vdu_index"],
+                    action_id,
+                    nsr_id,
+                    task_index,
+                    task_dict["target_vim"],
+                    extra_dict,
+                )
+                db_new_tasks.append(task)
+                step = "upload Task to db"
+                self.upload_all_tasks(
+                    db_new_tasks=db_new_tasks,
+                    now=now,
+                )
+                self.logger.debug(
+                    logging_text + "Exit. Created {} tasks".format(len(db_new_tasks))
+                )
+                return (
+                    {"status": "ok", "nsr_id": nsr_id, "action_id": action_id},
+                    action_id,
+                    True,
+                )
+        except Exception as e:
+            if isinstance(e, (DbException, NsException)):
+                self.logger.error(
+                    logging_text + "Exit Exception while '{}': {}".format(step, e)
+                )
+            else:
+                e = traceback_format_exc()
+                self.logger.critical(
+                    logging_text + "Exit Exception while '{}': {}".format(step, e),
+                    exc_info=True,
+                )
+            raise NsException(e)
+
     def get_deploy(self, session, indata, version, nsr_id, action_id, *args, **kwargs):
         nsrs = self.db.get_list("nsrs", {})
         return_data = []
index 767382d..9ed04d7 100644 (file)
@@ -887,6 +887,48 @@ class VimInteractionAffinityGroup(VimInteractionBase):
             return "FAILED", ro_vim_item_update
 
 
+class VimInteractionUpdateVdu(VimInteractionBase):
+    def exec(self, ro_task, task_index, task_depends):
+        task = ro_task["tasks"][task_index]
+        task_id = task["task_id"]
+        db_task_update = {"retries": 0}
+        created = False
+        created_items = {}
+        target_vim = self.my_vims[ro_task["target_id"]]
+
+        try:
+            if task.get("params"):
+                vim_vm_id = task["params"].get("vim_vm_id")
+                action = task["params"].get("action")
+                context = {action: action}
+                target_vim.action_vminstance(vim_vm_id, context)
+                # created = True
+            ro_vim_item_update = {
+                "vim_id": vim_vm_id,
+                "vim_status": "DONE",
+                "created": created,
+                "created_items": created_items,
+                "vim_details": None,
+                "vim_message": None,
+            }
+            self.logger.debug(
+                "task={} {} vm-migration done".format(task_id, ro_task["target_id"])
+            )
+            return "DONE", ro_vim_item_update, db_task_update
+        except (vimconn.VimConnException, NsWorkerException) as e:
+            self.logger.error(
+                "task={} vim={} VM Migration:"
+                " {}".format(task_id, ro_task["target_id"], e)
+            )
+            ro_vim_item_update = {
+                "vim_status": "VIM_ERROR",
+                "created": created,
+                "vim_message": str(e),
+            }
+
+            return "FAILED", ro_vim_item_update, db_task_update
+
+
 class VimInteractionSdnNet(VimInteractionBase):
     @staticmethod
     def _match_pci(port_pci, mapping):
@@ -1404,6 +1446,9 @@ class NsWorker(threading.Thread):
             "sdn_net": VimInteractionSdnNet(
                 self.db, self.my_vims, self.db_vims, self.logger
             ),
+            "update": VimInteractionUpdateVdu(
+                self.db, self.my_vims, self.db_vims, self.logger
+            ),
             "affinity-or-anti-affinity-group": VimInteractionAffinityGroup(
                 self.db, self.my_vims, self.db_vims, self.logger
             ),
index 30acd2b..bd2ea9e 100644 (file)
@@ -83,6 +83,30 @@ valid_url_methods = {
     },
     "ns": {
         "v1": {
+            "rebuild": {
+                "METHODS": ("POST",),
+                "ROLE_PERMISSION": "rebuild:",
+                "<ID>": {
+                    "METHODS": ("POST",),
+                    "ROLE_PERMISSION": "rebuild:id:",
+                },
+            },
+            "start": {
+                "METHODS": ("POST",),
+                "ROLE_PERMISSION": "start:",
+                "<ID>": {
+                    "METHODS": ("POST",),
+                    "ROLE_PERMISSION": "start:id:",
+                },
+            },
+            "stop": {
+                "METHODS": ("POST",),
+                "ROLE_PERMISSION": "stop:",
+                "<ID>": {
+                    "METHODS": ("POST",),
+                    "ROLE_PERMISSION": "stop:id:",
+                },
+            },
             "deploy": {
                 "METHODS": ("GET",),
                 "ROLE_PERMISSION": "deploy:",
@@ -170,6 +194,9 @@ class Server(object):
             "deploy:id:delete": self.ns.delete,
             "deploy:id:id:get": self.ns.status,
             "deploy:id:id:cancel:post": self.ns.cancel,
+            "rebuild:id:post": self.ns.rebuild_start_stop,
+            "start:id:post": self.ns.rebuild_start_stop,
+            "stop:id:post": self.ns.rebuild_start_stop,
             "recreate:id:post": self.ns.recreate,
             "recreate:id:id:get": self.ns.recreate_status,
             "migrate:id:post": self.ns.migrate,
index 4e081af..6c2615a 100644 (file)
@@ -2663,3 +2663,51 @@ class TestNs(unittest.TestCase):
 
     def test__process_vdu_params(self):
         pass
+
+    @patch("osm_ng_ro.ns.Ns._assign_vim")
+    def test__rebuild_start_stop_task(self, assign_vim):
+        self.ns = Ns()
+        extra_dict = {}
+        actions = ["start", "stop", "rebuild"]
+        vdu_id = "bb9c43f9-10a2-4569-a8a8-957c3528b6d1"
+        vnf_id = "665b4165-ce24-4320-bf19-b9a45bade49f"
+        vdu_index = "0"
+        action_id = "bb937f49-3870-4169-b758-9732e1ff40f3"
+        nsr_id = "993166fe-723e-4680-ac4b-b1af2541ae31"
+        task_index = 0
+        target_vim = "vim:f9f370ac-0d44-41a7-9000-457f2332bc35"
+        t = "vnfrs:665b4165-ce24-4320-bf19-b9a45bade49f:vdur.bb9c43f9-10a2-4569-a8a8-957c3528b6d1"
+        for action in actions:
+            expected_result = {
+                "target_id": "vim:f9f370ac-0d44-41a7-9000-457f2332bc35",
+                "action_id": "bb937f49-3870-4169-b758-9732e1ff40f3",
+                "nsr_id": "993166fe-723e-4680-ac4b-b1af2541ae31",
+                "task_id": "bb937f49-3870-4169-b758-9732e1ff40f3:0",
+                "status": "SCHEDULED",
+                "action": "EXEC",
+                "item": "update",
+                "target_record": "vnfrs:665b4165-ce24-4320-bf19-b9a45bade49f:vdur.0",
+                "target_record_id": t,
+                "params": {
+                    "vim_vm_id": "f37b18ef-3caa-4dc9-ab91-15c669b16396",
+                    "action": action,
+                },
+            }
+            extra_dict["params"] = {
+                "vim_vm_id": "f37b18ef-3caa-4dc9-ab91-15c669b16396",
+                "action": action,
+            }
+            task = self.ns.rebuild_start_stop_task(
+                vdu_id,
+                vnf_id,
+                vdu_index,
+                action_id,
+                nsr_id,
+                task_index,
+                target_vim,
+                extra_dict,
+            )
+            self.assertEqual(task.get("action_id"), action_id)
+            self.assertEqual(task.get("nsr_id"), nsr_id)
+            self.assertEqual(task.get("target_id"), target_vim)
+            self.assertDictEqual(task, expected_result)
index ca8cbc2..2601e90 100644 (file)
@@ -112,6 +112,22 @@ deploy_schema = {
     "additionalProperties": False,
 }
 
+rebuild_schema = {
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "vm_rebuild": {
+        "type": "array",
+        "items": {
+            "type": "object",
+            "properties": {
+                "vdu-id": id_schema,
+                "vim_name": name_schema,
+                "member-vnf-index": name_schema,
+            },
+        },
+        "additionalProperties": True,
+    },
+}
+
 
 class ValidationError(Exception):
     def __init__(self, message, http_code=HTTPStatus.UNPROCESSABLE_ENTITY):
index 11a50aa..da1499d 100644 (file)
@@ -2519,12 +2519,29 @@ class vimconnector(vimconn.VimConnector):
                         server.resume()
                     elif server.status == "SHUTOFF":
                         server.start()
+                    else:
+                        self.logger.debug(
+                            "ERROR : Instance is not in SHUTOFF/PAUSE/SUSPEND state"
+                        )
+                        raise vimconn.VimConnException(
+                            "Cannot 'start' instance while it is in active state",
+                            http_code=vimconn.HTTP_Bad_Request,
+                        )
+
             elif "pause" in action_dict:
                 server.pause()
             elif "resume" in action_dict:
                 server.resume()
             elif "shutoff" in action_dict or "shutdown" in action_dict:
-                server.stop()
+                self.logger.debug("server status %s", server.status)
+                if server.status == "ACTIVE":
+                    server.stop()
+                else:
+                    self.logger.debug("ERROR: VM is not in Active state")
+                    raise vimconn.VimConnException(
+                        "VM is not in active state, stop operation is not allowed",
+                        http_code=vimconn.HTTP_Bad_Request,
+                    )
             elif "forceOff" in action_dict:
                 server.stop()  # TODO
             elif "terminate" in action_dict:
diff --git a/releasenotes/notes/feature_10922_stop_start_rebuild-917f01116bc078e3.yaml b/releasenotes/notes/feature_10922_stop_start_rebuild-917f01116bc078e3.yaml
new file mode 100644 (file)
index 0000000..9f21d66
--- /dev/null
@@ -0,0 +1,21 @@
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+---
+features:
+  - |
+    Feature 10922 - Stop, start and rebuild operations over a VDU of a running VNF instance
+    This feature enables performing Stop, start and rebuild operations on a VDU of a running VNF instance.