Instantiate VDU Worfklow and Activities 57/13157/8
authorPatricia Reinoso <patricia.reinoso@canonical.com>
Wed, 5 Apr 2023 15:27:20 +0000 (15:27 +0000)
committerGulsum Atici <gulsum.atici@canonical.com>
Thu, 6 Apr 2023 12:19:20 +0000 (15:19 +0300)
Using Juju

Change-Id: I5c0ab16e348f6f66573085269b8729bbc8854f15
Signed-off-by: Patricia Reinoso <patricia.reinoso@canonical.com>
osm_lcm/nglcm.py
osm_lcm/temporal/vdu_workflows.py [new file with mode: 0644]
osm_lcm/temporal/vim_activities.py

index 0e8811b..30e4b36 100644 (file)
@@ -38,6 +38,7 @@ from osm_lcm.temporal.vim_workflows import (
     VimDeleteWorkflow,
     VimUpdateWorkflow,
 )
+from osm_lcm.temporal.vdu_workflows import VduInstantiateWorkflow
 from temporalio.client import Client
 from temporalio.worker import Worker
 
@@ -127,7 +128,7 @@ class NGLcm:
             f"{self.main_config.temporal.host}:{str(self.main_config.temporal.port)}"
         )
         client = await Client.connect(temporal_api)
-        data_activity_instance = VimDbActivity(self.db)
+        vim_data_activity_instance = VimDbActivity(self.db)
         paas_connector_instance = JujuPaasConnector(self.db)
         nslcm_activity_instance = NsLcmActivity(self.db)
 
@@ -136,14 +137,18 @@ class NGLcm:
             VimCreateWorkflow,
             VimDeleteWorkflow,
             VimUpdateWorkflow,
+            VduInstantiateWorkflow,
         ]
         activities = [
-            data_activity_instance.update_vim_operation_state,
-            data_activity_instance.update_vim_state,
-            data_activity_instance.delete_vim_record,
+            vim_data_activity_instance.update_vim_operation_state,
+            vim_data_activity_instance.update_vim_state,
+            vim_data_activity_instance.delete_vim_record,
             nslcm_activity_instance.update_ns_lcm_operation_state,
             nslcm_activity_instance.no_op,
             paas_connector_instance.test_vim_connectivity,
+            paas_connector_instance.create_model_if_doesnt_exist,
+            paas_connector_instance.deploy_charm,
+            paas_connector_instance.check_charm_status,
         ]
 
         # Check if we are running under a debugger
diff --git a/osm_lcm/temporal/vdu_workflows.py b/osm_lcm/temporal/vdu_workflows.py
new file mode 100644 (file)
index 0000000..97a7b2a
--- /dev/null
@@ -0,0 +1,77 @@
+#######################################################################################
+# 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.
+
+from datetime import timedelta
+import logging
+from temporalio import workflow
+from temporalio.common import RetryPolicy
+
+from osm_common.dataclasses.temporal_dataclasses import (
+    VduInstantiateInput,
+    CreateModelInput,
+)
+from osm_common.temporal_constants import (
+    WORKFLOW_VDU_INSTANTIATE,
+    ACTIVITY_CREATE_MODEL_IF_DOESNT_EXIST,
+    ACTIVITY_DEPLOY_CHARM,
+    ACTIVITY_CHECK_CHARM_STATUS,
+    LCM_TASK_QUEUE,
+)
+
+_SANDBOXED = False
+retry_policy = RetryPolicy(maximum_attempts=3)
+default_schedule_to_close_timeout = timedelta(minutes=10)
+
+workflow.logger = logging.getLogger("lcm.temporal.vdu_workflows")
+
+
+@workflow.defn(name=WORKFLOW_VDU_INSTANTIATE, sandboxed=_SANDBOXED)
+class VduInstantiateWorkflow:
+    """Instantiate a VDU"""
+
+    @workflow.run
+    async def run(self, input: VduInstantiateInput) -> None:
+        try:
+            await workflow.execute_activity(
+                activity=ACTIVITY_CREATE_MODEL_IF_DOESNT_EXIST,
+                arg=CreateModelInput(input.vim_uuid, input.model_name),
+                activity_id=f"{ACTIVITY_CREATE_MODEL_IF_DOESNT_EXIST}-{input.vim_uuid}",
+                task_queue=LCM_TASK_QUEUE,
+                schedule_to_close_timeout=default_schedule_to_close_timeout,
+                retry_policy=retry_policy,
+            )
+
+            await workflow.execute_activity(
+                activity=ACTIVITY_DEPLOY_CHARM,
+                arg=input,
+                activity_id=f"{ACTIVITY_DEPLOY_CHARM}-{input.vim_uuid}",
+                task_queue=LCM_TASK_QUEUE,
+                schedule_to_close_timeout=default_schedule_to_close_timeout,
+                retry_policy=retry_policy,
+            )
+
+            await workflow.execute_activity(
+                activity=ACTIVITY_CHECK_CHARM_STATUS,
+                arg=input,
+                activity_id=f"{ACTIVITY_CHECK_CHARM_STATUS}-{input.vim_uuid}",
+                task_queue=LCM_TASK_QUEUE,
+                schedule_to_close_timeout=default_schedule_to_close_timeout,
+                retry_policy=retry_policy,
+            )
+
+        except Exception as e:
+            workflow.logger.error(f"{WORKFLOW_VDU_INSTANTIATE} failed with {str(e)}")
+            raise e
index 6307704..c84713a 100644 (file)
@@ -23,12 +23,17 @@ from osm_common.temporal_constants import (
     ACTIVITY_TEST_VIM_CONNECTIVITY,
     ACTIVITY_UPDATE_VIM_OPERATION_STATE,
     ACTIVITY_UPDATE_VIM_STATE,
+    ACTIVITY_CREATE_MODEL_IF_DOESNT_EXIST,
+    ACTIVITY_DEPLOY_CHARM,
+    ACTIVITY_CHECK_CHARM_STATUS,
 )
 from osm_common.dataclasses.temporal_dataclasses import (
     DeleteVimInput,
     TestVimConnectivityInput,
     UpdateVimOperationStateInput,
     UpdateVimStateInput,
+    CreateModelInput,
+    VduInstantiateInput,
 )
 
 activity.logger = logging.getLogger("lcm.temporal.vim_activities")
@@ -79,6 +84,10 @@ class JujuPaasConnector:
             endpoint, username, password, cacert, cloud_name, cloud_credentials
         )
 
+    def _get_libjuju(self, vim_uuid):
+        connection_info = self._get_connection_info(vim_uuid)
+        return Libjuju(connection_info)
+
     @activity.defn(name=ACTIVITY_TEST_VIM_CONNECTIVITY)
     async def test_vim_connectivity(
         self, test_connectivity_input: TestVimConnectivityInput
@@ -108,14 +117,101 @@ class JujuPaasConnector:
         vim_id = test_connectivity_input.vim_uuid
         controller = None
         try:
-            connection_info = self._get_connection_info(vim_id)
-            libjuju = Libjuju(connection_info)
+            libjuju = self._get_libjuju(vim_id)
             controller = await libjuju.get_controller()
             message = f"Connection to juju controller succeeded for {vim_id}"
             activity.logger.info(message)
         finally:
             await libjuju.disconnect_controller(controller)
 
+    @activity.defn(name=ACTIVITY_CREATE_MODEL_IF_DOESNT_EXIST)
+    async def create_model_if_doesnt_exist(
+        self, create_model_input: CreateModelInput
+    ) -> None:
+        """Connects to Juju Controller. Create a new model if model_name does not exist
+
+        Collaborators:
+            DB Read:            vim_accounts
+            Juju Controller:    Connect and create model.
+
+        Raises  (Retryable):
+            ApplicationError    If Juju controller is not reachable
+
+        Activity Lifecycle:
+            This activity should complete relatively quickly (in a few seconds).
+            However, it would be reasonable to wait more than 72 seconds (network timeout)
+            incase there are network issues.
+
+            This activity will not report a heartbeat due to its
+            short-running nature.
+
+            It is recommended, although not necessary to implement a
+            back-off strategy for this activity, as it will naturally block
+            and wait on each connection attempt.
+        """
+        model_name = create_model_input.model_name
+        libjuju = self._get_libjuju(create_model_input.vim_uuid)
+        await libjuju.add_model(model_name)
+
+    @activity.defn(name=ACTIVITY_DEPLOY_CHARM)
+    async def deploy_charm(self, deploy_charm_input: VduInstantiateInput) -> None:
+        """Deploys a charm.
+
+        Collaborators:
+            DB Read:            vim_accounts
+            Juju Controller:    Connect and deploy charm
+
+        Raises  (Retryable):
+            ApplicationError    If Juju controller is not reachable
+
+        Activity Lifecycle:
+            This activity should complete relatively quickly (in a few seconds).
+            However, it would be reasonable to wait more than 72 seconds (network timeout)
+            incase there are network issues.
+
+            This activity will not report a heartbeat due to its
+            short-running nature.
+
+            It is recommended, although not necessary to implement a
+            back-off strategy for this activity, as it will naturally block
+            and wait on each connection attempt.
+        """
+        model_name = deploy_charm_input.model_name
+        libjuju = self._get_libjuju(deploy_charm_input.vim_uuid)
+        charm_info = deploy_charm_input.charm_info
+        await libjuju.deploy_charm(
+            application_name=charm_info.app_name,
+            path=charm_info.entity_url,
+            model_name=model_name,
+            channel=charm_info.channel,
+        )
+
+    @activity.defn(name=ACTIVITY_CHECK_CHARM_STATUS)
+    async def check_charm_status(self, check_charm_status: VduInstantiateInput) -> None:
+        """Validates the credentials by attempting to connect to the given Juju Controller.
+
+        Collaborators:
+            DB Read:            vim_accounts
+            Juju Controller:    Connect to controller and check charm status.
+
+        Raises  (Retryable):
+            ApplicationError    If any of password, cacert, cloud_credentials is invalid
+                                or Juju controller is not reachable
+
+        Activity Lifecycle:
+            This activity should complete relatively quickly (in a few seconds).
+            However, it would be reasonable to wait more than 72 seconds (network timeout)
+            incase there are network issues.
+
+            This activity will not report a heartbeat due to its
+            short-running nature.
+
+            It is recommended, although not necessary to implement a
+            back-off strategy for this activity, as it will naturally block
+            and wait on each connection attempt.
+        """
+        pass
+
 
 class VimDbActivity:
     """Perform Database operations for VIM accounts.