From 989602b0ef620c0b310d9dd4adeb9f387ca35023 Mon Sep 17 00:00:00 2001 From: Dario Faccin Date: Tue, 20 Jun 2023 16:12:29 +0200 Subject: [PATCH] OSMENG-1155 Implementation of Constants and Dataclasses Add stubs for common elements, workflows and activities Change-Id: If7a2aa8a6e6627df5293154bf48da742dea57e1c Signed-off-by: Dario Faccin --- .../dataclasses/temporal_dataclasses.py | 659 ------------------ osm_common/temporal/activities/base.py | 23 + osm_common/temporal/activities/lcm.py | 113 +++ osm_common/temporal/activities/ns.py | 180 +++++ osm_common/temporal/activities/paas.py | 231 ++++++ osm_common/temporal/activities/vim.py | 174 +++++ osm_common/temporal/activities/vnf.py | 420 +++++++++++ osm_common/temporal/dataclasses_common.py | 53 ++ osm_common/temporal/states.py | 57 ++ osm_common/temporal/workflows/base.py | 24 + osm_common/temporal/workflows/lcm.py | 167 +++++ osm_common/temporal/workflows/ns.py | 48 ++ osm_common/temporal/workflows/vdu.py | 55 ++ osm_common/temporal/workflows/vim.py | 108 +++ osm_common/temporal/workflows/vnf.py | 87 +++ osm_common/temporal_constants.py | 57 -- .../task_queues_mappings.py | 24 + 17 files changed, 1764 insertions(+), 716 deletions(-) delete mode 100644 osm_common/dataclasses/temporal_dataclasses.py create mode 100644 osm_common/temporal/activities/base.py create mode 100644 osm_common/temporal/activities/lcm.py create mode 100644 osm_common/temporal/activities/ns.py create mode 100644 osm_common/temporal/activities/paas.py create mode 100644 osm_common/temporal/activities/vim.py create mode 100644 osm_common/temporal/activities/vnf.py create mode 100644 osm_common/temporal/dataclasses_common.py create mode 100644 osm_common/temporal/states.py create mode 100644 osm_common/temporal/workflows/base.py create mode 100644 osm_common/temporal/workflows/lcm.py create mode 100644 osm_common/temporal/workflows/ns.py create mode 100644 osm_common/temporal/workflows/vdu.py create mode 100644 osm_common/temporal/workflows/vim.py create mode 100644 osm_common/temporal/workflows/vnf.py delete mode 100644 osm_common/temporal_constants.py create mode 100644 osm_common/temporal_task_queues/task_queues_mappings.py diff --git a/osm_common/dataclasses/temporal_dataclasses.py b/osm_common/dataclasses/temporal_dataclasses.py deleted file mode 100644 index 5827ab8..0000000 --- a/osm_common/dataclasses/temporal_dataclasses.py +++ /dev/null @@ -1,659 +0,0 @@ -####################################################################################### -# 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 dataclasses import dataclass -from enum import auto, IntEnum -from typing import List - - -####################################################################################### -# Defining States -class VimState(IntEnum): - PROCESSING = auto() - ENABLED = auto() - ERROR = auto() - - -class VimOperationState(IntEnum): - COMPLETED = auto() - FAILED = auto() - - -class NsState(IntEnum): - PROCESSING = auto() - INSTANTIATED = auto() - ERROR = auto() - - -class VnfLcmOperationState(IntEnum): - PROCESSING = auto() - COMPLETED = auto() - FAILED = auto() - - -class VnfInstantiationState(IntEnum): - NOT_INSTANTIATED = auto() - INSTANTIATED = auto() - - -class VnfState(IntEnum): - STOPPED = auto() - STARTED = auto() - - -class LcmOperationState(IntEnum): - PROCESSING = auto() - COMPLETED = auto() - FAILED = auto() - - -####################################################################################### -# Workflow Dataclasses - - -@dataclass -class VimOperationInput: - """ - Input dataclass for workflows that perform operations - (create, update, delete) on VIMs. - - Attributes: - ----------- - vim_uuid : str - The UUID of the VIM account as stored in the OSM vim - collection in Mongo - - op_id: str - The operation (task) id for this workflow. This is used - by the workflow at the end to update the status of the - operation in Mongo vim collection. - """ - - vim_uuid: str - op_id: str - - -@dataclass -class NsLcmOperationInput: - """ - Input dataclass for workflows that run as LCM operations. - - Attributes: - ----------- - - nslcmop: dict - A dictionary representing the nslcmop record from the - database. - """ - - nslcmop: dict - - -@dataclass -class CharmInfo: - """ - Input dataclass for - - Attributes: - ----------- - app_name : str - - channel: str - - entity_url: str - """ - - app_name: str - channel: str - entity_url: str - - -@dataclass -class GetVimCloudInput: - """ - Input dataclass for get vim cloud activity. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - - """ - - vnfr_uuid: str - - -@dataclass -class GetVimCloudOutput: - """ - Output dataclass for get vim cloud activity. - - Attributes: - ----------- - cloud : str - Type of the cloud which is used to Deploy VNF. - """ - - cloud: str - - -@dataclass -class VduComputeConstraints: - """ - Input dataclass for VDU constraints - - Attributes: - ----------- - cores : int (Number of virtual CPUs) - - mem: int (GB) - """ - - cores: int - mem: int - - -@dataclass -class VduInstantiateInput: - """ - Input dataclass for workflow that instantiates a VDU. - - vim_uuid: str - - model_name: str - - charm_info : CharmInfo - - constraints: VduComputeConstraints - - cloud: VIM cloud type - - config: Config details of application - """ - - vim_uuid: str - model_name: str - charm_info: CharmInfo - constraints: VduComputeConstraints - cloud: str - config: dict - - -@dataclass -class VnfInstantiateInput: - """ - Input dataclass for workflow that instantiates a VNF. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - - model_name: str - - instantiation_config: dict - The instantiation configuration of the VNF - - """ - - vnfr_uuid: str - model_name: str - instantiation_config: dict - - -@dataclass -class SetVnfModelInput: - """ - Input dataclass for activity that sets the VNF Model. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - - model_name: str - - """ - - vnfr_uuid: str - model_name: str - - -@dataclass -class VnfPrepareInput: - """ - Input dataclass for workflow that prepare a VNF. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - - model_name: str - - """ - - vnfr_uuid: str - model_name: str - - -@dataclass -class GetNsRecordInput: - """ - Input dataclass for getting NS record activity. - - Attributes: - ----------- - nsr_uuid : - The UUID of the NS record which is stored in the OSM nsrs - collection in Mongo. - - """ - - nsr_uuid: str - - -@dataclass -class GetNsRecordOutput: - """ - Output dataclass for getting NS record activity. - - Attributes: - ----------- - nsr : dict - NS record retrieved from Database.. - - """ - - nsr: dict - - -####################################################################################### -# Activity Dataclasses - - -@dataclass -class UpdateLcmOperationStateInput: - """ - Input dataclass for updating LCM Operations in the Mongo nslcmops - collection. The following attributes will be updated automatically - - statusEnteredTime - - _admin.modified - - Attributes: - ----------- - op_id: str - The operation (task) id for this activity. This is the key - to the record in nslcmops collection that will be updated. - - op_state : LcmOperationState - A representation of the state of the specified operation id, - such as PROCESSING, COMPLETED, or FAILED. - - stage: str - Human readable checkpoint message, intended only to give the - user feedback. - - error_message: str - Human readable error message if any failure occurred. - - detailed_status : str - Human readable message providing additional details to the - operation state, such as the error message explaining why - the operation failed. - """ - - op_id: str - op_state: LcmOperationState - stage: str - error_message: str - detailed_status: str - - -@dataclass -class TestVimConnectivityInput: - """ - Input dataclass for the Test Vim Connectivity Ativity - - Attributes: - ----------- - vim_uuid : str - The UUID of the VIM account as stored in the OSM vim - collection in Mongo - """ - - vim_uuid: str - - -@dataclass -class UpdateVimStateInput: - """ - Input dataclass for updating VIM state in the DB - - Attributes: - ----------- - vim_uuid : str - The UUID of the VIM account as stored in the OSM vim - collection in Mongo - - operational_state : VimState - A representation of the operational state (ENABLED or ERROR) - of the VIM. - - message : str - Human readable message providing additional details to the - operational state, such as the error message associated - with the ERROR operational_state. - """ - - vim_uuid: str - operational_state: VimState - message: str - - -@dataclass -class UpdateVimOperationStateInput: - """ - Input dataclass for updating VIM Operations in the Mongo VIM - collection. - - Attributes: - ----------- - vim_uuid : str - The UUID of the VIM account as stored in the OSM vim - collection in Mongo - - op_id: str - The operation (task) id for this workflow. This is used - to update the status of the operation in Mongo vim collection. - - op_state : VimOperationState - A representation of the state of the specified operation id, - such as COMPLETED, or FAILED. - - message : str - Human readable message providing additional details to the - operation state, such as the error message explaining why - the operation failed. - """ - - vim_uuid: str - op_id: str - op_state: VimOperationState - message: str - - -@dataclass -class DeleteVimInput: - """ - Input dataclass for deleting vim record from the database - - Attributes: - ----------- - vim_uuid : str - The UUID of the VIM account as stored in the OSM vim - collection in Mongo - - """ - - vim_uuid: str - - -@dataclass -class DeployNsInput: - """ - Input dataclass for - - Attributes: - ----------- - ns_uuid : str - The UUID of the NS as stored in the OSM nsr - collection in Mongo - """ - - ns_uuid: str - - -@dataclass -class UpdateNsStateInput: - """ - Input dataclass for updating NS state in the DB - - Attributes: - ----------- - ns_uuid : str - The UUID of the NS as stored in the OSM ns - collection in Mongo - - operational_state : NsState - A representation of the operational state (ENABLED or ERROR) - of the NS. - - message : str - Human readable message providing additional details to the - operational state, such as the error message associated - with the ERROR operational_state. - """ - - ns_uuid: str - state: NsState - message: str - - -@dataclass -class ModelInfo: - """ - Contains the information related to a model. - - Attributes: - ----------- - vim_uuid : str - The UUID of the VIM as stored in the OSM vim_accounts - collection in Mongo. - - model_name : str - Name of the Juju model used to deploy charms. - """ - - vim_uuid: str - model_name: str - - -@dataclass -class CheckCharmStatusInput: - """ - Input dataclass for checking on a specific charm's deployment - status - - Attributes: - ----------- - vim_uuid : str - The UUID of the VIM as stored in the OSM vim_accounts - collection in Mongo. - - model_name : str - Name of the model to create in Juju. - - application_name : str - Name of the application that the state is going to be - awaited. - - poll_interval : int (optional) - Time, in seconds, to wait between status checks. - """ - - vim_uuid: str - model_name: str - application_name: str - poll_interval: int = 1 - - -@dataclass -class ChangeVnfStateInput: - """ - Input dataclass for changing VNF State. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - - state : VnfState - A representation of the VNF state (STOPPED or STARTED). - """ - - vnfr_uuid: str - state: VnfState - - -@dataclass -class ChangeVnfInstantiationStateInput: - """ - Input dataclass for changing VNF Instantiation State. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - - state : VnfInstantiationState - A representation of the VNF instantiation state (NOT_INSTANTIATED or INSTANTIATED). - - """ - - vnfr_uuid: str - state: VnfInstantiationState - - -@dataclass -class GetTaskQueueInput: - """ - Input dataclass for get task queue activity. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - - """ - - vnfr_uuid: str - - -@dataclass -class GetTaskQueueOutput: - """ - Output dataclass for get task queue activity. - - Attributes: - ----------- - task_queue : str - Name of the queue which is used to Deploy VNF. - """ - - task_queue: str - - -@dataclass -class GetVnfRecordInput: - """ - Input dataclass for get vnf details activity. - - Attributes: - ----------- - vnfr_uuid : str - The UUID of the VNF which is stored in the OSM vnfrs - collection in Mongo. - """ - - vnfr_uuid: str - - -@dataclass -class GetVnfRecordOutput: - """ - Output dataclass for get vnf details activity. - - Attributes: - ----------- - vnfr : dict - VNF record retrieved from Database. - - """ - - vnfr: dict - - -@dataclass -class GetVnfDescriptorInput: - """ - Input dataclass for get vnf details activity. - - Attributes: - ----------- - vnfd_uuid : str - The UUID of the VNF descriptor which is stored in the OSM vnfds - collection in Mongo. - """ - - vnfd_uuid: str - - -@dataclass -class GetVnfDescriptorOutput: - """ - Output dataclass for get vnf details activity. - - Attributes: - ----------- - vnfd : dict - VNF descriptor retrieved from Database. - """ - - vnfd: dict - - -@dataclass -class GetVnfDetailsInput: - """ - Attributes: - ----------- - ns_uuid : str - The UUID of the NS from which to retrieve the VNF records. - """ - - ns_uuid: str - - -@dataclass -class GetVnfDetailsOutput: - """ - Attributes: - ----------- - vnf_details: list[(vnfr_ids: str, vnf_member_index_ref: str), .. ] - List of tuples including VNF details associated with the NS. - Tuple(VNF record IDs, vnf_member_index_ref) - """ - - vnf_details: List[tuple] diff --git a/osm_common/temporal/activities/base.py b/osm_common/temporal/activities/base.py new file mode 100644 index 0000000..d207fe3 --- /dev/null +++ b/osm_common/temporal/activities/base.py @@ -0,0 +1,23 @@ +####################################################################################### +# 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 + + +class BaseActivity: + def __init__(self): + self.logger = logging.getLogger(f"lcm.act.{self.__class__.__name__}") diff --git a/osm_common/temporal/activities/lcm.py b/osm_common/temporal/activities/lcm.py new file mode 100644 index 0000000..9298bd1 --- /dev/null +++ b/osm_common/temporal/activities/lcm.py @@ -0,0 +1,113 @@ +####################################################################################### +# 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 dataclasses import dataclass + +from osm_common.dbbase import DbBase +from osm_common.temporal.activities.base import BaseActivity +from osm_common.temporal.states import LcmOperationState + + +class NsLcmNoOp(BaseActivity): + """ + This is a simple No Operation Activity that simply logs the data + with which it was called. It can be used as a placeholder when + developing workflows, or can be enhanced with logic to throw + exceptions on specific conditions to test exception handling in + a workflow. + """ + + @dataclass + class Input: + """ + Input dataclass for workflows that run as LCM operations. + + Attributes: + ----------- + + nslcmop: dict + A dictionary representing the nslcmop record from the + database. + """ + + nslcmop: dict + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class UpdateNsLcmOperationState(BaseActivity): + """ + Changes the state of a LCM operation task. Should be done to + indicate progress, or completion of the task itself. + + Collaborators: + DB Write: nslcmops + + Raises (Retryable): + DbException If the target DB record does not exist or DB is not reachable. + + Activity Lifecycle: + This activity will not report a heartbeat due to its + short-running nature. + As this is a direct DB update, it is not recommended to have + any specific retry policy + """ + + @dataclass + class Input: + """ + Input dataclass for updating LCM Operations in the Mongo nslcmops + collection. The following attributes will be updated automatically + - statusEnteredTime + - _admin.modified + + Attributes: + ----------- + op_id: str + The operation (task) id for this activity. This is the key + to the record in nslcmops collection that will be updated. + + op_state : LcmOperationState + A representation of the state of the specified operation id, + such as PROCESSING, COMPLETED, or FAILED. + + stage: str + Human readable checkpoint message, intended only to give the + user feedback. + + error_message: str + Human readable error message if any failure occurred. + + detailed_status : str + Human readable message providing additional details to the + operation state, such as the error message explaining why + the operation failed. + """ + + op_id: str + op_state: LcmOperationState + stage: str + error_message: str + detailed_status: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() diff --git a/osm_common/temporal/activities/ns.py b/osm_common/temporal/activities/ns.py new file mode 100644 index 0000000..4f1f4fe --- /dev/null +++ b/osm_common/temporal/activities/ns.py @@ -0,0 +1,180 @@ +####################################################################################### +# 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 dataclasses import dataclass +from typing import List + + +from osm_common.dbbase import DbBase +from osm_common.temporal.activities.base import BaseActivity +from osm_common.temporal.states import NsState + + +class GetVnfDetails(BaseActivity): + """ + Gets the list of VNF record IDs, VNF member-index-refs for a given NS record ID. + + Collaborators: + DB Read: vnfrs + + Raises (Retryable): + DbException If the target DB record does not exist or DB is not reachable. + + Activity Lifecycle: + This activity will not report a heartbeat due to its short-running nature. + + Since this activity only reads from the DB, it is safe to retry, although + you may wish to have some back-off policy. + """ + + @dataclass + class Input: + """ + Attributes: + ----------- + ns_uuid : str + The UUID of the NS from which to retrieve the VNF records. + """ + + ns_uuid: str + + @dataclass + class Output: + """ + Attributes: + ----------- + vnf_details: list[(vnfr_ids: str, vnf_member_index_ref: str), .. ] + List of tuples including VNF details associated with the NS. + Tuple(VNF record IDs, vnf_member_index_ref) + """ + + vnf_details: List[tuple] + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> Output: + raise NotImplementedError() + + +class GetNsRecord(BaseActivity): + """Gets the NS record from Database. + + Collaborators: + DB Read: nsrs + + Raises (retryable): + DbException: If DB read operations fail, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than 10 + second). + + This activity will not report a heartbeat due to its + short-running nature. + + This is an idempotent activity. + + """ + + @dataclass + class Input: + """ + Input dataclass for getting NS record activity. + + Attributes: + ----------- + nsr_uuid : + The UUID of the NS record which is stored in the OSM nsrs + collection in Mongo. + + """ + + nsr_uuid: str + + @dataclass + class Output: + """ + Output dataclass for getting NS record activity. + + Attributes: + ----------- + nsr : dict + NS record retrieved from Database.. + + """ + + nsr: dict + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> Output: + raise NotImplementedError() + + +class UpdateNsState(BaseActivity): + """ + Changes the state of the NS itself. + + Collaborators: + DB Write: nsrs + + Raises (Retryable): + DbException If the target DB record does not exist or DB is not reachable. + + Activity Lifecycle: + This activity will not report a heartbeat due to its + short-running nature. + + As this is a direct DB update, it is not recommended to have + any specific retry policy + """ + + @dataclass + class Input: + """ + Input dataclass for updating NS state in the DB + + Attributes: + ----------- + ns_uuid : str + The UUID of the NS as stored in the OSM ns + collection in Mongo + + operational_state : NsState + A representation of the operational state (ENABLED or ERROR) + of the NS. + + message : str + Human readable message providing additional details to the + operational state, such as the error message associated + with the ERROR operational_state. + """ + + ns_uuid: str + state: NsState + message: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() diff --git a/osm_common/temporal/activities/paas.py b/osm_common/temporal/activities/paas.py new file mode 100644 index 0000000..a037282 --- /dev/null +++ b/osm_common/temporal/activities/paas.py @@ -0,0 +1,231 @@ +####################################################################################### +# 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 dataclasses import dataclass + +from osm_common.dbbase import DbBase +from osm_common.temporal.activities.base import BaseActivity +from osm_common.temporal.dataclasses_common import CharmInfo, VduComputeConstraints + + +class TestVimConnectivity(BaseActivity): + """Validates the credentials by attempting to connect to the given Juju Controller. + + Collaborators: + 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. + """ + + @dataclass + class Input: + """ + Input dataclass for the Test Vim Connectivity Ativity + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM account as stored in the OSM vim + collection in Mongo + """ + + vim_uuid: str + + def __init__(self, juju_controller): + super().__init__() + self.juju_controller = juju_controller + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class CreateModel(BaseActivity): + """Connects to Juju Controller. Creates a new model. + + Collaborators: + DB Read: vim_accounts + Juju Controller: Connect and create model. + + Raises (Retryable): + ApplicationError If Juju controller is not reachable. + If the model already exists. + + 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. + """ + + @dataclass + class Input: + """ + Contains the information related to a model. + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM as stored in the OSM vim_accounts + collection in Mongo. + + model_name : str + Name of the Juju model used to deploy charms. + """ + + vim_uuid: str + model_name: str + + def __init__(self, db: DbBase, juju_controller): + super().__init__() + self.db: DbBase = db + self.juju_controller = juju_controller + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class DeployCharm(BaseActivity): + """Deploys a charm. + + Collaborators: + Juju Controller: Connect and deploy charm + + Raises (Retryable): + ApplicationError If Juju controller is not reachable + If application already exists + + 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. + """ + + @dataclass + class Input: + """ + Input dataclass for workflow that instantiates a VDU. + + vim_uuid: str + + model_name: str + + charm_info : CharmInfo + + constraints: VduComputeConstraints + + cloud: VIM cloud type + + config: Config details of application + """ + + vim_uuid: str + model_name: str + charm_info: CharmInfo + constraints: VduComputeConstraints + cloud: str + config: dict + + def __init__(self, juju_controller): + super().__init__() + self.juju_controller = juju_controller + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class CheckCharmStatus(BaseActivity): + """Checks the ready status of the charm. This activity will block until the status of + the application is either "active" or "blocked". Additionally, it also blocks until + the workload status of each of its units is also either "active" or "blocked". + + Collaborators: + 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 will continue indefinitely until the specified charm deployment + has reached a ready state. Heartbeats are performed to ensure this activity + does not time out. + + A start-to-close of something reasonable (such as 5 minutes) should be implemented + at the workflow level and such a timeout shall trigger workflow failure logic. + """ + + @dataclass + class Input: + """ + Input dataclass for checking on a specific charm's deployment + status + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM as stored in the OSM vim_accounts + collection in Mongo. + + model_name : str + Name of the model to create in Juju. + + application_name : str + Name of the application that the state is going to be + awaited. + + poll_interval : int (optional) + Time, in seconds, to wait between status checks. + """ + + vim_uuid: str + model_name: str + application_name: str + poll_interval: int = 1 + + def __init__(self, juju_controller): + super().__init__() + self.juju_controller = juju_controller + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() diff --git a/osm_common/temporal/activities/vim.py b/osm_common/temporal/activities/vim.py new file mode 100644 index 0000000..e52b6a1 --- /dev/null +++ b/osm_common/temporal/activities/vim.py @@ -0,0 +1,174 @@ +####################################################################################### +# 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 dataclasses import dataclass + +from osm_common.dbbase import DbBase +from osm_common.temporal.activities.base import BaseActivity +from osm_common.temporal.states import VimOperationState, VimState + + +class UpdateVimState(BaseActivity): + """ + Changes the state of the VIM itself. Should be either + ENABLED or ERROR, however this activity does not validate + the state as no validation was done in OSM previously. + + Collaborators: + DB Write: vim_accounts + + Raises (Retryable): + DbException If the target DB record does not exist or DB is not reachable. + + Activity Lifecycle: + This activity will not report a heartbeat due to its + short-running nature. + + As this is a direct DB update, it is not recommended to have + any specific retry policy + """ + + @dataclass + class Input: + """ + Input dataclass for updating VIM state in the DB + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM account as stored in the OSM vim + collection in Mongo + + operational_state : VimState + A representation of the operational state (ENABLED or ERROR) + of the VIM. + + message : str + Human readable message providing additional details to the + operational state, such as the error message associated + with the ERROR operational_state. + """ + + vim_uuid: str + operational_state: VimState + message: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class UpdateVimOperationState(BaseActivity): + """ + Changes the state of a VIM operation task. Should be done to + indicate progress, or completion of the task itself. + + Collaborators: + DB Write: vim_accounts + + Raises (Retryable): + DbException If the target DB record does not exist or DB is not reachable. + + Activity Lifecycle: + This activity will not report a heartbeat due to its + short-running nature. + + As this is a direct DB update, it is not recommended to have + any specific retry policy + """ + + @dataclass + class Input: + """ + Input dataclass for updating VIM Operations in the Mongo VIM + collection. + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM account as stored in the OSM vim + collection in Mongo + + op_id: str + The operation (task) id for this workflow. This is used + to update the status of the operation in Mongo vim collection. + + op_state : VimOperationState + A representation of the state of the specified operation id, + such as COMPLETED, or FAILED. + + message : str + Human readable message providing additional details to the + operation state, such as the error message explaining why + the operation failed. + """ + + vim_uuid: str + op_id: str + op_state: VimOperationState + message: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class DeleteVimRecord(BaseActivity): + """ + Deletes the VIM record from the database. + + Collaborators: + DB Delete: vim_accounts + + Raises (Retryable): + DbException If the target DB record does not exist or DB is not reachable. + + Activity Lifecycle: + This activity will not report a heartbeat due to its + short-running nature. + + As this is a direct DB update, it is not recommended to have + any specific retry policy + """ + + @dataclass + class Input: + """ + Input dataclass for deleting vim record from the database + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM account as stored in the OSM vim + collection in Mongo + + """ + + vim_uuid: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() diff --git a/osm_common/temporal/activities/vnf.py b/osm_common/temporal/activities/vnf.py new file mode 100644 index 0000000..81f2982 --- /dev/null +++ b/osm_common/temporal/activities/vnf.py @@ -0,0 +1,420 @@ +####################################################################################### +# 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 dataclasses import dataclass + +from osm_common.dbbase import DbBase +from osm_common.temporal.activities.base import BaseActivity +from osm_common.temporal.states import VnfInstantiationState, VnfState + + +class ChangeVnfState(BaseActivity): + """Updates the VNF State in VNFR. + + Collaborators: + DB Write: vnfrs + + Raises (retryable): + DbException: If DB access/update fails, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than a + second). However, it would be reasonable to wait up to 10 + seconds. + + This activity will not report a heartbeat due to its + short-running nature. + + It is not necessary to implement a back-off strategy for this + activity, the operation is idempotent. + + """ + + @dataclass + class Input: + """ + Input dataclass for changing VNF State. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + state : VnfState + A representation of the VNF state (STOPPED or STARTED). + """ + + vnfr_uuid: str + state: VnfState + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class ChangeVnfInstantiationState(BaseActivity): + """Updates the VNF Instantiation State in VNFR. + + Collaborators: + DB Write: vnfrs + + Raises (retryable): + DbException: If DB access or update fails, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than a + second). However, it would be reasonable to wait up to 10 + seconds. + + This activity will not report a heartbeat due to its + short-running nature. + + It is not necessary to implement a back-off strategy for this + activity, the operation is idempotent. + + """ + + @dataclass + class Input: + """ + Input dataclass for changing VNF Instantiation State. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + state : VnfInstantiationState + A representation of the VNF instantiation state (NOT_INSTANTIATED or INSTANTIATED). + + """ + + vnfr_uuid: str + state: VnfInstantiationState + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() + + +class GetVnfRecord(BaseActivity): + """Gets the VNF record and VNF descriptor from Database. + + Collaborators: + DB read: vnfrs, vnfds + + Raises (retryable): + DbException: If DB read operations fail, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than 10 + second). + + This activity will not report a heartbeat due to its + short-running nature. + + This is an idempotent activity. + + """ + + @dataclass + class Input: + """ + Input dataclass for get vnf details activity. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + """ + + vnfr_uuid: str + + @dataclass + class Output: + """ + Output dataclass for get vnf details activity. + + Attributes: + ----------- + vnf_details: list[(vnfr_ids: str, vnf_member_index_ref: str), .. ] + List of tuples including VNF details associated with the NS. + Tuple(VNF record IDs, vnf_member_index_ref) + """ + + vnfr: dict + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> Output: + raise NotImplementedError() + + +class GetVnfDescriptor(BaseActivity): + """Gets the VNF record and VNF descriptor from Database. + + Collaborators: + DB read: vnfrs + + Raises (retryable): + DbException: If DB read operations fail, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than 10 + second). + + This activity will not report a heartbeat due to its + short-running nature. + + This is an idempotent activity. + + """ + + @dataclass + class Input: + """ + Input dataclass for get vnf descriptor activity. + + Attributes: + ----------- + vnfd_uuid : str + The UUID of the VNF descriptor which is stored in the OSM vnfds + collection in Mongo. + """ + + vnfd_uuid: str + + @dataclass + class Output: + """ + Output dataclass for get vnf details activity. + + Attributes: + ----------- + vnfd : dict + VNF descriptor retrieved from Database. + """ + + vnfd: dict + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> Output: + raise NotImplementedError() + + +class SendNotificationForVnf(BaseActivity): + """Perform Notification operations.""" + + @dataclass + class Input: + """ + Input dataclass for sending notifications for change in VNF Instantiation State. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + state : VnfInstantiationState + A representation of the VNF instantiation state (NOT_INSTANTIATED or INSTANTIATED). + + """ + + vnfr_uuid: str + state: VnfState + + async def __call__(self, activity_input: Input): + raise NotImplementedError() + + +class GetTaskQueue(BaseActivity): + """Finds the appropriate task queue according to VIM type of VNF. + + Collaborators: + DB read: vim_accounts, vnfrs + + Raises (retryable): + DbException: If DB read operations fail, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than a + second). However, it would be reasonable to wait up to 10 + seconds. + + This activity will not report a heartbeat due to its + short-running nature. + + It is not necessary to implement a back-off strategy for this + activity, the operation is idempotent. + + """ + + @dataclass + class Input: + """ + Input dataclass for get task queue activity. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + """ + + vnfr_uuid: str + + @dataclass + class Output: + """ + Output dataclass for get task queue activity. + + Attributes: + ----------- + task_queue : str + Name of the queue which is used to Deploy VNF. + """ + + task_queue: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> Output: + raise NotImplementedError() + + +class GetVimCloud(BaseActivity): + """Finds the cloud by checking the VIM account of VNF. + + Collaborators: + DB Read: vnfrs, vim_accounts + + Raises (retryable): + DbException: If DB read operations fail, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than a + second). However, it would be reasonable to wait up to 10 + seconds. + + This activity will not report a heartbeat due to its + short-running nature. + + It is not necessary to implement a back-off strategy for this + activity, the operation is idempotent. + + """ + + @dataclass + class Input: + """ + Input dataclass for get vim cloud activity. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + """ + + vnfr_uuid: str + + @dataclass + class Output: + """ + Output dataclass for get vim cloud activity. + + Attributes: + ----------- + cloud : str + Type of the cloud which is used to Deploy VNF. + """ + + cloud: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> Output: + raise NotImplementedError() + + +class SetVnfModel(BaseActivity): + """Updates the model name of VNF in VNFR. + + Collaborators: + DB Write: vnfrs + + Raises (retryable): + DbException: If DB access or update fails, the collection or DB record ID does not exist. + + Activity Lifecycle: + This activity should complete relatively quickly (less than a + second). However, it would be reasonable to wait up to 10 + seconds. + + This activity will not report a heartbeat due to its + short-running nature. + + It is not necessary to implement a back-off strategy for this + activity, the operation is idempotent. + + """ + + @dataclass + class Input: + """ + Input dataclass for workflow that instantiates a VNF. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + model_name: str + + """ + + vnfr_uuid: str + model_name: str + + def __init__(self, db: DbBase): + super().__init__() + self.db: DbBase = db + + async def __call__(self, activity_input: Input) -> None: + raise NotImplementedError() diff --git a/osm_common/temporal/dataclasses_common.py b/osm_common/temporal/dataclasses_common.py new file mode 100644 index 0000000..fc06643 --- /dev/null +++ b/osm_common/temporal/dataclasses_common.py @@ -0,0 +1,53 @@ +####################################################################################### +# 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 dataclasses import dataclass + + +@dataclass +class CharmInfo: + """ + Input dataclass for + + Attributes: + ----------- + app_name : str + + channel: str + + entity_url: str + """ + + app_name: str + channel: str + entity_url: str + + +@dataclass +class VduComputeConstraints: + """ + Input dataclass for VDU constraints + + Attributes: + ----------- + cores : int (Number of virtual CPUs) + + mem: int (GB) + """ + + cores: int + mem: int diff --git a/osm_common/temporal/states.py b/osm_common/temporal/states.py new file mode 100644 index 0000000..1c4c896 --- /dev/null +++ b/osm_common/temporal/states.py @@ -0,0 +1,57 @@ +####################################################################################### +# 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 enum import auto, IntEnum + + +class VimState(IntEnum): + PROCESSING = auto() + ENABLED = auto() + ERROR = auto() + + +class VimOperationState(IntEnum): + COMPLETED = auto() + FAILED = auto() + + +class NsState(IntEnum): + PROCESSING = auto() + INSTANTIATED = auto() + ERROR = auto() + + +class VnfLcmOperationState(IntEnum): + PROCESSING = auto() + COMPLETED = auto() + FAILED = auto() + + +class VnfInstantiationState(IntEnum): + NOT_INSTANTIATED = auto() + INSTANTIATED = auto() + + +class VnfState(IntEnum): + STOPPED = auto() + STARTED = auto() + + +class LcmOperationState(IntEnum): + PROCESSING = auto() + COMPLETED = auto() + FAILED = auto() diff --git a/osm_common/temporal/workflows/base.py b/osm_common/temporal/workflows/base.py new file mode 100644 index 0000000..44b73be --- /dev/null +++ b/osm_common/temporal/workflows/base.py @@ -0,0 +1,24 @@ +####################################################################################### +# 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 abc import ABC +import logging + + +class BaseWorkflow(ABC): + def __init__(self): + self.logger = logging.getLogger(f"lcm.wfl.{self.__class__.__name__}") diff --git a/osm_common/temporal/workflows/lcm.py b/osm_common/temporal/workflows/lcm.py new file mode 100644 index 0000000..ee5b6ad --- /dev/null +++ b/osm_common/temporal/workflows/lcm.py @@ -0,0 +1,167 @@ +####################################################################################### +# 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 abc import abstractmethod +from dataclasses import dataclass +from datetime import timedelta + +from osm_common.temporal.activities.lcm import UpdateNsLcmOperationState +from osm_common.temporal.workflows.base import BaseWorkflow +from osm_common.temporal.states import LcmOperationState +from temporalio import workflow +from temporalio.common import RetryPolicy +from temporalio.exceptions import ActivityError, ChildWorkflowError + + +class LcmOperationWorkflow(BaseWorkflow): + """ + An abstract base class representing a Lifecycle Management Operation. Any + workflows that need LCM OP control should extend this class and implement + the workflow method. + + Methods + ------- + + @abstractmethod run(self, workflow_input: Input) + Method for subclasses to implement the actual workflow that is being + wrapped in this operation. + + @workflow.run wrap_nslcmop(workflow_input: Input) + Must be implemented in every subclass exactly as follows: + @workflow.run + async def wrap_nslcmop(self, workflow_input: Input) -> None: + await super().wrap_nslcmop(workflow_input=workflow_input) + """ + + retry_policy = RetryPolicy(maximum_attempts=3) + no_retry_policy = RetryPolicy(maximum_attempts=1) + default_schedule_to_close_timeout = timedelta(minutes=10) + + @dataclass + class Input: + """ + Input dataclass for workflows that run as LCM operations. + + Attributes: + ----------- + + nslcmop: dict + A dictionary representing the nslcmop record from the + database. + """ + + nslcmop: dict + + def __init__(self): + super().__init__() + self.op_id = None + self.stage = "" + + async def wrap_nslcmop(self, workflow_input: Input): + self.op_id = workflow_input.nslcmop["_id"] + await self.update_operation_state(LcmOperationState.PROCESSING) + try: + await self.run(workflow_input=workflow_input) + + except ActivityError as e: + err_details = str(e.cause.with_traceback(e.__traceback__)) + self.logger.error(err_details) + await self.update_operation_state( + LcmOperationState.FAILED, + error_message=str(e.cause.message), + detailed_status=err_details, + ) + raise e + + except ChildWorkflowError as e: + err_details = str(e.cause.with_traceback(e.cause.__traceback__)) + self.logger.error(err_details) + await self.update_operation_state( + LcmOperationState.FAILED, + error_message=str(e.cause.message), + detailed_status=err_details, + ) + raise e + + except Exception as e: + self.logger.exception(e) + await self.update_operation_state( + LcmOperationState.FAILED, + error_message=str(e), + detailed_status=str(e), + ) + raise e + + await self.update_operation_state(LcmOperationState.COMPLETED) + + async def update_operation_state( + self, + op_state: LcmOperationState, + stage: str = None, + error_message: str = "", + detailed_status: str = "", + ) -> None: + if stage is not None: + self.stage = stage + update_input = UpdateNsLcmOperationState.Input( + op_id=self.op_id, + op_state=op_state, + stage=self.stage, + error_message=error_message, + detailed_status=detailed_status, + ) + await workflow.execute_activity( + activity=UpdateNsLcmOperationState.__name__, + arg=update_input, + activity_id=f"{UpdateNsLcmOperationState.__name__}-{self.op_id}", + schedule_to_close_timeout=LcmOperationWorkflow.default_schedule_to_close_timeout, + retry_policy=LcmOperationWorkflow.retry_policy, + ) + + @abstractmethod + async def run(self, workflow_input: Input): + pass + + +class NsNoOpWorkflow(LcmOperationWorkflow): + """ + This is a simple No Operation workflow that simply calls a No Operation + activity. It can be used as a placeholder when developing workflows. + """ + + @dataclass + class Input: + """ + Input dataclass for workflows that run as LCM operations. + + Attributes: + ----------- + + nslcmop: dict + A dictionary representing the nslcmop record from the + database. + """ + + nslcmop: dict + + @abstractmethod + async def wrap_nslcmop(self, workflow_input: Input) -> None: + pass + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass diff --git a/osm_common/temporal/workflows/ns.py b/osm_common/temporal/workflows/ns.py new file mode 100644 index 0000000..acd2670 --- /dev/null +++ b/osm_common/temporal/workflows/ns.py @@ -0,0 +1,48 @@ +####################################################################################### +# 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 abc import abstractmethod +from dataclasses import dataclass + +from osm_common.temporal.workflows.lcm import LcmOperationWorkflow + + +class NsInstantiateWorkflow(LcmOperationWorkflow): + """Instantiate a NS""" + + @dataclass + class Input: + """ + Input dataclass for workflows that run as LCM operations. + + Attributes: + ----------- + + nslcmop: dict + A dictionary representing the nslcmop record from the + database. + """ + + nslcmop: dict + + @abstractmethod + async def wrap_nslcmop(self, workflow_input) -> None: + pass + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass diff --git a/osm_common/temporal/workflows/vdu.py b/osm_common/temporal/workflows/vdu.py new file mode 100644 index 0000000..e7f2f84 --- /dev/null +++ b/osm_common/temporal/workflows/vdu.py @@ -0,0 +1,55 @@ +####################################################################################### +# 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 abc import abstractmethod +from dataclasses import dataclass + +from osm_common.temporal.dataclasses_common import CharmInfo, VduComputeConstraints +from osm_common.temporal.workflows.base import BaseWorkflow + + +class VduInstantiateWorkflow(BaseWorkflow): + """Instantiate a VDU""" + + @dataclass + class Input: + """ + Input dataclass for workflow that instantiates a VDU. + + vim_uuid: str + + model_name: str + + charm_info : CharmInfo + + constraints: VduComputeConstraints + + cloud: VIM cloud type + + config: Config details of application + """ + + vim_uuid: str + model_name: str + charm_info: CharmInfo + constraints: VduComputeConstraints + cloud: str + config: dict + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass diff --git a/osm_common/temporal/workflows/vim.py b/osm_common/temporal/workflows/vim.py new file mode 100644 index 0000000..89b19af --- /dev/null +++ b/osm_common/temporal/workflows/vim.py @@ -0,0 +1,108 @@ +####################################################################################### +# 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 abc import abstractmethod +from dataclasses import dataclass + +from osm_common.temporal.workflows.base import BaseWorkflow + + +class VimCreateWorkflow(BaseWorkflow): + """Creates VIM account by validating the VIM connectivity.""" + + @dataclass + class Input: + """ + Input dataclass for workflows that perform operations + (create, update, delete) on VIMs. + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM account as stored in the OSM vim + collection in Mongo + + op_id: str + The operation (task) id for this workflow. This is used + by the workflow at the end to update the status of the + operation in Mongo vim collection. + """ + + vim_uuid: str + op_id: str + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass + + +class VimUpdateWorkflow(VimCreateWorkflow): + """Updates VIM account state by validating the VIM connectivity.""" + + @dataclass + class Input: + """ + Input dataclass for workflows that perform operations + (create, update, delete) on VIMs. + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM account as stored in the OSM vim + collection in Mongo + + op_id: str + The operation (task) id for this workflow. This is used + by the workflow at the end to update the status of the + operation in Mongo vim collection. + """ + + vim_uuid: str + op_id: str + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass + + +class VimDeleteWorkflow(BaseWorkflow): + """Deletes VIM accounts.""" + + @dataclass + class Input: + """ + Input dataclass for workflows that perform operations + (create, update, delete) on VIMs. + + Attributes: + ----------- + vim_uuid : str + The UUID of the VIM account as stored in the OSM vim + collection in Mongo + + op_id: str + The operation (task) id for this workflow. This is used + by the workflow at the end to update the status of the + operation in Mongo vim collection. + """ + + vim_uuid: str + op_id: str + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass diff --git a/osm_common/temporal/workflows/vnf.py b/osm_common/temporal/workflows/vnf.py new file mode 100644 index 0000000..365f953 --- /dev/null +++ b/osm_common/temporal/workflows/vnf.py @@ -0,0 +1,87 @@ +####################################################################################### +# 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 abc import abstractmethod +from dataclasses import dataclass + +from osm_common.temporal.workflows.base import BaseWorkflow + + +class VnfInstantiateWorkflow(BaseWorkflow): + """Instantiate a VNF. + + Workflow Identifier: + It is recommended that the ID for the VNF is referred as a workflow + ID when invoking this workflow. + """ + + @dataclass + class Input: + """ + Input dataclass for workflow that instantiates a VNF. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + model_name: str + + instantiation_config: dict + The instantiation configuration of the VNF + + """ + + vnfr_uuid: str + model_name: str + instantiation_config: dict + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass + + +class VnfPrepareWorkflow(BaseWorkflow): + """Prepare a VNF. + + Workflow Identifier: + It is recommended that the ID for the VNF is referred as a workflow + ID when invoking this workflow. + """ + + @dataclass + class Input: + """ + Input dataclass for workflow that instantiates a VNF. + + Attributes: + ----------- + vnfr_uuid : str + The UUID of the VNF which is stored in the OSM vnfrs + collection in Mongo. + + model_name: str + + """ + + vnfr_uuid: str + model_name: str + + @abstractmethod + async def run(self, workflow_input: Input) -> None: + pass diff --git a/osm_common/temporal_constants.py b/osm_common/temporal_constants.py deleted file mode 100644 index 9a3af23..0000000 --- a/osm_common/temporal_constants.py +++ /dev/null @@ -1,57 +0,0 @@ -####################################################################################### -# 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. -####################################################################################### -# Task Queues -LCM_TASK_QUEUE = "lcm-task-queue" - -# Vim Type-Task Queue Mappings -VIM_TYPE_TASK_QUEUE_MAPPINGS = { - "paas": LCM_TASK_QUEUE, -} - -# Activities -ACTIVITY_NSLCM_NO_OP = "nslcm-no-op" -ACTIVITY_EXECUTE_NS_LCM_WORKFLOW = "execute-ns-lcm-workflow" -ACTIVITY_UPDATE_LCM_OPERATION_STATE = "update-lcm-operation-state" -ACTIVITY_DELETE_VIM = "delete-vim" -ACTIVITY_TEST_VIM_CONNECTIVITY = "test-vim-connectivity" -ACTIVITY_UPDATE_VIM_OPERATION_STATE = "update-vim-operation-state" -ACTIVITY_UPDATE_VIM_STATE = "update-vim-state" -ACTIVITY_GET_NS_RECORD = "get-ns-record" -ACTIVITY_GET_VNF_DETAILS = "get-vnf-details" -ACTIVITY_UPDATE_NS_STATE = "update-ns-state" -ACTIVITY_CREATE_MODEL = "create-model" -ACTIVITY_GET_MODEL_INFO = "get-model-info" -ACTIVITY_DEPLOY_CHARM = "deploy-charm" -ACTIVITY_CHECK_CHARM_STATUS = "check-charm-status" -ACTIVITY_CHANGE_VNF_STATE = "change-vnf-state" -ACTIVITY_CHANGE_VNF_INSTANTIATION_STATE = "change-vnf-instantiation-state" -ACTIVITY_SEND_NOTIFICATION_FOR_VNF = "send-notification-for-vnf" -ACTIVITY_GET_TASK_QUEUE = "get-task-queue" -ACTIVITY_GET_VNF_RECORD = "get-vnf-record" -ACTIVITY_GET_VNF_DESCRIPTOR = "get-vnf-descriptor" -ACTIVITY_SET_VNF_MODEL = "set-vnf-model" -ACTIVITY_GET_VIM_CLOUD = "get-vim-cloud" - -# Workflows -WORKFLOW_NSLCM_NO_OP = "nslcm-no-op" -WORKFLOW_VIM_CREATE = "vim-create" -WORKFLOW_VIM_UPDATE = "vim-update" -WORKFLOW_VIM_DELETE = "vim-delete" -WORKFLOW_NS_INSTANTIATE = "ns-instantiate" -WORKFLOW_VDU_INSTANTIATE = "vdu-instantiate" -WORKFLOW_VNF_INSTANTIATE = "vnf-instantiate" -WORKFLOW_VNF_PREPARE = "vnf-prepare" diff --git a/osm_common/temporal_task_queues/task_queues_mappings.py b/osm_common/temporal_task_queues/task_queues_mappings.py new file mode 100644 index 0000000..6a644a3 --- /dev/null +++ b/osm_common/temporal_task_queues/task_queues_mappings.py @@ -0,0 +1,24 @@ +####################################################################################### +# 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. +####################################################################################### + +# Task Queues +LCM_TASK_QUEUE = "lcm-task-queue" + +# Vim Type-Task Queue Mappings +VIM_TYPE_TASK_QUEUE_MAPPINGS = { + "paas": LCM_TASK_QUEUE, +} -- 2.25.1