from os import path
from osm_lcm.temporal.lcm_activities import NsLcmActivity
from osm_lcm.temporal.lcm_workflows import NsNoOpWorkflow
-from osm_lcm.temporal.vim_activities import VimDbActivity, JujuPaasConnector
+from osm_lcm.temporal.vim_activities import VimDbActivity
+from osm_lcm.temporal.juju_paas_activities import JujuPaasConnector
from osm_lcm.temporal.vim_workflows import (
VimCreateWorkflow,
VimDeleteWorkflow,
--- /dev/null
+#######################################################################################
+# 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.
+import logging
+from temporalio import activity
+from n2vc.temporal_libjuju import ConnectionInfo, Libjuju
+from osm_common.temporal_constants import (
+ ACTIVITY_TEST_VIM_CONNECTIVITY,
+ ACTIVITY_CREATE_MODEL_IF_DOESNT_EXIST,
+ ACTIVITY_DEPLOY_CHARM,
+ ACTIVITY_CHECK_CHARM_STATUS,
+)
+from osm_common.dataclasses.temporal_dataclasses import (
+ TestVimConnectivityInput,
+ CreateModelInput,
+ VduInstantiateInput,
+)
+
+
+class JujuPaasConnector:
+ """Handles Juju Controller operations.
+
+ Args:
+ db (object): Data Access Object
+ """
+
+ def __init__(self, db):
+ self.db = db
+ self.logger = logging.getLogger(f"lcm.act.{self.__class__.__name__}")
+
+ def _decrypt_password(self, vim_content: dict) -> str:
+ """Decrypt a password.
+ vim_content (dict): VIM details as a dictionary
+
+ Returns:
+ plain text password (str)
+ """
+ return self.db.decrypt(
+ vim_content["vim_password"],
+ schema_version=vim_content["schema_version"],
+ salt=vim_content["_id"],
+ )
+
+ def _get_connection_info(self, vim_id: str) -> ConnectionInfo:
+ """Get VIM details from database using vim_id and returns
+ the Connection Info to connect Juju Controller.
+
+ Args:
+ vim_id (str): VIM ID
+
+ Returns:
+ ConnectionInfo (object)
+ """
+ vim_content = self.db.get_one("vim_accounts", {"_id": vim_id})
+ endpoint = vim_content["vim_url"]
+ username = vim_content["vim_user"]
+ vim_config = vim_content["config"]
+ cacert = vim_config["ca_cert_content"]
+ cloud_name = vim_config["cloud"]
+ cloud_credentials = vim_config["cloud_credentials"]
+ password = self._decrypt_password(vim_content)
+ return ConnectionInfo(
+ 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
+ ) -> None:
+ """Validates the credentials by attempting to connect to the given Juju Controller.
+
+ Collaborators:
+ DB Read: vim_accounts
+ Juju Controller: Connect only
+
+ 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.
+ """
+ vim_id = test_connectivity_input.vim_uuid
+ controller = None
+ try:
+ libjuju = self._get_libjuju(vim_id)
+ controller = await libjuju.get_controller()
+ message = f"Connection to juju controller succeeded for {vim_id}"
+ self.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
from temporalio import workflow
from temporalio.common import RetryPolicy
-from osm_common.dataclasses.temporal_dataclasses import (
- VduInstantiateInput,
- CreateModelInput,
-)
+from osm_common.dataclasses.temporal_dataclasses import VduInstantiateInput
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,
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"""
+ def __init__(self):
+ self.logger = logging.getLogger(f"lcm.wfl.{self.__class__.__name__}")
+
@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,
)
except Exception as e:
- workflow.logger.error(f"{WORKFLOW_VDU_INSTANTIATE} failed with {str(e)}")
+ self.logger.error(f"{WORKFLOW_VDU_INSTANTIATE} failed with {str(e)}")
raise e
import logging
from temporalio import activity
from time import time
-from n2vc.temporal_libjuju import ConnectionInfo, Libjuju
from osm_common.temporal_constants import (
ACTIVITY_DELETE_VIM,
- 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")
-
-
-class JujuPaasConnector:
- """Handles Juju Controller operations.
-
- Args:
- db (object): Data Access Object
- """
-
- def __init__(self, db):
- self.db = db
-
- def _decrypt_password(self, vim_content: dict) -> str:
- """Decrypt a password.
- vim_content (dict): VIM details as a dictionary
-
- Returns:
- plain text password (str)
- """
- return self.db.decrypt(
- vim_content["vim_password"],
- schema_version=vim_content["schema_version"],
- salt=vim_content["_id"],
- )
-
- def _get_connection_info(self, vim_id: str) -> ConnectionInfo:
- """Get VIM details from database using vim_id and returns
- the Connection Info to connect Juju Controller.
-
- Args:
- vim_id (str): VIM ID
-
- Returns:
- ConnectionInfo (object)
- """
- vim_content = self.db.get_one("vim_accounts", {"_id": vim_id})
- endpoint = vim_content["vim_url"]
- username = vim_content["vim_user"]
- vim_config = vim_content["config"]
- cacert = vim_config["ca_cert_content"]
- cloud_name = vim_config["cloud"]
- cloud_credentials = vim_config["cloud_credentials"]
- password = self._decrypt_password(vim_content)
- return ConnectionInfo(
- 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
- ) -> None:
- """Validates the credentials by attempting to connect to the given Juju Controller.
-
- Collaborators:
- DB Read: vim_accounts
- Juju Controller: Connect only
-
- 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.
- """
- vim_id = test_connectivity_input.vim_uuid
- controller = None
- try:
- 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.
def __init__(self, db):
self.db = db
+ self.logger = logging.getLogger(f"lcm.act.{self.__class__.__name__}")
@activity.defn(name=ACTIVITY_UPDATE_VIM_STATE)
async def update_vim_state(self, data: UpdateVimStateInput) -> None:
}
self.db.set_one("vim_accounts", {"_id": data.vim_uuid}, update_vim_state)
- activity.logger.debug(
+ self.logger.debug(
f"Updated VIM {data.vim_uuid} to {data.operational_state.name}"
)
}
self.db.set_one("vim_accounts", {"_id": data.vim_uuid}, update_operation_state)
- activity.logger.debug(
+ self.logger.debug(
f"Updated VIM {data.vim_uuid} OP ID {data.op_id} to {data.op_state.name}"
)
"""
self.db.del_one("vim_accounts", {"_id": data.vim_uuid})
- activity.logger.debug(f"Removed VIM {data.vim_uuid}")
+ self.logger.debug(f"Removed VIM {data.vim_uuid}")