import yaml
from osm_common.dbbase import DbException
from osm_common.temporal_constants import LCM_TASK_QUEUE
-from temporalio.client import Client
-from temporalio.worker import Worker
-
from osm_lcm.data_utils.database.database import Database
from osm_lcm.data_utils.lcm_config import LcmCfg
from osm_lcm.lcm_utils import LcmException
VnfSendNotifications,
)
from osm_lcm.temporal.vnf_workflows import VnfInstantiateWorkflow, VnfPrepareWorkflow
+from temporalio.client import Client
+from temporalio.worker import Worker
class NGLcm:
]
activities = [
ns_data_activity_instance.update_ns_state,
- ns_operation_instance.get_vnf_record_ids,
+ ns_operation_instance.get_vnf_details,
+ ns_operation_instance.get_ns_record,
nslcm_activity_instance.update_ns_lcm_operation_state,
nslcm_activity_instance.no_op,
paas_connector_instance.create_model,
vnf_data_activity_instance.change_vnf_instantiation_state,
vnf_operation_instance.get_task_queue,
vnf_operation_instance.get_vim_cloud,
- vnf_operation_instance.get_vnf_details,
+ vnf_operation_instance.get_vnf_descriptor,
+ vnf_operation_instance.get_vnf_record,
vnf_send_notifications_instance.send_notification_for_vnf,
vnf_data_activity_instance.set_vnf_model,
]
import base64
import logging
from dataclasses import dataclass
+
from juju.application import Application
from juju.controller import Controller
from n2vc.config import EnvironConfig
application_name=application_name,
channel=charm_info.channel,
constraints=constraints if constraints else None,
+ config=deploy_charm_input.config,
)
@activity.defn(name=ACTIVITY_CHECK_CHARM_STATUS)
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
-from temporalio import activity
import time
+
from osm_common.dataclasses.temporal_dataclasses import (
NsLcmOperationInput,
UpdateLcmOperationStateInput,
ACTIVITY_NSLCM_NO_OP,
)
from osm_lcm.data_utils.database.database import Database
+from temporalio import activity
class NsLcmActivity:
import logging
from abc import ABC, abstractmethod
from datetime import timedelta
-from temporalio import workflow
-from temporalio.common import RetryPolicy
-from temporalio.exceptions import ActivityError, ChildWorkflowError
from osm_common.dataclasses.temporal_dataclasses import (
LcmOperationState,
ACTIVITY_UPDATE_LCM_OPERATION_STATE,
WORKFLOW_NSLCM_NO_OP,
)
+from temporalio import workflow
+from temporalio.common import RetryPolicy
+from temporalio.exceptions import ActivityError, ChildWorkflowError
class LcmOperationWorkflow(ABC):
raise e
except ChildWorkflowError as e:
- err_details = str(e.cause.cause.cause.with_traceback(e.cause.__traceback__))
+ 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.cause.message),
+ error_message=str(e.cause.message),
detailed_status=err_details,
)
raise e
await self.update_operation_state(
LcmOperationState.FAILED,
error_message=str(e),
- detailed_status=err_details,
+ detailed_status=str(e),
)
raise e
from time import time
from osm_common.dataclasses.temporal_dataclasses import (
- GetVnfRecordIdsInput,
- GetVnfRecordIdsOutput,
+ GetNsRecordInput,
+ GetNsRecordOutput,
+ GetVnfDetailsInput,
+ GetVnfDetailsOutput,
UpdateNsStateInput,
)
from osm_common.temporal_constants import (
- ACTIVITY_GET_VNF_RECORD_IDS,
+ ACTIVITY_GET_NS_RECORD,
+ ACTIVITY_GET_VNF_DETAILS,
ACTIVITY_UPDATE_NS_STATE,
)
-from temporalio import activity
-
from osm_lcm.data_utils.database.database import Database
+from temporalio import activity
class NsOperations:
self.db: Database = db
self.logger = logging.getLogger(f"lcm.act.{self.__class__.__name__}")
- @activity.defn(name=ACTIVITY_GET_VNF_RECORD_IDS)
- async def get_vnf_record_ids(
- self, get_vnf_record_ids_input: GetVnfRecordIdsInput
- ) -> GetVnfRecordIdsOutput:
+ @activity.defn(name=ACTIVITY_GET_VNF_DETAILS)
+ async def get_vnf_details(
+ self, get_vnf_details_input: GetVnfDetailsInput
+ ) -> GetVnfDetailsOutput:
"""
- Gets the list of VNF record IDs for a given NS record ID.
+ Gets the list of VNF record IDs, VNF member-index-refs for a given NS record ID.
Collaborators:
DB Read: vnfrs
Since this activity only reads from the DB, it is safe to retry, although
you may wish to have some back-off policy.
"""
- vnfrs = self.db.get_list(
- "vnfrs", {"nsr-id-ref": get_vnf_record_ids_input.ns_uuid}
+ vnfrs = self.db.get_list("vnfrs", {"nsr-id-ref": get_vnf_details_input.ns_uuid})
+ return GetVnfDetailsOutput(
+ vnf_details=[(vnfr["id"], vnfr["member-vnf-index-ref"]) for vnfr in vnfrs]
)
- return GetVnfRecordIdsOutput(vnfr_ids=[vnfr["id"] for vnfr in vnfrs])
+
+ @activity.defn(name=ACTIVITY_GET_NS_RECORD)
+ async def get_ns_record(
+ self, get_ns_record_input: GetNsRecordInput
+ ) -> GetNsRecordOutput:
+ """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.
+
+ """
+ nsr = self.db.get_one("nsrs", {"_id": get_ns_record_input.nsr_uuid})
+ self.logger.debug("Got the nsr from Database for VNF operations.")
+ return GetNsRecordOutput(nsr=nsr)
class NsDbActivity:
# limitations under the License.
import asyncio
-from temporalio import workflow
-from temporalio.converter import value_to_type
-from temporalio.exceptions import ActivityError, ChildWorkflowError
import traceback
from osm_common.dataclasses.temporal_dataclasses import (
- GetVnfRecordIdsInput,
- GetVnfRecordIdsOutput,
+ GetNsRecordInput,
+ GetNsRecordOutput,
+ GetVnfDetailsInput,
+ GetVnfDetailsOutput,
ModelInfo,
NsLcmOperationInput,
NsState,
)
from osm_common.temporal_constants import (
ACTIVITY_CREATE_MODEL,
- ACTIVITY_GET_VNF_RECORD_IDS,
+ ACTIVITY_GET_NS_RECORD,
+ ACTIVITY_GET_VNF_DETAILS,
ACTIVITY_UPDATE_NS_STATE,
WORKFLOW_NS_INSTANTIATE,
WORKFLOW_VNF_INSTANTIATE,
)
from osm_lcm.temporal.lcm_workflows import LcmOperationWorkflow
+from temporalio import workflow
+from temporalio.converter import value_to_type
+from temporalio.exceptions import ActivityError, ChildWorkflowError
@workflow.defn(name=WORKFLOW_NS_INSTANTIATE, sandboxed=LcmOperationWorkflow._SANDBOXED)
async def workflow(self, input: NsLcmOperationInput) -> None:
self.logger.info(f"Executing {WORKFLOW_NS_INSTANTIATE} with {input}")
- # TODO: Can we clean up the input? Perhaps this workflow could receive NsInstantiateInput
- # directly.
+ # TODO: Can we clean up the input? Perhaps this workflow could receive NsInstantiateInput directly.
ns_uuid = input.nslcmop["nsInstanceId"]
vim_uuid = input.nslcmop["operationParams"]["vimAccountId"]
model_name = self._get_namespace(ns_uuid, vim_uuid)
schedule_to_close_timeout=LcmOperationWorkflow.default_schedule_to_close_timeout,
retry_policy=LcmOperationWorkflow.no_retry_policy,
)
-
- vnf_record_ids_output: GetVnfRecordIdsOutput = value_to_type(
- GetVnfRecordIdsOutput,
- await workflow.execute_activity(
- activity=ACTIVITY_GET_VNF_RECORD_IDS,
- arg=GetVnfRecordIdsInput(ns_uuid=ns_uuid),
- activity_id=f"{ACTIVITY_GET_VNF_RECORD_IDS}-{ns_uuid}",
+ activities_results = await asyncio.gather(
+ workflow.execute_activity(
+ activity=ACTIVITY_GET_VNF_DETAILS,
+ arg=GetVnfDetailsInput(ns_uuid=ns_uuid),
+ activity_id=f"{ACTIVITY_GET_VNF_DETAILS}-{ns_uuid}",
+ schedule_to_close_timeout=LcmOperationWorkflow.default_schedule_to_close_timeout,
+ retry_policy=LcmOperationWorkflow.no_retry_policy,
+ ),
+ workflow.execute_activity(
+ activity=ACTIVITY_GET_NS_RECORD,
+ arg=GetNsRecordInput(nsr_uuid=ns_uuid),
+ activity_id=f"{ACTIVITY_GET_NS_RECORD}-{ns_uuid}",
schedule_to_close_timeout=LcmOperationWorkflow.default_schedule_to_close_timeout,
retry_policy=LcmOperationWorkflow.no_retry_policy,
),
)
+ get_vnf_details, get_ns_record = value_to_type(
+ GetVnfDetailsOutput, activities_results[0]
+ ), value_to_type(GetNsRecordOutput, activities_results[1])
+
await asyncio.gather(
*(
workflow.execute_child_workflow(
workflow=WORKFLOW_VNF_INSTANTIATE,
arg=VnfInstantiateInput(
- vnfr_uuid=vnfr_uuid, model_name=model_name
+ vnfr_uuid=vnfr_uuid,
+ model_name=model_name,
+ instantiation_config=NsInstantiateWorkflow.get_vnf_config(
+ vnf_member_index_ref, get_ns_record.nsr
+ ),
),
id=f"{WORKFLOW_VNF_INSTANTIATE}-{vnfr_uuid}",
)
- for vnfr_uuid in vnf_record_ids_output.vnfr_ids
+ for vnfr_uuid, vnf_member_index_ref in get_vnf_details.vnf_details
)
)
raise e
except ChildWorkflowError as e:
- err_details = str(e.cause.cause.cause.with_traceback(e.cause.__traceback__))
+ err_details = str(e.cause.with_traceback(e.cause.__traceback__))
await self.update_ns_state(ns_uuid, NsState.INSTANTIATED, err_details)
self.logger.error(f"{WORKFLOW_NS_INSTANTIATE} failed with {err_details}")
raise e
def _get_namespace(self, ns_id: str, vim_id: str) -> str:
"""The NS namespace is the combination if the NS ID and the VIM ID."""
return ns_id[-12:] + "-" + vim_id[-12:]
+
+ @staticmethod
+ def get_vnf_config(vnf_member_index_ref: str, nsr: dict) -> dict:
+ """Get the VNF instantiation config
+ Args:
+ vnf_member_index_ref (str): VNF member-index-ref
+ nsr (dict): NS record
+
+ Returns:
+ vnf_config (dict) VNF instantiation config
+
+ """
+ for vnf_config in nsr.get("instantiate_params", {}).get("vnf", {}):
+ if vnf_config.get("member-vnf-index") == vnf_member_index_ref:
+ return vnf_config
+ return {}
from datetime import timedelta
import logging
-from temporalio import workflow
-from temporalio.common import RetryPolicy
-from temporalio.exceptions import ActivityError
import traceback
from osm_common.dataclasses.temporal_dataclasses import (
LCM_TASK_QUEUE,
WORKFLOW_VDU_INSTANTIATE,
)
+from temporalio import workflow
+from temporalio.common import RetryPolicy
+from temporalio.exceptions import ActivityError
_SANDBOXED = False
retry_policy = RetryPolicy(maximum_attempts=3)
# limitations under the License.
import logging
-from temporalio import activity
from time import time
+
from osm_common.temporal_constants import (
ACTIVITY_DELETE_VIM,
ACTIVITY_UPDATE_VIM_OPERATION_STATE,
UpdateVimStateInput,
)
from osm_lcm.data_utils.database.database import Database
+from temporalio import activity
class VimDbActivity:
from datetime import timedelta
import logging
-from temporalio import workflow
-from temporalio.common import RetryPolicy
-from temporalio.exceptions import ActivityError
import traceback
from osm_common.dataclasses.temporal_dataclasses import (
WORKFLOW_VIM_UPDATE,
WORKFLOW_VIM_DELETE,
)
+from temporalio import workflow
+from temporalio.common import RetryPolicy
+from temporalio.exceptions import ActivityError
_SANDBOXED = False
retry_policy = RetryPolicy(maximum_attempts=3)
# limitations under the License.
import logging
+from typing import List, Any
+
from osm_common.temporal_constants import (
ACTIVITY_CHANGE_VNF_STATE,
ACTIVITY_CHANGE_VNF_INSTANTIATION_STATE,
ACTIVITY_GET_TASK_QUEUE,
ACTIVITY_GET_VIM_CLOUD,
- ACTIVITY_GET_VNF_DETAILS,
+ ACTIVITY_GET_VNF_DESCRIPTOR,
+ ACTIVITY_GET_VNF_RECORD,
ACTIVITY_SEND_NOTIFICATION_FOR_VNF,
ACTIVITY_SET_VNF_MODEL,
VIM_TYPE_TASK_QUEUE_MAPPINGS,
GetTaskQueueOutput,
GetVimCloudInput,
GetVimCloudOutput,
- GetVnfDetailsInput,
- GetVnfDetailsOutput,
- VnfInstantiateInput,
+ GetVnfDescriptorInput,
+ GetVnfDescriptorOutput,
+ GetVnfRecordInput,
+ GetVnfRecordOutput,
+ SetVnfModelInput,
+ VduComputeConstraints,
)
from osm_lcm.data_utils.database.database import Database
from temporalio import activity
+CONFIG_IDENTIFIER = "config::"
+
+
class VnfOperations:
def __init__(self, db: Database):
self.db: Database = db
"""Finds the cloud by checking the VIM account of VNF.
Collaborators:
- DB Access Object
+ DB Read: vnfrs, vim_accounts
Raises (retryable):
DbException: If DB read operations fail, the collection or DB record ID does not exist.
self.logger.debug(f"Got the cloud type {cloud} for VNF operations.")
return GetVimCloudOutput(cloud=cloud)
- @activity.defn(name=ACTIVITY_GET_VNF_DETAILS)
- async def get_vnf_details(
- self, get_vnf_details_input: GetVnfDetailsInput
- ) -> GetVnfDetailsOutput:
+ @activity.defn(name=ACTIVITY_GET_VNF_RECORD)
+ async def get_vnf_record(
+ self, get_vnf_record_input: GetVnfRecordInput
+ ) -> GetVnfRecordOutput:
+ """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.
+
+ """
+ vnfr = self.db.get_one("vnfrs", {"_id": get_vnf_record_input.vnfr_uuid})
+ self.logger.debug("Got the vnfr from Database for VNF operations.")
+ return GetVnfRecordOutput(vnfr=vnfr)
+
+ @activity.defn(name=ACTIVITY_GET_VNF_DESCRIPTOR)
+ async def get_vnf_descriptor(
+ self, get_vnf_descriptor_input: GetVnfDescriptorInput
+ ) -> GetVnfDescriptorOutput:
"""Gets the VNF record and VNF descriptor from Database.
Collaborators:
- DB read: vnfrs, vnfds
+ DB read: vnfds
Raises (retryable):
DbException: If DB read operations fail, the collection or DB record ID does not exist.
This is an idempotent activity.
"""
- vnfr = self.db.get_one("vnfrs", {"_id": get_vnf_details_input.vnfr_uuid})
- vnfd = self.db.get_one("vnfds", {"_id": vnfr["vnfd-id"]})
+ vnfd = self.db.get_one("vnfds", {"_id": get_vnf_descriptor_input.vnfd_uuid})
self.logger.debug("Got the vnfr and vnfd from Database for VNF operations.")
- return GetVnfDetailsOutput(vnfr=vnfr, vnfd=vnfd)
+ return GetVnfDescriptorOutput(vnfd=vnfd)
+
+ @staticmethod
+ def get_vdu_instantiation_params(
+ vdu_id: str, vnf_instantiation_config: dict
+ ) -> dict:
+ for vdu in vnf_instantiation_config.get("vdu", []):
+ if vdu.get("id") == vdu_id:
+ return vdu.get("configurable-properties", {})
+ return {}
+
+ @staticmethod
+ def get_compute_constraints(vdu: dict, vnfd: dict) -> VduComputeConstraints:
+ compute_desc_id = vdu.get("virtual-compute-desc")
+ if not compute_desc_id:
+ return VduComputeConstraints(cores=0, mem=0)
+ flavor_details = VnfOperations._get_flavor_details(compute_desc_id, vnfd)
+ if not flavor_details:
+ return VduComputeConstraints(cores=0, mem=0)
+
+ cpu_cores = flavor_details.get("virtual-cpu", {}).get("num-virtual-cpu", 0)
+ memory_gb = flavor_details.get("virtual-memory", {}).get("size", 0)
+ return VduComputeConstraints(cores=cpu_cores, mem=int(memory_gb))
+
+ @staticmethod
+ def _get_flavor_details(compute_desc_id: str, vnfd: dict) -> Any:
+ for flavor in vnfd.get("virtual-compute-desc", []):
+ if flavor.get("id") == compute_desc_id:
+ return flavor
+ return None
+
+ @staticmethod
+ def get_application_config(vdu: dict, vdu_instantiation_config: dict) -> dict:
+ configurable_properties = vdu.get("configurable-properties", [])
+
+ config_from_descriptor = VnfOperations._get_only_config_items(
+ VnfOperations._list_to_dict(configurable_properties)
+ )
+
+ config_from_instantiation = VnfOperations._get_only_config_items(
+ vdu_instantiation_config
+ )
+ return {**config_from_descriptor, **config_from_instantiation}
+
+ @staticmethod
+ def _get_only_config_items(config: dict) -> dict:
+ return {
+ key[len(CONFIG_IDENTIFIER) :]: value
+ for key, value in config.items()
+ if key.startswith(CONFIG_IDENTIFIER)
+ }
+
+ @staticmethod
+ def _list_to_dict(indata: List[dict]) -> dict:
+ return {
+ item["key"]: item["value"]
+ for item in indata
+ if item.get("key") and item.get("value")
+ }
class VnfDbActivity:
)
@activity.defn(name=ACTIVITY_SET_VNF_MODEL)
- async def set_vnf_model(self, set_vnf_model_input: VnfInstantiateInput) -> None:
+ async def set_vnf_model(self, set_vnf_model_input: SetVnfModelInput) -> None:
"""Updates the model name of VNF in VNFR.
Collaborators:
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
+import asyncio
from datetime import timedelta
import logging
-from temporalio import workflow
-from temporalio.converter import value_to_type
-from temporalio.common import RetryPolicy
-from temporalio.exceptions import ActivityError, ChildWorkflowError
import traceback
+from typing import Tuple
from osm_common.dataclasses.temporal_dataclasses import (
ChangeVnfInstantiationStateInput,
GetTaskQueueOutput,
GetVimCloudInput,
GetVimCloudOutput,
- GetVnfDetailsInput,
- GetVnfDetailsOutput,
- VduComputeConstraints,
+ GetVnfDescriptorInput,
+ GetVnfDescriptorOutput,
+ GetVnfRecordInput,
+ GetVnfRecordOutput,
+ SetVnfModelInput,
VduInstantiateInput,
VnfInstantiateInput,
VnfInstantiationState,
+ VnfPrepareInput,
VnfState,
)
-
from osm_common.temporal_constants import (
ACTIVITY_CHANGE_VNF_INSTANTIATION_STATE,
ACTIVITY_SEND_NOTIFICATION_FOR_VNF,
ACTIVITY_CHANGE_VNF_STATE,
ACTIVITY_GET_TASK_QUEUE,
ACTIVITY_GET_VIM_CLOUD,
- ACTIVITY_GET_VNF_DETAILS,
+ ACTIVITY_GET_VNF_RECORD,
+ ACTIVITY_GET_VNF_DESCRIPTOR,
ACTIVITY_SET_VNF_MODEL,
LCM_TASK_QUEUE,
WORKFLOW_VDU_INSTANTIATE,
WORKFLOW_VNF_PREPARE,
)
from osm_lcm.temporal.juju_paas_activities import CharmInfoUtils
+from osm_lcm.temporal.vnf_activities import VnfOperations
+from temporalio import workflow
+from temporalio.converter import value_to_type
+from temporalio.common import RetryPolicy
+from temporalio.exceptions import ActivityError, ChildWorkflowError
_SANDBOXED = False
retry_policy = RetryPolicy(maximum_attempts=3)
id=f"{WORKFLOW_VNF_PREPARE}-{input.vnfr_uuid}",
)
- get_vnf_details = value_to_type(
- GetVnfDetailsOutput,
+ get_vnf_record = value_to_type(
+ GetVnfRecordOutput,
await workflow.execute_activity(
- activity=ACTIVITY_GET_VNF_DETAILS,
- arg=GetVnfDetailsInput(input.vnfr_uuid),
- activity_id=f"{ACTIVITY_GET_VNF_DETAILS}-{input.vnfr_uuid}",
+ activity=ACTIVITY_GET_VNF_RECORD,
+ arg=GetVnfRecordInput(input.vnfr_uuid),
+ activity_id=f"{ACTIVITY_GET_VNF_RECORD}-{input.vnfr_uuid}",
task_queue=vnf_task_queue.task_queue,
schedule_to_close_timeout=default_schedule_to_close_timeout,
retry_policy=retry_policy,
),
)
-
- get_cloud = value_to_type(
- GetVimCloudOutput,
- await workflow.execute_activity(
+ activities_results = await asyncio.gather(
+ workflow.execute_activity(
+ activity=ACTIVITY_GET_VNF_DESCRIPTOR,
+ arg=GetVnfDescriptorInput(get_vnf_record.vnfr["vnfd-id"]),
+ activity_id=f"{ACTIVITY_GET_VNF_DESCRIPTOR}-{get_vnf_record.vnfr['vnfd-id']}",
+ task_queue=vnf_task_queue.task_queue,
+ schedule_to_close_timeout=default_schedule_to_close_timeout,
+ retry_policy=retry_policy,
+ ),
+ workflow.execute_activity(
activity=ACTIVITY_GET_VIM_CLOUD,
arg=GetVimCloudInput(input.vnfr_uuid),
activity_id=f"{ACTIVITY_GET_VIM_CLOUD}-{input.vnfr_uuid}",
retry_policy=retry_policy,
),
)
+ get_vnf_descriptor, get_cloud = value_to_type(
+ GetVnfDescriptorOutput, activities_results[0]
+ ), value_to_type(GetVimCloudOutput, activities_results[1])
await self.instantiate_vdus(
- vnfr=get_vnf_details.vnfr,
- vnfd=get_vnf_details.vnfd,
+ vnfr=get_vnf_record.vnfr,
+ vnfd=get_vnf_descriptor.vnfd,
task_queue=vnf_task_queue.task_queue,
cloud=get_cloud.cloud,
+ vnf_instantiation_config=input.instantiation_config,
)
await self.update_vnf_instantiation_state(
ChangeVnfInstantiationStateInput(
raise e
except ChildWorkflowError as e:
- err_details = str(e.cause.cause.with_traceback(e.cause.__traceback__))
+ err_details = str(e.cause.with_traceback(e.cause.__traceback__))
await self.update_vnf_instantiation_state(
ChangeVnfInstantiationStateInput(
vnfr_uuid=input.vnfr_uuid, state=VnfInstantiationState.INSTANTIATED
)
@staticmethod
- async def instantiate_vdus(vnfr: dict, vnfd: dict, task_queue: str, cloud: str):
+ async def instantiate_vdus(
+ vnfr: dict,
+ vnfd: dict,
+ task_queue: str,
+ cloud: str,
+ vnf_instantiation_config: dict,
+ ):
for vdu in vnfd.get("vdu"):
(
vdu_instantiate_input,
vdu_instantiate_workflow_id,
- ) = VnfInstantiateWorkflow.get_vdu_instantiate_input(
- vnfr=vnfr, vnfd=vnfd, vdu=vdu, cloud=cloud
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=vnfr,
+ vnfd=vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config=vnf_instantiation_config,
)
await workflow.execute_child_workflow(
workflow=WORKFLOW_VDU_INSTANTIATE,
)
@staticmethod
- def get_flavor_details(compute_desc_id: str, vnfd: dict):
- if not compute_desc_id:
- return {}
- flavor_details = next(
- filter(
- lambda flavor: flavor.get("id") == compute_desc_id,
- vnfd.get("virtual-compute-desc", {}),
- ),
- {},
- )
- return flavor_details
-
- @staticmethod
- def get_compute_constraints(vdu: dict, vnfd: dict) -> VduComputeConstraints:
- compute_desc_id = vdu.get("virtual-compute-desc", "")
- flavor_details = VnfInstantiateWorkflow.get_flavor_details(
- compute_desc_id, vnfd
- )
- if not flavor_details:
- return VduComputeConstraints(cores=0, mem=0)
-
- cpu_cores = (
- flavor_details["virtual-cpu"].get("num-virtual-cpu", 0)
- if flavor_details.get("virtual-cpu")
- else 0
- )
- memory_gb = (
- flavor_details["virtual-memory"].get("size", 0)
- if flavor_details.get("virtual-memory")
- else 0
- )
- return VduComputeConstraints(cores=cpu_cores, mem=int(memory_gb))
-
- @staticmethod
- def get_vdu_instantiate_input(vnfr: dict, vnfd: dict, vdu: dict, cloud: str):
+ def _get_vdu_instantiate_info(
+ vnfr, vnfd, vdu, cloud, vnf_instantiation_config
+ ) -> Tuple[VduInstantiateInput, str]:
+ """Calculates the VDU instantiate input data without reaching Database."""
model_name = vnfr.get("namespace")
vim_id = vnfr.get("vim-account-id")
sw_image_descs = vnfd.get("sw-image-desc")
vdu_info = CharmInfoUtils.get_charm_info(vdu, sw_image_descs)
- compute_constraints = VnfInstantiateWorkflow.get_compute_constraints(vdu, vnfd)
+ vdu_instantiation_config = VnfOperations.get_vdu_instantiation_params(
+ vdu["id"], vnf_instantiation_config
+ )
+ compute_constraints = VnfOperations.get_compute_constraints(vdu, vnfd)
+ config = VnfOperations.get_application_config(vdu, vdu_instantiation_config)
vdu_instantiate_input = VduInstantiateInput(
vim_uuid=vim_id,
model_name=model_name,
charm_info=vdu_info,
constraints=compute_constraints,
cloud=cloud,
- config={},
+ config=config,
)
vdu_instantiate_workflow_id = (
vdu_instantiate_input.model_name
self.logger = logging.getLogger(f"lcm.wfl.{self.__class__.__name__}")
@workflow.run
- async def run(self, wf_input: VnfInstantiateInput) -> None:
+ async def run(self, wf_input: VnfPrepareInput) -> None:
try:
await workflow.execute_activity(
activity=ACTIVITY_SET_VNF_MODEL,
- arg=wf_input,
+ arg=SetVnfModelInput(wf_input.vnfr_uuid, wf_input.model_name),
activity_id=f"{ACTIVITY_SET_VNF_MODEL}-{wf_input.vnfr_uuid}",
task_queue=LCM_TASK_QUEUE,
schedule_to_close_timeout=default_schedule_to_close_timeout,
import asyncio
from unittest import TestCase
import unittest.mock as mock
+from unittest.mock import ANY, AsyncMock, Mock
from juju.application import Application
from juju.controller import Controller
from osm_lcm.temporal.juju_paas_activities import JujuPaasConnector
from parameterized import parameterized
from temporalio.testing import ActivityEnvironment
-from unittest.mock import ANY, AsyncMock, Mock
namespace = "some-namespace"
vim_content = {
entity_url = "ch:my-charm"
cloud_k8s = "microk8s"
cloud_other = "other"
- config = {}
+ config = {"domain_name1": "osm.org", "domain_name2": "osm.com"}
charm_info = CharmInfo(app_name, channel, entity_url)
- vdu_instantiate_input_with_constraints_k8s = VduInstantiateInput(
+ vdu_instantiate_input_with_constraints_k8s_without_config = VduInstantiateInput(
+ vim_content["_id"],
+ namespace,
+ charm_info,
+ VduComputeConstraints(mem=1, cores=1),
+ cloud_k8s,
+ {},
+ )
+ vdu_instantiate_input_with_constraints_k8s_with_config = VduInstantiateInput(
vim_content["_id"],
namespace,
charm_info,
config,
)
- async def test_deploy_charm_with_constraints_k8s_cloud(self):
- await self.env.run(
- self.juju_paas.deploy_charm, self.vdu_instantiate_input_with_constraints_k8s
- )
- self.model.deploy.assert_called_once_with(
- entity_url=self.entity_url,
- application_name=self.app_name,
- channel=self.channel,
- constraints={"mem": 1024},
- )
-
- async def test_deploy_charm_with_constraints_other_cloud(self):
- await self.env.run(
- self.juju_paas.deploy_charm,
- VduInstantiateInput(
- vim_content["_id"],
- namespace,
- self.charm_info,
- VduComputeConstraints(mem=1, cores=1),
- self.cloud_other,
- self.config,
+ @parameterized.expand(
+ [
+ (
+ "k8s_cloud_without_config_with_constraints",
+ vdu_instantiate_input_with_constraints_k8s_without_config,
+ {"mem": 1024},
+ {},
),
- )
- self.model.deploy.assert_called_once_with(
- entity_url=self.entity_url,
- application_name=self.app_name,
- channel=self.channel,
- constraints={"mem": 1024, "cores": 1},
- )
-
- async def test_deploy_charm_without_constraints_k8s_cloud(self):
- await self.env.run(
- self.juju_paas.deploy_charm,
- VduInstantiateInput(
- vim_content["_id"],
- namespace,
- self.charm_info,
- VduComputeConstraints(mem=0, cores=0),
- self.cloud_k8s,
- self.config,
+ (
+ "k8s_cloud_with_config_with_constraints",
+ vdu_instantiate_input_with_constraints_k8s_with_config,
+ {"mem": 1024},
+ config,
),
- )
- self.model.deploy.assert_called_once_with(
- entity_url=self.entity_url,
- application_name=self.app_name,
- channel=self.channel,
- constraints=None,
- )
-
- async def test_deploy_charm_without_constraints_other_cloud(self):
+ (
+ "k8s_cloud_with_config_without_constraints",
+ VduInstantiateInput(
+ vim_content["_id"],
+ namespace,
+ charm_info,
+ VduComputeConstraints(mem=0, cores=0),
+ cloud_k8s,
+ config,
+ ),
+ None,
+ config,
+ ),
+ (
+ "other_cloud_without_config_with_constraints",
+ VduInstantiateInput(
+ vim_content["_id"],
+ namespace,
+ charm_info,
+ VduComputeConstraints(mem=1, cores=1),
+ cloud_other,
+ {},
+ ),
+ {"mem": 1024, "cores": 1},
+ {},
+ ),
+ (
+ "other_cloud_without_config_without_constraints",
+ VduInstantiateInput(
+ vim_content["_id"],
+ namespace,
+ charm_info,
+ VduComputeConstraints(mem=0, cores=0),
+ cloud_other,
+ {},
+ ),
+ None,
+ {},
+ ),
+ ]
+ )
+ async def test_deploy_charm__model_deployed_with_expected_constraints_and_config(
+ self, _, vdu_instantiate_input, expected_constraint, expected_config
+ ):
await self.env.run(
self.juju_paas.deploy_charm,
- VduInstantiateInput(
- vim_content["_id"],
- namespace,
- self.charm_info,
- VduComputeConstraints(mem=0, cores=0),
- self.cloud_other,
- self.config,
- ),
+ vdu_instantiate_input,
)
self.model.deploy.assert_called_once_with(
entity_url=self.entity_url,
application_name=self.app_name,
channel=self.channel,
- constraints=None,
+ constraints=expected_constraint,
+ config=expected_config,
)
- async def test_deploy_charm_app_already_exists(self):
+ async def test_deploy_charm__app_already_exists__get_expected_error_details(self):
self.add_application(self.app_name)
with self.assertRaises(Exception) as err:
await self.env.run(
self.juju_paas.deploy_charm,
- self.vdu_instantiate_input_with_constraints_k8s,
+ self.vdu_instantiate_input_with_constraints_k8s_without_config,
)
self.model.deploy.assert_not_called()
self.assertEqual(
"Application {} already exists".format(self.app_name),
)
- async def test_deploy_charm_raises_exception(self):
+ async def test_deploy_charm__juju_error_occured__app_is_not_deployed(self):
self.controller.get_model.side_effect = JujuError()
with self.assertRaises(JujuError):
await self.env.run(
self.juju_paas.deploy_charm,
- self.vdu_instantiate_input_with_constraints_k8s,
+ self.vdu_instantiate_input_with_constraints_k8s_without_config,
)
self.model.deploy.assert_not_called()
constraints = VduComputeConstraints(mem=1, cores=1)
no_constraints = VduComputeConstraints(mem=0, cores=0)
- def test_get_application_constraints_k8s_cloud(self):
- result = JujuPaasConnector._get_application_constraints(
- self.constraints, "kubernetes"
- )
- self.assertEqual(result, {"mem": 1024})
-
- def test_get_application_constraints_aws_cloud(self):
- result = JujuPaasConnector._get_application_constraints(self.constraints, "aws")
- self.assertEqual(result, {"cores": 1, "mem": 1024})
-
- def test_get_application_constraints_no_constraints_aws(self):
- result = JujuPaasConnector._get_application_constraints(
- self.no_constraints, "aws"
- )
- self.assertEqual(result, {})
-
- def test_get_application_constraints_no_constraints_microk8s(self):
- result = JujuPaasConnector._get_application_constraints(
- self.no_constraints, "microk8s"
- )
- self.assertEqual(result, {})
-
- def test_get_application_constraints_empty_cloud(self):
- result = JujuPaasConnector._get_application_constraints(self.constraints, "")
- self.assertEqual(result, {"cores": 1, "mem": 1024})
+ @parameterized.expand(
+ [
+ (
+ "k8s_cloud_with_constraints",
+ constraints,
+ "kubernetes",
+ {"mem": 1024},
+ ),
+ (
+ "aws_cloud_with_constraints",
+ constraints,
+ "aws",
+ {"cores": 1, "mem": 1024},
+ ),
+ (
+ "aws_cloud_without_constraints",
+ no_constraints,
+ "aws",
+ {},
+ ),
+ (
+ "microk8s_without_constraints",
+ no_constraints,
+ "microk8s",
+ {},
+ ),
+ (
+ "empty_cloud_with_constraints",
+ constraints,
+ "",
+ {"cores": 1, "mem": 1024},
+ ),
+ ]
+ )
+ def test_get_application_constraints__get_expected_constraints(
+ self, _, constraints, cloud, expected_result
+ ):
+ result = JujuPaasConnector._get_application_constraints(constraints, cloud)
+ self.assertEqual(result, expected_result)
class TestTestVimConnectivity(TestJujuPaasActivitiesBase):
# See the License for the specific language governing permissions and
# limitations under the License.
-
-from unittest.mock import Mock
-
import asynctest
-from osm_common.dataclasses.temporal_dataclasses import GetVnfRecordIdsInput
+
+from osm_common.dataclasses.temporal_dataclasses import (
+ GetNsRecordInput,
+ GetVnfDetailsInput,
+)
from osm_common.dbbase import DbException
from temporalio.testing import ActivityEnvironment
-
from osm_lcm.temporal.ns_activities import NsOperations
+from unittest.mock import Mock
ns_uuid = "00000000-0000-0000-0000-000000000000"
-get_vnf_record_ids_input = GetVnfRecordIdsInput(ns_uuid=ns_uuid)
+get_vnf_details_input = GetVnfDetailsInput(ns_uuid=ns_uuid)
+sample_vnf_details = [
+ {
+ "id": "00000000-0000-0000-0000-000000000000",
+ "member-vnf-index-ref": "vnf1",
+ },
+ {
+ "id": "00000000-0000-0000-0000-000000000000",
+ "member-vnf-index-ref": "vnf2",
+ },
+]
+sample_nsr = {
+ "_id": ns_uuid,
+ "name": "sol006_juju24",
+ "name-ref": "sol006_juju24",
+ "short-name": "sol006_juju24",
+ "admin-status": "ENABLED",
+ "nsState": "NOT_INSTANTIATED",
+ "currentOperation": "IDLE",
+}
+
+
+class TestException(Exception):
+ pass
-class TestGetModelInfo(asynctest.TestCase):
+class TestGetVnfDetails(asynctest.TestCase):
def setUp(self):
self.db = Mock()
self.env = ActivityEnvironment()
self.ns_operations_activity = NsOperations(self.db)
- async def test_get_vnfr_ids(self):
- self.db.get_list.return_value = [
- {"id": "00000000-0000-0000-0000-000000000000"},
- {"id": "00000000-0000-0000-0000-000000000000"},
- ]
+ async def test_activity__succeded__get_expected_result(self):
+ self.db.get_list.return_value = sample_vnf_details
result = await self.env.run(
- self.ns_operations_activity.get_vnf_record_ids, get_vnf_record_ids_input
+ self.ns_operations_activity.get_vnf_details, get_vnf_details_input
)
- assert result.vnfr_ids == [
- "00000000-0000-0000-0000-000000000000",
- "00000000-0000-0000-0000-000000000000",
- ]
-
- self.db.get_list.assert_called_with("vnfrs", {"nsr-id-ref": ns_uuid})
+ self.assertEqual(
+ result.vnf_details,
+ [
+ ("00000000-0000-0000-0000-000000000000", "vnf1"),
+ ("00000000-0000-0000-0000-000000000000", "vnf2"),
+ ],
+ )
- async def test_activity_raises_db_exception(self):
- self.db.get_list.side_effect = DbException("not found")
+ async def test_activity__failed__raise_db_exception(self):
+ self.db.get_list.side_effect = DbException("not found.")
with self.assertRaises(DbException):
await self.env.run(
- self.ns_operations_activity.get_vnf_record_ids, get_vnf_record_ids_input
+ self.ns_operations_activity.get_vnf_details, get_vnf_details_input
+ )
+
+
+class TestGetNsRecord(asynctest.TestCase):
+ async def setUp(self):
+ self.db = Mock()
+ self.env = ActivityEnvironment()
+ self.ns_operations_activity = NsOperations(self.db)
+
+ async def test_activity__succeeded__get_expected_result(self):
+ self.db.get_one.return_value = sample_nsr
+ activity_result = await self.env.run(
+ self.ns_operations_activity.get_ns_record,
+ GetNsRecordInput(nsr_uuid=sample_nsr["_id"]),
+ )
+ self.assertEqual(activity_result.nsr, sample_nsr)
+
+ async def test_activity__failed__raise_test_exception(self):
+ self.db.get_one.side_effect = TestException("Can not connect to Database.")
+ with self.assertRaises(TestException):
+ await self.env.run(
+ self.ns_operations_activity.get_ns_record,
+ GetNsRecordInput(nsr_uuid=sample_nsr["_id"]),
)
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
-
-from unittest.mock import Mock
-
import asynctest
-from mock import AsyncMock, patch
+import copy
+from datetime import timedelta
+from unittest.mock import Mock, patch
+
from osm_common.dataclasses.temporal_dataclasses import (
- GetVnfRecordIdsInput,
- GetVnfRecordIdsOutput,
+ GetNsRecordInput,
+ GetNsRecordOutput,
+ GetVnfDetailsInput,
+ GetVnfDetailsOutput,
LcmOperationState,
ModelInfo,
NsLcmOperationInput,
)
from osm_common.temporal_constants import (
ACTIVITY_CREATE_MODEL,
- ACTIVITY_GET_VNF_RECORD_IDS,
+ ACTIVITY_GET_NS_RECORD,
+ ACTIVITY_GET_VNF_DETAILS,
ACTIVITY_UPDATE_LCM_OPERATION_STATE,
ACTIVITY_UPDATE_NS_STATE,
LCM_TASK_QUEUE,
WORKFLOW_VNF_INSTANTIATE,
)
+from osm_lcm.temporal.ns_workflows import NsInstantiateWorkflow
from temporalio import activity, workflow
from temporalio.client import WorkflowFailureError
+from temporalio.common import RetryPolicy
+from temporalio.exceptions import (
+ ActivityError,
+ ChildWorkflowError,
+ RetryState,
+ TimeoutError,
+)
from temporalio.testing import WorkflowEnvironment
from temporalio.worker import Worker
-from osm_lcm.temporal.ns_workflows import NsInstantiateWorkflow
-vnfr_ids = [
- "828d91ee-fa04-43bb-8471-f66ea74597e7",
- "c4bbeb41-df7e-4daa-863d-c8fd29fac96d",
+vnfr_uuid_1 = "828d91ee-fa04-43bb-8471-f66ea74597e7"
+vnfr_uuid_2 = "c4bbeb41-df7e-4daa-863d-c8fd29fac96d"
+vnf_member_index_ref_1 = "vnf-profile-id"
+vnf_member_index_ref_2 = "vnf-profile-id-2"
+vnf_details = [
+ (vnfr_uuid_1, vnf_member_index_ref_1),
+ (vnfr_uuid_2, vnf_member_index_ref_2),
]
+ns_uuid = "9c96e9c1-aae2-4c61-a85f-2ec8acb448fc"
+vim_uuid = "a64f7c6c-bc27-4ec8-b664-5500a3324eca"
+vdu_id = "test-vdu"
+model_name = "2ec8acb448fc-5500a3324eca"
+vnf_config = {
+ "member-vnf-index": vnf_member_index_ref_1,
+ "vdu": [
+ {
+ "id": vdu_id,
+ "configurable-properties": {
+ "config::redirect-map": "https://osm.instantiation.params"
+ },
+ }
+ ],
+}
+sample_nsr = {
+ "_id": ns_uuid,
+ "name": "sol006_juju23",
+ "name-ref": "sol006_juju23",
+ "short-name": "sol006_juju23",
+ "admin-status": "ENABLED",
+ "nsState": "NOT_INSTANTIATED",
+ "instantiate_params": {
+ "nsdId": ns_uuid,
+ "nsName": "sol006_juju23",
+ "nsDescription": "default description",
+ "vimAccountId": vim_uuid,
+ "vnf": [vnf_config],
+ },
+}
+mock_get_namespace = Mock()
+retry_policy = RetryPolicy(
+ initial_interval=timedelta(seconds=1),
+ backoff_coefficient=2.0,
+ maximum_interval=None,
+ maximum_attempts=1,
+ non_retryable_error_types=None,
+)
+SANDBOXED = False
+DEBUG_MODE = True
+TASK_TIMEOUT = timedelta(seconds=0.5)
+EXECUTION_TIMEOUT = timedelta(seconds=1)
class TestException(Exception):
pass
-@activity.defn(name=ACTIVITY_GET_VNF_RECORD_IDS)
-async def mock_get_vnf_record_ids(
- get_vnf_record_ids_input: GetVnfRecordIdsInput,
-) -> None:
- return GetVnfRecordIdsOutput(vnfr_ids=vnfr_ids)
-
-
@activity.defn(name=ACTIVITY_CREATE_MODEL)
async def mock_create_model_raises(create_model_input: ModelInfo) -> None:
- raise TestException("Test exception")
+ raise TestException(f"{ACTIVITY_CREATE_MODEL} failed.")
+
+
+@activity.defn(name=ACTIVITY_GET_VNF_DETAILS)
+async def mock_get_vnf_details(
+ get_vnf_details_input: GetVnfDetailsInput,
+) -> GetVnfDetailsOutput:
+ return GetVnfDetailsOutput(vnf_details=vnf_details)
-@workflow.defn(name=WORKFLOW_VNF_INSTANTIATE, sandboxed=False)
+@activity.defn(name=ACTIVITY_GET_VNF_DETAILS)
+async def mock_get_vnf_details_raises(
+ et_vnf_details_input: GetVnfDetailsInput,
+) -> GetVnfDetailsOutput:
+ raise TestException(f"{ACTIVITY_GET_VNF_DETAILS} failed.")
+
+
+@activity.defn(name=ACTIVITY_GET_NS_RECORD)
+async def mock_get_ns_record(
+ get_ns_record_input: GetNsRecordInput,
+) -> GetNsRecordOutput:
+ return GetNsRecordOutput(nsr=sample_nsr)
+
+
+@activity.defn(name=ACTIVITY_GET_NS_RECORD)
+async def mock_get_ns_record_raise_exception(
+ get_ns_record_input: GetNsRecordInput,
+) -> GetNsRecordOutput:
+ raise TestException(f"{ACTIVITY_GET_NS_RECORD} failed.")
+
+
+@workflow.defn(name=WORKFLOW_VNF_INSTANTIATE, sandboxed=SANDBOXED)
class MockVnfInstantiateWorkflow:
@workflow.run
async def run(self, input: VnfInstantiateInput) -> None:
pass
+@workflow.defn(name=WORKFLOW_VNF_INSTANTIATE, sandboxed=SANDBOXED)
+class MockVnfInstantiateWorkflowFailed:
+ @workflow.run
+ async def run(self, input: VnfInstantiateInput) -> None:
+ raise ChildWorkflowError(
+ message=f"{WORKFLOW_VNF_INSTANTIATE} child workflow failed.",
+ namespace="default",
+ workflow_id="123",
+ run_id="1",
+ workflow_type=WORKFLOW_VNF_INSTANTIATE,
+ initiated_event_id=0,
+ started_event_id=0,
+ retry_state=RetryState.NON_RETRYABLE_FAILURE,
+ )
+
+
+@patch(
+ "osm_lcm.temporal.ns_workflows.NsInstantiateWorkflow._get_namespace",
+ new=mock_get_namespace,
+)
class TestNsInstantiateWorkflow(asynctest.TestCase):
input = NsLcmOperationInput(
nslcmop={
"_id": "1234",
- "nsInstanceId": "5678",
- "operationParams": {"vimAccountId": "9876"},
+ "nsInstanceId": ns_uuid,
+ "operationParams": {"vimAccountId": vim_uuid},
}
)
async def setUp(self):
self.env = await WorkflowEnvironment.start_time_skipping()
+ self.client = self.env.client
self.mock_update_lcm_operation_state_tracker = Mock()
self.mock_update_ns_state_tracker = Mock()
+ self.workflows = [NsInstantiateWorkflow, MockVnfInstantiateWorkflow]
+ self.task_queue = LCM_TASK_QUEUE
+ mock_get_namespace.return_value = model_name
- @patch("temporalio.workflow.execute_child_workflow")
- async def test_instantiate_workflow(self, mock_execute_child_workflow: AsyncMock):
- async with self.env as env:
- async with Worker(
- env.client,
- task_queue=LCM_TASK_QUEUE,
- workflows=[NsInstantiateWorkflow, MockVnfInstantiateWorkflow],
- activities=[
- mock_create_model,
- mock_get_vnf_record_ids,
- self.mock_update_ns_state,
- self.mock_update_lcm_operation_state,
- ],
- debug_mode=True,
- ):
- await env.client.execute_workflow(
- NsInstantiateWorkflow,
- arg=self.input,
- id=self.input.nslcmop["nsInstanceId"],
- task_queue=LCM_TASK_QUEUE,
- )
+ def get_worker(self, task_queue: str, workflows: list, activities: list) -> Worker:
+ return Worker(
+ self.client,
+ task_queue=task_queue,
+ workflows=workflows,
+ activities=activities,
+ debug_mode=DEBUG_MODE,
+ )
- self.assertEqual(
- [
- call.kwargs["workflow"] == WORKFLOW_VNF_INSTANTIATE
- and call.kwargs["arg"].vnfr_uuid
- for call in mock_execute_child_workflow.call_args_list
- ],
- vnfr_ids,
+ async def execute_workflow(self):
+ return await self.client.execute_workflow(
+ NsInstantiateWorkflow,
+ arg=self.input,
+ id=self.input.nslcmop["nsInstanceId"],
+ task_queue=self.task_queue,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
+ async def test_instantiate_workflow__successful__update_lcm_op_state(self):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
self.assert_lcm_op_states(
self.mock_update_lcm_operation_state_tracker.call_args_list,
[LcmOperationState.PROCESSING, LcmOperationState.COMPLETED],
)
+ async def test_instantiate_workflow__successful__update_ns_state(self):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assert_ns_states(
+ self.mock_update_ns_state_tracker.call_args_list, [NsState.INSTANTIATED]
+ )
+
+ async def test_instantiate_workflow__activity_failed__update_ns_state(
+ self,
+ ):
+ activities = [
+ mock_create_model_raises,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
self.assert_ns_states(
self.mock_update_ns_state_tracker.call_args_list, [NsState.INSTANTIATED]
)
- async def test_instantiate_workflow_with_exception_updates_lcm_operation(self):
- async with self.env as env:
- async with Worker(
- env.client,
- task_queue=LCM_TASK_QUEUE,
- workflows=[NsInstantiateWorkflow, MockVnfInstantiateWorkflow],
- activities=[
- mock_create_model_raises,
- mock_get_vnf_record_ids,
- self.mock_update_ns_state,
- self.mock_update_lcm_operation_state,
- ],
- debug_mode=True,
+ async def test_instantiate_workflow__activity_failed__update_lcm_op_state(
+ self,
+ ):
+ activities = [
+ mock_create_model_raises,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assert_lcm_op_states(
+ self.mock_update_lcm_operation_state_tracker.call_args_list,
+ [LcmOperationState.PROCESSING, LcmOperationState.FAILED],
+ )
+
+ async def test_instantiate_workflow__create_model_activity_failed__raise_activity_error(
+ self,
+ ):
+ activities = [
+ mock_create_model_raises,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError) as err:
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
+
+ async def test_instantiate_workflow__create_model_activity_failed__error_details_expected(
+ self,
+ ):
+ activities = [
+ mock_create_model_raises,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assert_ns_error_details(
+ self.mock_update_ns_state_tracker.call_args_list,
+ ["TestException: create-model failed."],
+ )
+
+ async def test_instantiate_workflow__get_ns_record_activity_failed__error_details_expected(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record_raise_exception,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
):
- with self.assertRaises(WorkflowFailureError) as e_info:
- await env.client.execute_workflow(
- NsInstantiateWorkflow,
- arg=self.input,
- id=self.input.nslcmop["nsInstanceId"],
- task_queue=LCM_TASK_QUEUE,
- )
- self.assertEqual(e_info.exception.cause.cause.type, "TestException")
+ await self.execute_workflow()
+ self.assert_ns_error_details(
+ self.mock_update_ns_state_tracker.call_args_list,
+ ["TestException: get-ns-record failed."],
+ )
+ async def test_instantiate_workflow__get_ns_record_activity_failed__raise_activity_error(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record_raise_exception,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError) as err:
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
+
+ async def test_instantiate_workflow__get_vnf_details_activity_failed__error_details_expected(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details_raises,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assert_ns_error_details(
+ self.mock_update_ns_state_tracker.call_args_list,
+ ["TestException: get-vnf-details failed."],
+ )
+
+ async def test_instantiate_workflow__get_vnf_details_activity_failed__raise_activity_error(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details_raises,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError) as err:
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
+
+ @patch("osm_lcm.temporal.ns_workflows.NsInstantiateWorkflow.get_vnf_config")
+ async def test_instantiate_workflow__get_vnf_config_failed__workflow_times_out(
+ self, mock_get_vnf_config
+ ):
+ # Because of workflow task timeout policy, workflow times out
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ mock_get_vnf_config.side_effect = TestException("get_vnf_config failed.")
+ with self.assertRaises(WorkflowFailureError) as err:
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, TimeoutError))
+
+ @patch("osm_lcm.temporal.ns_workflows.NsInstantiateWorkflow.get_vnf_config")
+ async def test_instantiate_workflow__get_vnf_config_failed__update_ns_state(
+ self, mock_get_vnf_config
+ ):
+ # Workflow task failure
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ mock_get_vnf_config.side_effect = TestException("get_vnf_config failed.")
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
+ self.assert_ns_states(
+ self.mock_update_ns_state_tracker.call_args_list, [NsState.INSTANTIATED]
+ )
+
+ @patch("osm_lcm.temporal.ns_workflows.NsInstantiateWorkflow.get_vnf_config")
+ async def test_instantiate_workflow__get_vnf_config_failed__update_lcm_op_state(
+ self, mock_get_vnf_config
+ ):
+ # Workflow task failure
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ mock_get_vnf_config.side_effect = TestException("get_vnf_config failed.")
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ await self.execute_workflow()
self.assert_lcm_op_states(
self.mock_update_lcm_operation_state_tracker.call_args_list,
[LcmOperationState.PROCESSING, LcmOperationState.FAILED],
)
- async def test_instantiate_workflow_with_exception_updates_ns_state(self):
- async with self.env as env:
- async with Worker(
- env.client,
- task_queue=LCM_TASK_QUEUE,
- workflows=[NsInstantiateWorkflow, MockVnfInstantiateWorkflow],
- activities=[
- mock_create_model_raises,
- mock_get_vnf_record_ids,
- self.mock_update_ns_state,
- self.mock_update_lcm_operation_state,
- ],
- debug_mode=True,
+ async def test_instantiate_workflow__child_wf_failed__raise_child_workflow_error(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError) as err:
+ async with self.env, self.get_worker(
+ self.task_queue,
+ [NsInstantiateWorkflow, MockVnfInstantiateWorkflowFailed],
+ activities,
+ ):
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, ChildWorkflowError))
+
+ async def test_instantiate_workflow__child_wf_failed__error_details_expected(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue,
+ [NsInstantiateWorkflow, MockVnfInstantiateWorkflowFailed],
+ activities,
):
- with self.assertRaises(WorkflowFailureError) as e_info:
- await env.client.execute_workflow(
- NsInstantiateWorkflow,
- arg=self.input,
- id=self.input.nslcmop["nsInstanceId"],
- task_queue=LCM_TASK_QUEUE,
- )
- self.assertEqual(e_info.exception.cause.cause.type, "TestException")
+ await self.execute_workflow()
+ self.assert_ns_error_details(
+ self.mock_update_ns_state_tracker.call_args_list,
+ ["vnf-instantiate child workflow failed."],
+ )
+
+ async def test_instantiate_workflow__child_wf_failed__update_ns_state(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue,
+ [NsInstantiateWorkflow, MockVnfInstantiateWorkflowFailed],
+ activities,
+ ):
+ await self.execute_workflow()
self.assert_ns_states(
self.mock_update_ns_state_tracker.call_args_list, [NsState.INSTANTIATED]
)
+ async def test_instantiate_workflow__child_wf_failed__update_lcm_op_state(
+ self,
+ ):
+ activities = [
+ mock_create_model,
+ mock_get_vnf_details,
+ mock_get_ns_record,
+ self.mock_update_ns_state,
+ self.mock_update_lcm_operation_state,
+ ]
+
+ with self.assertRaises(WorkflowFailureError):
+ async with self.env, self.get_worker(
+ self.task_queue,
+ [NsInstantiateWorkflow, MockVnfInstantiateWorkflowFailed],
+ activities,
+ ):
+ await self.execute_workflow()
+ self.assert_lcm_op_states(
+ self.mock_update_lcm_operation_state_tracker.call_args_list,
+ [LcmOperationState.PROCESSING, LcmOperationState.FAILED],
+ )
+
def assert_ns_states(self, call_args_list, expected_states):
"""Asserts that the NS state was set to each of the expected states (in order)."""
self.assertEqual(
[call.args[0].state for call in call_args_list], expected_states
)
+ def assert_ns_error_details(self, call_args_list, expected_error):
+ """Asserts that the NS state was set to each of the expected states (in order)."""
+ self.assertEqual(
+ [call.args[0].message for call in call_args_list], expected_error
+ )
+
def assert_lcm_op_states(self, call_args_list, expected_states):
- """Asserts that the LCM operation was set to each of the exepcted states (in order)."""
+ """Asserts that the LCM operation was set to each of the expected states (in order)."""
self.assertEqual(
[call.args[0].op_state for call in call_args_list], expected_states
)
+
+
+class TestGetVnfConfig(asynctest.TestCase):
+ def test_vnf_config__nsr_config_matches_with_vnf__return_expected_config(self):
+ expected_config = {
+ "member-vnf-index": "vnf-profile-id",
+ "vdu": [
+ {
+ "configurable-properties": {
+ "config::redirect-map": "https://osm.instantiation.params"
+ },
+ "id": "test-vdu",
+ }
+ ],
+ }
+ result = NsInstantiateWorkflow.get_vnf_config(
+ vnf_member_index_ref_1, sample_nsr
+ )
+ self.assertEqual(result, expected_config)
+
+ def test_vnf_config__nsr_does_not_have_config__expected_no_config(self):
+ nsr = copy.deepcopy(sample_nsr)
+ nsr["instantiate_params"] = {}
+ result = NsInstantiateWorkflow.get_vnf_config(vnf_member_index_ref_1, nsr)
+ self.assertEqual(result, {})
+
+ def test_vnf_config__empty_vnf_member_index_ref__expected_no_config(self):
+ result = NsInstantiateWorkflow.get_vnf_config("", sample_nsr)
+ self.assertEqual(result, {})
+
+ def test_vnf_config__nsr_config_does_not_match_with_vnf__expected_no_config(self):
+ result = NsInstantiateWorkflow.get_vnf_config(
+ vnf_member_index_ref_2, sample_nsr
+ )
+ self.assertEqual(result, {})
# limitations under the License.
import asynctest
+from datetime import timedelta
from osm_common.dataclasses.temporal_dataclasses import (
CharmInfo,
from osm_lcm.temporal.vdu_workflows import CheckCharmStatusInput, VduInstantiateWorkflow
from temporalio import activity
from temporalio.client import WorkflowFailureError
+from temporalio.exceptions import (
+ ActivityError,
+)
from temporalio.testing import WorkflowEnvironment
from temporalio.worker import Worker
+TASK_TIMEOUT = timedelta(seconds=0.5)
+EXECUTION_TIMEOUT = timedelta(seconds=1)
+
+
+class TestException(Exception):
+ pass
+
@activity.defn(name=ACTIVITY_DEPLOY_CHARM)
async def deploy_charm_mocked(deploy_charm_input: VduInstantiateInput) -> None:
@activity.defn(name=ACTIVITY_DEPLOY_CHARM)
async def deploy_charm_mocked_raises(deploy_charm_input: VduInstantiateInput) -> None:
- raise Exception()
+ raise TestException(f"{ACTIVITY_DEPLOY_CHARM} failed.")
@activity.defn(name=ACTIVITY_CHECK_CHARM_STATUS)
async def check_charm_status_mocked_raises(
check_charm_status: CheckCharmStatusInput,
) -> None:
- raise Exception()
+ raise TestException(f"{ACTIVITY_CHECK_CHARM_STATUS} failed.")
class TestVduWorkflows(asynctest.TestCase):
channel = "latest"
entity_url = "ch:my-charm"
cloud = "microk8s"
- config = {}
+ config = {"domain_name1": "osm.org", "domain_name2": "osm.com"}
constraints = VduComputeConstraints(mem=1, cores=1)
charm_info = CharmInfo(app_name, channel, entity_url)
- vdu_instantiate_input = VduInstantiateInput(
+ vdu_instantiate_input_without_config = VduInstantiateInput(
+ vim_id, namespace, charm_info, constraints, cloud, {}
+ )
+ vdu_instantiate_input_with_config = VduInstantiateInput(
vim_id, namespace, charm_info, constraints, cloud, config
)
- worflow_id = namespace + "-" + app_name
+ workflow_id = namespace + "-" + app_name
async def setUp(self):
self.env = await WorkflowEnvironment.start_time_skipping()
debug_mode=True,
)
- async def test_vdu_instantiate(self):
+ async def test_vdu_instantiate__without_config__successful(self):
activities = [deploy_charm_mocked, check_charm_status_mocked]
async with self.env, self.get_worker(activities):
- result = await self.client.execute_workflow(
+ await self.client.execute_workflow(
VduInstantiateWorkflow.run,
- arg=self.vdu_instantiate_input,
- id=self.worflow_id,
+ arg=self.vdu_instantiate_input_without_config,
+ id=self.workflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
- self.assertIsNone(result)
- async def test_vdu_instantiate_deploy_raises(self):
+ async def test_vdu_instantiate__with_config__successful(self):
+ activities = [deploy_charm_mocked, check_charm_status_mocked]
+ async with self.env, self.get_worker(activities):
+ await self.client.execute_workflow(
+ VduInstantiateWorkflow.run,
+ arg=self.vdu_instantiate_input_with_config,
+ id=self.workflow_id,
+ task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
+ )
+
+ async def test_vdu_instantiate__deploy_charm_failed__raise_activity_error(self):
+ activities = [deploy_charm_mocked_raises, check_charm_status_mocked]
+ async with self.env, self.get_worker(activities):
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.client.execute_workflow(
+ VduInstantiateWorkflow.run,
+ arg=self.vdu_instantiate_input_without_config,
+ id=self.workflow_id,
+ task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
+ )
+ self.assertTrue(err.exception.cause, ActivityError)
+
+ async def test_vdu_instantiate__deploy_charm_failed__get_error_details(self):
activities = [deploy_charm_mocked_raises, check_charm_status_mocked]
async with self.env, self.get_worker(activities):
- with self.assertRaises(WorkflowFailureError):
- result = await self.client.execute_workflow(
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.client.execute_workflow(
VduInstantiateWorkflow.run,
- arg=self.vdu_instantiate_input,
- id=self.worflow_id,
+ arg=self.vdu_instantiate_input_without_config,
+ id=self.workflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
- self.assertIsNone(result)
+ self.assertEqual(
+ str(err.exception.cause.cause), "TestException: deploy-charm failed."
+ )
- async def test_vdu_instantiate_check_status_raises(self):
+ async def test_vdu_instantiate__check_status__raise_activity_error(self):
activities = [deploy_charm_mocked, check_charm_status_mocked_raises]
async with self.env, self.get_worker(activities):
- with self.assertRaises(WorkflowFailureError):
- result = await self.client.execute_workflow(
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.client.execute_workflow(
VduInstantiateWorkflow.run,
- arg=self.vdu_instantiate_input,
- id=self.worflow_id,
+ arg=self.vdu_instantiate_input_without_config,
+ id=self.workflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
- self.assertIsNone(result)
+ self.assertTrue(err.exception.cause, ActivityError)
+
+ async def test_vdu_instantiate__check_status__get_error_details(self):
+ activities = [deploy_charm_mocked, check_charm_status_mocked_raises]
+ async with self.env, self.get_worker(activities):
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.client.execute_workflow(
+ VduInstantiateWorkflow.run,
+ arg=self.vdu_instantiate_input_without_config,
+ id=self.workflow_id,
+ task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
+ )
+ self.assertEqual(
+ str(err.exception.cause.cause),
+ "TestException: check-charm-status failed.",
+ )
from unittest import TestCase
from unittest.mock import Mock, patch, MagicMock
-
from osm_common import msgbase
from osm_common.dbbase import DbException
from osm_lcm.vim_sdn import K8sClusterLcm, VcaLcm
# limitations under the License.
import asynctest
+from datetime import timedelta
+from unittest.mock import Mock
+
from osm_common.dataclasses.temporal_dataclasses import (
DeleteVimInput,
TestVimConnectivityInput,
from temporalio.client import WorkflowFailureError
from temporalio.testing import WorkflowEnvironment
from temporalio.worker import Worker
-from unittest.mock import Mock
+
+TASK_TIMEOUT = timedelta(seconds=0.5)
+EXECUTION_TIMEOUT = timedelta(seconds=1)
class TestException(Exception):
arg=self.vim_operation_input,
id=self.worflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
self.check_vim_state_is_updated(expected_vim_state)
self.check_vim_op_state_is_updated(expected_vim_op_state)
arg=self.vim_operation_input,
id=self.worflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
self.check_vim_state_is_updated(expected_vim_state)
self.check_vim_op_state_is_updated(expected_vim_op_state)
arg=self.vim_operation_input,
id=self.worflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
self.check_vim_state_is_updated(expected_vim_state)
self.check_vim_op_state_is_updated(expected_vim_op_state)
arg=self.vim_operation_input,
id=self.worflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
self.check_vim_state_is_updated(expected_vim_state)
self.check_vim_op_state_is_updated(expected_vim_op_state)
arg=self.vim_operation_input,
id=self.worflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
self.assertIsNone(result)
self.mock_delete_vim_record_tracker.assert_called_once()
arg=self.vim_operation_input,
id=self.worflow_id,
task_queue=self.task_queue_name,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
self.assertIsNone(result)
# See the License for the specific language governing permissions and
# limitations under the License.
-
import asynctest
-from asyncio.exceptions import CancelledError
from copy import deepcopy
+from unittest import TestCase
+from unittest.mock import Mock, patch
+
from osm_common.dataclasses.temporal_dataclasses import (
ChangeVnfInstantiationStateInput,
ChangeVnfStateInput,
GetTaskQueueInput,
GetVimCloudInput,
- GetVnfDetailsInput,
- VnfInstantiateInput,
+ GetVnfDescriptorInput,
+ GetVnfRecordInput,
+ SetVnfModelInput,
VnfInstantiationState,
VnfState,
+ VduComputeConstraints,
)
from osm_common.dbbase import DbException
from osm_common.temporal_constants import (
)
from osm_lcm.temporal.vnf_activities import VnfDbActivity, VnfOperations
from temporalio.testing import ActivityEnvironment
-from unittest.mock import Mock
-vnfr_uuid = "d08d2da5-2120-476c-8538-deaeb4e88b3e"
-model_name = "a-model-name"
-vnf_instantiate_input = VnfInstantiateInput(vnfr_uuid=vnfr_uuid, model_name=model_name)
+
+vnfr_uuid = "9f472177-95c0-4335-b357-5cdc17a79965"
+vnfd_uuid = "97784f19-d254-4252-946c-cf92d85443ca"
+vim_uuid = "a64f7c6c-bc27-4ec8-b664-5500a3324eca"
+model_name = "my-model-name"
+set_vnf_model_input = SetVnfModelInput(vnfr_uuid=vnfr_uuid, model_name=model_name)
cloud = "microk8s"
-sample_vnfr = {
- "_id": "9f472177-95c0-4335-b357-5cdc17a79965",
- "id": "9f472177-95c0-4335-b357-5cdc17a79965",
- "nsr-id-ref": "dcf4c922-5a73-41bf-a6ca-870c22d6336c",
- "vnfd-ref": "jar_vnfd_scalable",
- "vnfd-id": "f1b38eac-190c-485d-9a74-c6e169c929d8",
- "vim-account-id": "9b0bedc3-ea8e-42fd-acc9-dd03f4dee73c",
-}
-sample_vnfd = {
- "_id": "97784f19-d254-4252-946c-cf92d85443ca",
- "id": "sol006-vnf",
- "provider": "Canonical",
- "product-name": "test-vnf",
- "software-version": "1.0",
-}
+nsr_uuid = "583726d4-957d-47f5-8df5-199456f7afd0"
sample_vim_record = {
- "_id": "a64f7c6c-bc27-4ec8-b664-5500a3324eca",
+ "_id": vim_uuid,
"name": "juju",
"vim_type": "paas",
"vim_url": "192.168.1.100:17070",
"ca_cert_content": "-----BEGIN-----",
},
}
+vim_account_id = "9b0bedc3-ea8e-42fd-acc9-dd03f4dee73c"
+vdu_id = "hackfest_basic-VM"
+vnf_index = "vnf-profile-id"
+sample_vnfr = {
+ "_id": vnfr_uuid,
+ "id": vnfr_uuid,
+ "nsr-id-ref": "dcf4c922-5a73-41bf-a6ca-870c22d6336c",
+ "vnfd-ref": "jar_vnfd_scalable",
+ "vnfd-id": "f1b38eac-190c-485d-9a74-c6e169c929d8",
+ "vim-account-id": vim_account_id,
+ "namespace": model_name,
+ "member-vnf-index-ref": vnf_index,
+}
+vnf_config = {
+ "member-vnf-index": vnf_index,
+ "vdu": [
+ {
+ "id": vdu_id,
+ "configurable-properties": {
+ "config::redirect-map": "https://osm.instantiation.params"
+ },
+ }
+ ],
+}
+app_config = {"domain_name1": "osm.org", "domain_name2": "osm.com"}
+config = [
+ {"key": "config::domain_name1", "value": "osm.org"},
+ {"key": "config::domain_name2", "value": "osm.com"},
+ {"key": "track", "value": "latest"},
+ {"key": "channel", "value": "stable"},
+]
+vdu = {
+ "id": vdu_id,
+ "name": "hackfest_basic-VM",
+ "sw-image-desc": "ubuntu18.04",
+ "virtual-compute-desc": "hackfest_basic-VM-compute",
+ "virtual-storage-desc": ["hackfest_basic-VM-storage"],
+ "configurable-properties": config,
+}
+vnfd_id = "97784f19-d254-4252-946c-cf92d85443ca"
+flavor_1 = {
+ "id": "compute-id-1",
+ "virtual-memory": {"size": "4"},
+ "virtual-cpu": {"cpu-architecture": "x86", "num-virtual-cpu": 2},
+}
+flavor_2 = {
+ "id": "compute-id-2",
+ "virtual-cpu": {"cpu-architecture": "x86", "num-virtual-cpu": 2},
+}
+flavor_3 = {
+ "id": "compute-id-2",
+ "virtual-memory": {"size": "4"},
+}
+sample_vnfd = {
+ "_id": vnfd_id,
+ "id": "sol006-vnf",
+ "provider": "Canonical",
+ "product-name": "test-vnf",
+ "software-version": "1.0",
+ "vdu": [vdu],
+ "virtual-compute-desc": [flavor_1, flavor_2],
+}
+
+
+class TestException(Exception):
+ pass
class TestVnfDbActivity(asynctest.TestCase):
self.env = ActivityEnvironment()
self.vnf_db_activity = VnfDbActivity(self.db)
- async def test_change_vnf_state_nominal_case(self):
+ async def test_change_vnf_state__successful__db_updated_as_expected(self):
vnf_state = VnfState.STOPPED
change_vnf_state_input = ChangeVnfStateInput(vnfr_uuid, vnf_state)
await self.env.run(
"vnfrs", {"_id": vnfr_uuid}, {"vnfState": vnf_state.name}
)
- async def test_change_vnf_state_db_raises_exception(self):
+ async def test_change_vnf_state__failed__raises_db_exception(self):
change_vnf_state_input = ChangeVnfStateInput(vnfr_uuid, VnfState.STARTED)
self.db.set_one.side_effect = DbException("not found")
with self.assertRaises(DbException):
self.vnf_db_activity.change_vnf_state, change_vnf_state_input
)
- async def test_change_vnf_instantiation_state_nominal_case(self):
+ async def test_change_vnf_instantiation_state__successful__db_updated_as_expected(
+ self,
+ ):
instantiation_state = VnfInstantiationState.NOT_INSTANTIATED
change_instantiation_input = ChangeVnfInstantiationStateInput(
vnfr_uuid, instantiation_state
{"instantiationState": instantiation_state.name},
)
- async def test_change_vnf_instantiation_state_db_raises_exception(self):
+ async def test_change_vnf_instantiation_state__failed__raises_db_exception(self):
change_instantiation_input = ChangeVnfInstantiationStateInput(
vnfr_uuid, VnfInstantiationState.INSTANTIATED
)
self.db.set_one.side_effect = DbException("not found")
with self.assertRaises(DbException):
await self.env.run(
- self.vnf_db_activity.change_vnf_state, change_instantiation_input
+ self.vnf_db_activity.change_vnf_instantiation_state,
+ change_instantiation_input,
)
- async def test_set_vnf_model_nominal_case(self):
- await self.env.run(self.vnf_db_activity.set_vnf_model, vnf_instantiate_input)
+ async def test_set_vnf_model__successful__db_updated_as_expected(self):
+ await self.env.run(self.vnf_db_activity.set_vnf_model, set_vnf_model_input)
self.db.set_one.assert_called_with(
"vnfrs", {"_id": vnfr_uuid}, {"namespace": model_name}
)
- async def test_set_vnf_model_db_raises_exception(self):
+ async def test_set_vnf_model__failed__raises_db_exception(self):
self.db.set_one.side_effect = DbException("not found")
with self.assertRaises(DbException):
- await self.env.run(
- self.vnf_db_activity.set_vnf_model, vnf_instantiate_input
- )
+ await self.env.run(self.vnf_db_activity.set_vnf_model, set_vnf_model_input)
class TestGetTaskQueue(asynctest.TestCase):
self.env = ActivityEnvironment()
self.get_task_queue_input = GetTaskQueueInput(vnfr_uuid=sample_vnfr["id"])
- async def test_activity_succeeded(self):
+ async def test_activity__succeeded__get_expected_task_queue(self):
self.db.get_one.side_effect = [sample_vnfr, sample_vim_record]
activity_result = await self.env.run(
self.vnf_operations_instance.get_task_queue,
)
self.assertEqual(activity_result.task_queue, LCM_TASK_QUEUE)
- async def test_db_raises_exception(self):
+ async def test_activity__failed__raises_db_exception(self):
self.db.get_one.side_effect = DbException("not found")
with self.assertRaises(DbException):
await self.env.run(
self.get_task_queue_input,
)
- async def test_invalid_task_queue(self):
+ async def test_activity__invalid_task_queue__raises_key_error(self):
vim_record = deepcopy(sample_vim_record)
vim_record["vim_type"] = "some-vim-type"
self.db.get_one.side_effect = [sample_vnfr, vim_record]
self.get_task_queue_input,
)
- async def test_activity_cancelled(self):
- self.env._cancelled = True
- self.db.get_one.side_effect = [sample_vnfr, sample_vim_record]
- with self.assertRaises(CancelledError):
- activity_result = await self.env.run(
- self.vnf_operations_instance.get_task_queue,
- self.get_task_queue_input,
- )
- self.assertEqual(activity_result, None)
-
-class TestVnfDetails(asynctest.TestCase):
+class TestGetVnfDescriptor(asynctest.TestCase):
async def setUp(self):
self.db = Mock()
self.vnf_operations_instance = VnfOperations(self.db)
self.env = ActivityEnvironment()
- async def test_activity_succeeded(self):
- self.db.get_one.side_effect = [sample_vnfr, sample_vnfd]
+ async def test_activity__succeeded__get_expected_vnfd(self):
+ self.db.get_one.return_value = sample_vnfd
activity_result = await self.env.run(
- self.vnf_operations_instance.get_vnf_details,
- GetVnfDetailsInput(vnfr_uuid=sample_vnfr["id"]),
+ self.vnf_operations_instance.get_vnf_descriptor,
+ GetVnfDescriptorInput(vnfd_uuid=vnfd_uuid),
)
self.assertEqual(activity_result.vnfd, sample_vnfd)
- self.assertEqual(activity_result.vnfr, sample_vnfr)
- async def test_activity_failed_db_exception(self):
+ async def test_activity__failed__raises_db_exception(self):
self.db.get_one.side_effect = DbException("Can not connect to Database.")
- with self.assertRaises(DbException) as err:
- activity_result = await self.env.run(
- self.vnf_operations_instance.get_vnf_details,
- GetVnfDetailsInput(vnfr_uuid=sample_vnfr["id"]),
+ with self.assertRaises(DbException):
+ await self.env.run(
+ self.vnf_operations_instance.get_vnf_descriptor,
+ GetVnfDescriptorInput(vnfd_uuid=vnfd_uuid),
)
- self.assertEqual(activity_result, None)
- self.assertEqual(
- str(err.exception), "database exception Can not connect to Database."
+
+
+class TestGetVnfRecord(asynctest.TestCase):
+ async def setUp(self):
+ self.db = Mock()
+ self.vnf_operations_instance = VnfOperations(self.db)
+ self.env = ActivityEnvironment()
+
+ async def test_activity__succeeded__get_expected_vnfr(self):
+ self.db.get_one.return_value = sample_vnfr
+ activity_result = await self.env.run(
+ self.vnf_operations_instance.get_vnf_record,
+ GetVnfRecordInput(vnfr_uuid=vnfr_uuid),
)
+ self.assertEqual(activity_result.vnfr, sample_vnfr)
- async def test_activity_failed_key_error(self):
- vnfr = deepcopy(sample_vnfr)
- vnfr.pop("vnfd-id")
- self.db.get_one.side_effect = [vnfr, sample_vnfd]
- with self.assertRaises(KeyError) as err:
- activity_result = await self.env.run(
- self.vnf_operations_instance.get_vnf_details,
- GetVnfDetailsInput(vnfr_uuid=sample_vnfr["id"]),
- )
- self.assertEqual(activity_result, None)
- self.assertEqual(str(err.exception.args[0]), "vnfd-id")
-
- async def test_activity_cancelled(self):
- self.env._cancelled = True
- self.db.get_one.side_effect = [sample_vnfr, sample_vnfd]
- with self.assertRaises(CancelledError):
- activity_result = await self.env.run(
- self.vnf_operations_instance.get_vnf_details,
- GetVnfDetailsInput(vnfr_uuid=sample_vnfr["id"]),
+ async def test_activity__failed__raise_db_exception(self):
+ self.db.get_one.side_effect = DbException("Can not connect to Database.")
+ with self.assertRaises(DbException):
+ await self.env.run(
+ self.vnf_operations_instance.get_vnf_record,
+ GetVnfRecordInput(vnfr_uuid=vnfr_uuid),
)
- self.assertEqual(activity_result, None)
class TestGetVimCloud(asynctest.TestCase):
self.vnf_operations_instance = VnfOperations(self.db)
self.env = ActivityEnvironment()
- async def test_activity_succeeded(self):
+ async def test_activity__succeeded__get_vim_cloud(self):
self.db.get_one.side_effect = [sample_vnfr, sample_vim_record]
activity_result = await self.env.run(
self.vnf_operations_instance.get_vim_cloud,
)
self.assertEqual(activity_result.cloud, cloud)
- async def test_activity_vim_record_without_cloud(self):
+ async def test_activity__vim_record_without_cloud__no_cloud_info(self):
vim_record = deepcopy(sample_vim_record)
vim_record["config"].pop("cloud")
self.db.get_one.side_effect = [sample_vnfr, vim_record]
)
self.assertEqual(activity_result.cloud, "")
- async def test_activity_failed_db_exception(self):
+ async def test_activity__failed__raise_db_exception(self):
self.db.get_one.side_effect = DbException("Can not connect to Database.")
- with self.assertRaises(DbException) as err:
- activity_result = await self.env.run(
+ with self.assertRaises(DbException):
+ await self.env.run(
self.vnf_operations_instance.get_vim_cloud,
GetVimCloudInput(vnfr_uuid=sample_vnfr["id"]),
)
- self.assertEqual(activity_result, None)
- self.assertEqual(
- str(err.exception), "database exception Can not connect to Database."
- )
- async def test_activity_failed_key_error(self):
+ async def test_activity__wrong_vim_record__raise_key_error(self):
vim_record = deepcopy(sample_vim_record)
vim_record.pop("config")
self.db.get_one.side_effect = [sample_vnfr, vim_record]
- with self.assertRaises(KeyError) as err:
- activity_result = await self.env.run(
+ with self.assertRaises(KeyError):
+ await self.env.run(
self.vnf_operations_instance.get_vim_cloud,
GetVimCloudInput(vnfr_uuid=sample_vnfr["id"]),
)
- self.assertEqual(activity_result, None)
- self.assertEqual(str(err.exception.args[0]), "config")
- async def test_activity_cancelled(self):
- self.env._cancelled = True
- self.db.get_one.side_effect = [sample_vnfr, sample_vim_record]
- with self.assertRaises(CancelledError):
- activity_result = await self.env.run(
- self.vnf_operations_instance.get_vim_cloud,
- GetVimCloudInput(vnfr_uuid=sample_vnfr["id"]),
- )
- self.assertEqual(activity_result, None)
+
+class TestGetVduInstantiateInfoMethods(TestCase):
+ def test_get_flavor_details__successful__get_flavor(self):
+ compute_desc_id = "compute-id-1"
+ result = VnfOperations._get_flavor_details(compute_desc_id, sample_vnfd)
+ self.assertEqual(result, flavor_1)
+
+ def test_get_flavor_details__empty_compute_desc__flavor_is_none(self):
+ compute_desc_id = ""
+ result = VnfOperations._get_flavor_details(compute_desc_id, sample_vnfd)
+ self.assertEqual(result, None)
+
+ def test_get_flavor_details__compute_desc_not_found__flavor_is_none(self):
+ compute_desc_id = "compute-id-5"
+ result = VnfOperations._get_flavor_details(compute_desc_id, sample_vnfd)
+ self.assertEqual(result, None)
+
+ def test_get_flavor_details__empty_vnfd__flavor_is_none(self):
+ compute_desc_id = "compute-id-5"
+ result = VnfOperations._get_flavor_details(compute_desc_id, {})
+ self.assertEqual(result, None)
+
+ def test_get_flavor_details__wrong_vnfd_format__flavor_is_none(self):
+ compute_desc_id = "compute-id-2"
+ sample_vnfd = {
+ "_id": vnfd_id,
+ "vdu": [vdu],
+ "virtual-compute-desc": [
+ {
+ "virtual-memory": {"size": "4"},
+ }
+ ],
+ }
+ result = VnfOperations._get_flavor_details(compute_desc_id, sample_vnfd)
+ self.assertEqual(result, None)
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_flavor_details")
+ def test_get_compute_constraints__succeeded__get_constraints(
+ self, mock_get_flavor_details
+ ):
+ mock_get_flavor_details.return_value = flavor_1
+ result = VnfOperations.get_compute_constraints(vdu, sample_vnfd)
+ self.assertEqual(VduComputeConstraints(cores=2, mem=4), result)
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_flavor_details")
+ def test_get_compute_constraints__empty_flavor_details__no_constraints(
+ self, mock_get_flavor_details
+ ):
+ mock_get_flavor_details.return_value = {}
+ result = VnfOperations.get_compute_constraints(vdu, sample_vnfd)
+ self.assertEqual(VduComputeConstraints(cores=0, mem=0), result)
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_flavor_details")
+ def test_get_compute_constraints__flavor_details_is_none__no_constraints(
+ self, mock_get_flavor_details
+ ):
+ mock_get_flavor_details.return_value = None
+ result = VnfOperations.get_compute_constraints(vdu, sample_vnfd)
+ self.assertEqual(VduComputeConstraints(cores=0, mem=0), result)
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_flavor_details")
+ def test_get_compute_constraints__flavor_has_only_cpu__get_cpu_constraint(
+ self, mock_get_flavor_details
+ ):
+ mock_get_flavor_details.return_value = flavor_2
+ result = VnfOperations.get_compute_constraints(vdu, sample_vnfd)
+ self.assertEqual(VduComputeConstraints(cores=2, mem=0), result)
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_flavor_details")
+ def test_get_compute_constraints__flavor_has_only_memory__get_memory_constraint(
+ self, mock_get_flavor_details
+ ):
+ mock_get_flavor_details.return_value = flavor_3
+ result = VnfOperations.get_compute_constraints(vdu, sample_vnfd)
+ self.assertEqual(VduComputeConstraints(cores=0, mem=4), result)
+
+ def test_list_to_dict__config_has_several_items__get_expected_dict(self):
+ config = [
+ {"key": "config::domain_name1", "value": "osm.org"},
+ {"key": "domain_name2", "value": "osm.com"},
+ ]
+ result = VnfOperations._list_to_dict(config)
+ self.assertEqual(
+ result, {"config::domain_name1": "osm.org", "domain_name2": "osm.com"}
+ )
+
+ def test_list_to_dict__empty_input__get_empty_dict(self):
+ config = []
+ result = VnfOperations._list_to_dict(config)
+ self.assertEqual(result, {})
+
+ def test_get_only_config_items__with_identifier__get_expected_config(self):
+ config = {"config::redirect-map": "https://osm.instantiation.params"}
+ result = VnfOperations._get_only_config_items(config)
+ self.assertEqual(result, {"redirect-map": "https://osm.instantiation.params"})
+
+ def test_get_only_config_items__without_identifier__no_config(self):
+ config = {"key": "domain_name1", "value": "osm.org"}
+ result = VnfOperations._get_only_config_items(config)
+ self.assertEqual(result, {})
+
+ def test_get_only_config_items__empty_input__no_config(self):
+ config = {}
+ result = VnfOperations._get_only_config_items(config)
+ self.assertEqual(result, {})
+
+ def test_get_vdu_instantiation_params__empty_vnf_config__get_params(self):
+ result = VnfOperations.get_vdu_instantiation_params(vdu_id, vnf_config)
+ self.assertEqual(
+ result, {"config::redirect-map": "https://osm.instantiation.params"}
+ )
+
+ def test_get_vdu_instantiation_params__empty_vnf_config__no_params(self):
+ result = VnfOperations.get_vdu_instantiation_params(vdu_id, {})
+ self.assertEqual(result, {})
+
+ def test_get_vdu_instantiation_params__vdu_id_mismatch__no_params(self):
+ config = deepcopy(vnf_config)
+ config["vdu"][0]["id"] = "other-vdu-id"
+ result = VnfOperations.get_vdu_instantiation_params(vdu_id, config)
+ self.assertEqual(result, {})
+
+ def test_get_vdu_instantiation_params__empty_configurable_properties__no_params(
+ self,
+ ):
+ config = deepcopy(vnf_config)
+ config["vdu"][0]["configurable-properties"] = {}
+ result = VnfOperations.get_vdu_instantiation_params(vdu_id, config)
+ self.assertEqual(result, {})
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_only_config_items")
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._list_to_dict")
+ def test_get_application_config__instantiate_config_overrides_vdu_config__get_expected_application_config(
+ self,
+ mock_list_to_dict,
+ mock_get_only_config_items,
+ ):
+ vdu_instantiate_config = {"config::domain_name1": "osm.public"}
+ mock_get_only_config_items.side_effect = [
+ {
+ "domain_name1": "osm.org",
+ "domain_name2": "osm.com",
+ },
+ {"domain_name1": "osm.public"},
+ ]
+ result = VnfOperations.get_application_config(vdu, vdu_instantiate_config)
+ self.assertEqual(
+ result, {"domain_name1": "osm.public", "domain_name2": "osm.com"}
+ )
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_only_config_items")
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._list_to_dict")
+ def test_get_application_config__empty_instantiate_config__get_descriptor_config(
+ self,
+ mock_list_to_dict,
+ mock_get_only_config_items,
+ ):
+ vdu_instantiate_config = {}
+ mock_get_only_config_items.side_effect = [
+ {
+ "domain_name1": "osm.org",
+ "domain_name2": "osm.com",
+ },
+ {},
+ ]
+ result = VnfOperations.get_application_config(vdu, vdu_instantiate_config)
+ self.assertEqual(result, app_config)
+
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._get_only_config_items")
+ @patch("osm_lcm.temporal.vnf_activities.VnfOperations._list_to_dict")
+ def test_get_application_config__no_config__empty_application_config(
+ self,
+ mock_list_to_dict,
+ mock_get_only_config_items,
+ ):
+ vdu_instantiate_config = {}
+ vdu_copy = deepcopy(vdu)
+ vdu_copy["configurable-properties"] = []
+ mock_get_only_config_items.side_effect = [{}, {}]
+ result = VnfOperations.get_application_config(vdu_copy, vdu_instantiate_config)
+ self.assertEqual(result, {})
if __name__ == "__main__":
# limitations under the License.
import asynctest
+from asynctest.mock import patch
from copy import deepcopy
-from temporalio import activity
-from temporalio import workflow
-from temporalio.client import WorkflowFailureError
-from temporalio.testing import WorkflowEnvironment
-from temporalio.worker import Worker
-from unittest import TestCase
-from unittest.mock import Mock, patch, AsyncMock
+from datetime import timedelta
+from unittest.mock import Mock
+import uuid
from osm_common.dataclasses.temporal_dataclasses import (
ChangeVnfInstantiationStateInput,
GetTaskQueueOutput,
GetVimCloudInput,
GetVimCloudOutput,
- GetVnfDetailsInput,
- GetVnfDetailsOutput,
+ GetVnfDescriptorInput,
+ GetVnfDescriptorOutput,
+ GetVnfRecordInput,
+ GetVnfRecordOutput,
+ SetVnfModelInput,
VduComputeConstraints,
VduInstantiateInput,
VnfInstantiateInput,
VnfInstantiationState,
+ VnfPrepareInput,
VnfState,
)
from osm_common.temporal_constants import (
ACTIVITY_CHANGE_VNF_INSTANTIATION_STATE,
ACTIVITY_GET_TASK_QUEUE,
ACTIVITY_GET_VIM_CLOUD,
- ACTIVITY_GET_VNF_DETAILS,
+ ACTIVITY_GET_VNF_DESCRIPTOR,
+ ACTIVITY_GET_VNF_RECORD,
ACTIVITY_SEND_NOTIFICATION_FOR_VNF,
ACTIVITY_SET_VNF_MODEL,
LCM_TASK_QUEUE,
WORKFLOW_VDU_INSTANTIATE,
WORKFLOW_VNF_PREPARE,
)
-
from osm_lcm.temporal.vnf_workflows import VnfInstantiateWorkflow, VnfPrepareWorkflow
+from temporalio import activity
+from temporalio import workflow
+from temporalio.client import WorkflowFailureError
+from temporalio.exceptions import (
+ ActivityError,
+ ChildWorkflowError,
+ RetryState,
+)
+from temporalio.testing import WorkflowEnvironment
+from temporalio.worker import Worker
+
# The variables used in the tests
model_name = "my-model-name"
-wf_input = VnfInstantiateInput(
- vnfr_uuid="86b53d92-4f5a-402e-8ac2-585ec6b64698",
- model_name=model_name,
-)
cloud = "microk8s"
-config = {}
juju_task_queue = "juju_task_queue"
vnfr_uuid = "9f472177-95c0-4335-b357-5cdc17a79965"
vim_account_id = "9b0bedc3-ea8e-42fd-acc9-dd03f4dee73c"
+vdu_id = "hackfest_basic-VM"
+vnf_index = "vnf-profile-id"
sample_vnfr = {
"_id": vnfr_uuid,
"id": vnfr_uuid,
"vnfd-id": "f1b38eac-190c-485d-9a74-c6e169c929d8",
"vim-account-id": vim_account_id,
"namespace": model_name,
+ "member-vnf-index-ref": vnf_index,
+}
+vnf_config = {
+ "member-vnf-index": vnf_index,
+ "vdu": [
+ {
+ "id": vdu_id,
+ "configurable-properties": {
+ "config::redirect-map": "https://osm.instantiation.params"
+ },
+ }
+ ],
}
+app_config = {"domain_name1": "osm.org", "domain_name2": "osm.com"}
+config = [
+ {"key": "config::domain_name1", "value": "osm.org"},
+ {"key": "config::domain_name2", "value": "osm.com"},
+ {"key": "track", "value": "latest"},
+ {"key": "channel", "value": "stable"},
+]
+wf_input = VnfInstantiateInput(
+ vnfr_uuid=vnfr_uuid,
+ model_name=model_name,
+ instantiation_config={},
+)
vdu = {
- "id": "hackfest_basic-VM",
+ "id": vdu_id,
"name": "hackfest_basic-VM",
- "sw-image-desc": "ubuntu18.04",
+ "sw-image-desc": "ubuntu20.04",
"virtual-compute-desc": "hackfest_basic-VM-compute",
"virtual-storage-desc": ["hackfest_basic-VM-storage"],
+ "configurable-properties": config,
}
vnfd_id = "97784f19-d254-4252-946c-cf92d85443ca"
flavor_1 = {
"id": "compute-id-2",
"virtual-cpu": {"cpu-architecture": "x86", "num-virtual-cpu": 2},
}
-flavor_3 = {
- "id": "compute-id-2",
- "virtual-memory": {"size": "4"},
-}
sample_vnfd = {
"_id": vnfd_id,
"id": "sol006-vnf",
"software-version": "1.0",
"vdu": [vdu],
"virtual-compute-desc": [flavor_1, flavor_2],
+ "sw-image-desc": [
+ {
+ "id": "ubuntu20.04",
+ "image": "ubuntu20.04",
+ "name": "ubuntu20.04",
+ "version": "1.0",
+ }
+ ],
}
sample_charm_info = CharmInfo(app_name="my-app", channel="latest", entity_url="my-url")
sample_constraints = VduComputeConstraints(cores=1, mem=1)
charm_info=sample_charm_info,
constraints=sample_constraints,
cloud=cloud,
- config=config,
+ config={},
)
+sample_vdu_instantiate_wf_id_1 = "vdu-instantiate-workflow-id-1"
+sample_vdu_instantiate_input_with_config = VduInstantiateInput(
+ vim_uuid=vim_account_id,
+ model_name=model_name,
+ charm_info=sample_charm_info,
+ constraints=sample_constraints,
+ cloud=cloud,
+ config=app_config,
+)
+
SANDBOXED = False
DEBUG_MODE = True
+TASK_TIMEOUT = timedelta(seconds=0.5)
+EXECUTION_TIMEOUT = timedelta(seconds=1)
class TestException(Exception):
pass
+class GetApplicationConfigException(Exception):
+ pass
+
+
+class GetVduInstantiationParamsException(Exception):
+ pass
+
+
+class GetCharmInfoException(Exception):
+ pass
+
+
+class GetComputeConstraintsException(Exception):
+ pass
+
+
# Mock Activities
@activity.defn(name=ACTIVITY_SET_VNF_MODEL)
-async def mock_set_vnf_model(set_vnf_model_input: VnfInstantiateInput) -> None:
+async def mock_set_vnf_model(set_vnf_model_input: SetVnfModelInput) -> None:
pass
@activity.defn(name=ACTIVITY_SET_VNF_MODEL)
async def mock_set_vnf_model_raise_exception(
- set_vnf_model_input: VnfInstantiateInput,
+ set_vnf_model_input: SetVnfModelInput,
) -> None:
raise TestException(f"{ACTIVITY_SET_VNF_MODEL} failed.")
raise TestException(f"{ACTIVITY_GET_TASK_QUEUE} failed.")
-@activity.defn(name=ACTIVITY_GET_VNF_DETAILS)
-async def mock_get_vnf_details(
- get_vnf_details_input: GetVnfDetailsInput,
-) -> GetVnfDetailsOutput:
- return GetVnfDetailsOutput(vnfr=sample_vnfr, vnfd=sample_vnfd)
+@activity.defn(name=ACTIVITY_GET_VNF_DESCRIPTOR)
+async def mock_get_vnf_descriptor(
+ get_vnf_descriptor_input: GetVnfDescriptorInput,
+) -> GetVnfDescriptorOutput:
+ return GetVnfDescriptorOutput(vnfd=sample_vnfd)
-@activity.defn(name=ACTIVITY_GET_VNF_DETAILS)
-async def mock_get_vnf_details_empty_output(
- get_vnf_details_input: GetVnfDetailsInput,
-) -> GetVnfDetailsOutput:
- return GetVnfDetailsOutput(vnfr={}, vnfd={})
+@activity.defn(name=ACTIVITY_GET_VNF_DESCRIPTOR)
+async def mock_get_vnf_descriptor_empty_output(
+ get_vnf_descriptor_input: GetVnfDescriptorInput,
+) -> GetVnfDescriptorOutput:
+ return GetVnfDescriptorOutput(vnfd={})
-@activity.defn(name=ACTIVITY_GET_VNF_DETAILS)
-async def mock_get_vnf_details_raise_exception(
- get_vnf_details_input: GetVnfDetailsInput,
-) -> GetVnfDetailsOutput:
- raise TestException(f"{ACTIVITY_GET_VNF_DETAILS} failed.")
+@activity.defn(name=ACTIVITY_GET_VNF_DESCRIPTOR)
+async def mock_get_vnf_descriptor_raise_exception(
+ get_vnf_descriptor_input: GetVnfDescriptorInput,
+) -> GetVnfDescriptorOutput:
+ raise TestException(f"{ACTIVITY_GET_VNF_DESCRIPTOR} failed.")
+
+
+@activity.defn(name=ACTIVITY_GET_VNF_RECORD)
+async def mock_get_vnf_record(
+ get_vnf_record_input: GetVnfRecordInput,
+) -> GetVnfRecordOutput:
+ return GetVnfRecordOutput(vnfr=sample_vnfr)
+
+
+@activity.defn(name=ACTIVITY_GET_VNF_RECORD)
+async def mock_get_vnf_record_raise_exception(
+ get_vnf_record_input: GetVnfRecordInput,
+) -> GetVnfRecordOutput:
+ raise TestException(f"{ACTIVITY_GET_VNF_RECORD} failed.")
@activity.defn(name=ACTIVITY_GET_VIM_CLOUD)
raise TestException(f"{ACTIVITY_GET_VIM_CLOUD} failed.")
-# Mock Workflowa
+# Mock Workflows
@workflow.defn(name=WORKFLOW_VNF_PREPARE, sandboxed=SANDBOXED)
class MockPrepareVnfWorkflow:
@workflow.run
- async def run(self, input: VnfInstantiateInput) -> None:
+ async def run(self, input: VnfPrepareInput) -> None:
pass
+@workflow.defn(name=WORKFLOW_VNF_PREPARE, sandboxed=SANDBOXED)
+class MockPrepareVnfWorkflowFailed:
+ @workflow.run
+ async def run(self, input: VnfPrepareInput) -> None:
+ raise ChildWorkflowError(
+ message=f"{WORKFLOW_VNF_PREPARE} child workflow failed.",
+ namespace="default",
+ workflow_id="123",
+ run_id="1",
+ workflow_type=WORKFLOW_VNF_PREPARE,
+ initiated_event_id=0,
+ started_event_id=0,
+ retry_state=RetryState.NON_RETRYABLE_FAILURE,
+ )
+
+
@workflow.defn(name=WORKFLOW_VDU_INSTANTIATE, sandboxed=SANDBOXED)
class MockVduInstantiateWorkflow:
@workflow.run
pass
+@workflow.defn(name=WORKFLOW_VDU_INSTANTIATE, sandboxed=SANDBOXED)
+class MockVduInstantiateWorkflowFailed:
+ @workflow.run
+ async def run(self, input: VduInstantiateInput) -> None:
+ raise ChildWorkflowError(
+ message=f"{WORKFLOW_VDU_INSTANTIATE} child workflow failed.",
+ namespace="default",
+ workflow_id="123",
+ run_id="1",
+ workflow_type=WORKFLOW_VDU_INSTANTIATE,
+ initiated_event_id=0,
+ started_event_id=0,
+ retry_state=RetryState.NON_RETRYABLE_FAILURE,
+ )
+
+
class TestVnfPrepareWorkflow(asynctest.TestCase):
async def setUp(self):
self.env = await WorkflowEnvironment.start_time_skipping()
self.client = self.env.client
self.task_queue = LCM_TASK_QUEUE
- async def test_vnf_prepare_workflow_successful(self):
+ async def test_vnf_prepare_workflow__successful(self):
async with self.env:
async with Worker(
self.client,
arg=wf_input,
id=f"{WORKFLOW_VNF_PREPARE}-{wf_input.vnfr_uuid}",
task_queue=self.task_queue,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
- async def test_vnf_prepare_workflow_fails(self):
+ async def test_vnf_prepare_workflow__activity_set_vnf_model_fails__raise_activity_error(
+ self,
+ ):
+ async with self.env:
+ async with Worker(
+ self.client,
+ debug_mode=DEBUG_MODE,
+ task_queue=self.task_queue,
+ workflows=[VnfPrepareWorkflow],
+ activities=[mock_set_vnf_model_raise_exception],
+ ):
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.client.execute_workflow(
+ VnfPrepareWorkflow.run,
+ arg=wf_input,
+ id=f"{WORKFLOW_VNF_PREPARE}-{wf_input.vnfr_uuid}",
+ task_queue=self.task_queue,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
+ )
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
+
+ async def test_vnf_prepare_workflow__activity_set_vnf_model_fails__get_expected_error_details(
+ self,
+ ):
async with self.env:
async with Worker(
self.client,
arg=wf_input,
id=f"{WORKFLOW_VNF_PREPARE}-{wf_input.vnfr_uuid}",
task_queue=self.task_queue,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
- self.assertEqual(str(err.exception), "Workflow execution failed")
self.assertEqual(
- str(err.exception.cause.cause.message),
- "set-vnf-model failed.",
+ str(err.exception.cause.cause), "TestException: set-vnf-model failed."
)
debug_mode=DEBUG_MODE,
)
- async def execute_workflow(self):
+ async def execute_workflow(self, wf_input=wf_input):
return await self.client.execute_workflow(
VnfInstantiateWorkflow.run,
- arg=VnfInstantiateInput(vnfr_uuid=vnfr_uuid, model_name="a-model-name"),
- id="wf1",
+ arg=wf_input,
+ id=uuid.uuid4().hex,
task_queue=self.task_queue,
+ task_timeout=TASK_TIMEOUT,
+ execution_timeout=EXECUTION_TIMEOUT,
)
- def check_state_change_call_counts(self):
- self.assertEqual(self.mock_change_vnf_instantiation_state_tracker.call_count, 2)
- self.assertEqual(self.mock_change_vnf_state_tracker.call_count, 1)
- self.assertEqual(self.mock_send_notification_for_vnf_tracker.call_count, 2)
-
- def workflow_is_succeeded(self):
+ def vnf_instantiation_state_is_updated(self, state):
call_mock_change_vnf_instantiation_state_tracker = (
self.mock_change_vnf_instantiation_state_tracker.call_args_list
)
- call_mock_change_vnf_state_tracker = (
- self.mock_change_vnf_state_tracker.call_args_list
- )
self.assertEqual(
call_mock_change_vnf_instantiation_state_tracker[1].args[0],
- ChangeVnfInstantiationStateInput(
- vnfr_uuid=vnfr_uuid, state=VnfInstantiationState.INSTANTIATED
- ),
- )
- self.assertEqual(
- call_mock_change_vnf_state_tracker[0].args[0],
- ChangeVnfStateInput(vnfr_uuid=vnfr_uuid, state=VnfState.STARTED),
+ ChangeVnfInstantiationStateInput(vnfr_uuid=vnfr_uuid, state=state),
)
- def workflow_is_failed(self, error):
- call_mock_change_vnf_instantiation_state_tracker = (
- self.mock_change_vnf_instantiation_state_tracker.call_args_list
- )
+ def vnf_state_is_updated(self, state):
call_mock_change_vnf_state_tracker = (
self.mock_change_vnf_state_tracker.call_args_list
)
- self.assertEqual(
- call_mock_change_vnf_instantiation_state_tracker[1].args[0],
- ChangeVnfInstantiationStateInput(
- vnfr_uuid=vnfr_uuid, state=VnfInstantiationState.INSTANTIATED
- ),
- )
self.assertEqual(
call_mock_change_vnf_state_tracker[0].args[0],
- ChangeVnfStateInput(vnfr_uuid=vnfr_uuid, state=VnfState.STOPPED),
+ ChangeVnfStateInput(vnfr_uuid=vnfr_uuid, state=state),
)
- self.assertEqual(str(error.exception), "Workflow execution failed")
@activity.defn(name=ACTIVITY_CHANGE_VNF_STATE)
async def mock_change_vnf_state(self, nf_state_input: ChangeVnfStateInput) -> None:
async def mock_send_notification_for_vnf(self, input) -> None:
self.mock_send_notification_for_vnf_tracker()
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
+ @patch(
+ "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow._get_vdu_instantiate_info"
)
- async def test_vnf_instantiate_workflow_successful(self, mock_instantiate_vdus):
+ async def test_vnf_instantiate_workflow__successful__updates_vnf_instantiation_state(
+ self, mock_get_vdu_instantiate_info
+ ):
+ workflows = [
+ VnfInstantiateWorkflow,
+ MockPrepareVnfWorkflow,
+ MockVduInstantiateWorkflow,
+ ]
activities = [
mock_get_task_queue,
self.mock_change_vnf_instantiation_state,
self.mock_change_vnf_state,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
mock_get_vim_cloud,
]
+ mock_get_vdu_instantiate_info.return_value = (
+ sample_vdu_instantiate_input_with_config,
+ sample_vdu_instantiate_wf_id_1,
+ )
async with self.env, self.get_worker(
- self.task_queue, self.workflows, activities
- ):
+ self.task_queue, workflows, activities
+ ), self.get_worker(self.task_queue, workflows, activities):
await self.execute_workflow()
- self.check_state_change_call_counts()
- self.workflow_is_succeeded()
- mock_instantiate_vdus.assert_called_once_with(
- vnfr=sample_vnfr, vnfd=sample_vnfd, task_queue=LCM_TASK_QUEUE, cloud=cloud
- )
+ self.vnf_instantiation_state_is_updated(VnfInstantiationState.INSTANTIATED)
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
+ @patch(
+ "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow._get_vdu_instantiate_info"
)
- async def test_vnf_instantiate_workflow_change_vnf_instantiation_state_exception(
- self, mock_instantiate_vdus
+ async def test_vnf_instantiate_workflow__successful__updates_vnf_state(
+ self, mock_get_vdu_instantiate_info
+ ):
+ workflows = [
+ VnfInstantiateWorkflow,
+ MockPrepareVnfWorkflow,
+ MockVduInstantiateWorkflow,
+ ]
+ activities = [
+ mock_get_task_queue,
+ self.mock_change_vnf_instantiation_state,
+ self.mock_change_vnf_state,
+ self.mock_send_notification_for_vnf,
+ mock_set_vnf_model,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
+ mock_get_vim_cloud,
+ ]
+ mock_get_vdu_instantiate_info.return_value = (
+ sample_vdu_instantiate_input_with_config,
+ sample_vdu_instantiate_wf_id_1,
+ )
+ async with self.env, self.get_worker(
+ self.task_queue, workflows, activities
+ ), self.get_worker(self.task_queue, workflows, activities):
+ await self.execute_workflow()
+ self.vnf_instantiation_state_is_updated(VnfState.STARTED)
+
+ async def test_vnf_instantiate_workflow__activity_change_vnf_instantiation_state_failed__raise_activity_error(
+ self,
):
activities = [
mock_get_task_queue,
self.mock_change_vnf_state,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
mock_get_vim_cloud,
]
async with self.env, self.get_worker(
):
with self.assertRaises(WorkflowFailureError) as err:
await self.execute_workflow()
- self.assertEqual(self.mock_change_vnf_instantiation_state_tracker.call_count, 6)
- self.assertEqual(self.mock_change_vnf_state_tracker.call_count, 0)
- self.assertEqual(self.mock_send_notification_for_vnf_tracker.call_count, 0)
- call_mock_change_vnf_instantiation_state_tracker = (
- self.mock_change_vnf_instantiation_state_tracker.call_args_list
- )
- self.assertEqual(
- call_mock_change_vnf_instantiation_state_tracker[1].args[0],
- ChangeVnfInstantiationStateInput(
- vnfr_uuid=vnfr_uuid, state=VnfInstantiationState.NOT_INSTANTIATED
- ),
- )
- mock_instantiate_vdus.assert_not_called()
- self.assertEqual(str(err.exception), "Workflow execution failed")
- self.assertEqual(
- str(err.exception.cause.cause.message),
- "change-vnf-instantiation-state failed.",
- )
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
- )
- async def test_vnf_instantiate_workflow_change_vnf_state_exception(
- self, mock_instantiate_vdus
+ async def test_vnf_instantiate_workflow__activity_change_vnf_instantiation_state_failed__vnf_state_not_updated(
+ self,
+ ):
+ activities = [
+ mock_get_task_queue,
+ self.mock_change_vnf_instantiation_state_exception,
+ self.mock_change_vnf_state,
+ self.mock_send_notification_for_vnf,
+ mock_set_vnf_model,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
+ mock_get_vim_cloud,
+ ]
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ with self.assertRaises(WorkflowFailureError):
+ await self.execute_workflow()
+ self.mock_change_vnf_state_tracker.assert_not_called()
+
+ async def test_vnf_instantiate_workflow__change_vnf_state_failed__raise_activity_error(
+ self,
):
activities = [
mock_get_task_queue,
self.mock_change_vnf_state_exception,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
mock_get_vim_cloud,
]
async with self.env, self.get_worker(
):
with self.assertRaises(WorkflowFailureError) as err:
await self.execute_workflow()
- self.assertEqual(self.mock_change_vnf_instantiation_state_tracker.call_count, 3)
- self.assertEqual(self.mock_change_vnf_state_tracker.call_count, 6)
- self.assertEqual(self.mock_send_notification_for_vnf_tracker.call_count, 1)
- # using workflow_is_succeeded method since vnfInstantationState is being changed to INSTANTIATED and
- # vnfState to STARTED (not STOPPED)
- self.workflow_is_succeeded()
- self.assertEqual(
- str(err.exception.cause.cause.message),
- "change-vnf-state failed.",
- )
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
- )
- async def test_vnf_instantiate_workflow_empty_vnf_details(
- self, mock_instantiate_vdus
+ async def test_vnf_instantiate_workflow__get_task_queue_failed__raises_activity_error(
+ self,
):
activities = [
- mock_get_task_queue,
+ mock_get_task_queue_raise_exception,
self.mock_change_vnf_instantiation_state,
self.mock_change_vnf_state,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details_empty_output,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
mock_get_vim_cloud,
]
async with self.env, self.get_worker(
self.task_queue, self.workflows, activities
):
- await self.execute_workflow()
- self.check_state_change_call_counts()
- self.workflow_is_succeeded()
- mock_instantiate_vdus.assert_called_once_with(
- vnfr={}, vnfd={}, task_queue=LCM_TASK_QUEUE, cloud=cloud
- )
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
- )
- async def test_vnf_instantiate_workflow_get_task_queue_raises_exception(
- self, mock_instantiate_vdus
+ async def test_vnf_instantiate_workflow__wf_vnf_prepare_failed__raises_child_wf_error(
+ self,
):
activities = [
- mock_get_task_queue_raise_exception,
+ mock_get_task_queue,
self.mock_change_vnf_instantiation_state,
self.mock_change_vnf_state,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
mock_get_vim_cloud,
]
async with self.env, self.get_worker(
- self.task_queue, self.workflows, activities
+ self.task_queue,
+ [
+ VnfInstantiateWorkflow,
+ MockPrepareVnfWorkflowFailed,
+ MockVduInstantiateWorkflow,
+ ],
+ activities,
):
with self.assertRaises(WorkflowFailureError) as err:
await self.execute_workflow()
- self.check_state_change_call_counts()
- self.workflow_is_failed(err)
- mock_instantiate_vdus.assert_not_called()
- self.assertEqual(
- str(err.exception.cause.cause.message),
- "get_task_queue failed.",
- )
+ self.assertTrue(isinstance(err.exception.cause.cause, ChildWorkflowError))
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
- )
- async def test_vnf_instantiate_workflow_get_vnf_details_raises_exception(
- self, mock_instantiate_vdus
+ async def test_vnf_instantiate_workflow__wf_vdu_instantiate_failed__raises_child_wf_error(
+ self,
):
- workflows = [VnfInstantiateWorkflow, MockPrepareVnfWorkflow]
activities = [
mock_get_task_queue,
self.mock_change_vnf_instantiation_state,
self.mock_change_vnf_state,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details_raise_exception,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
mock_get_vim_cloud,
]
- async with self.env, self.get_worker(self.task_queue, workflows, activities):
+ async with self.env, self.get_worker(
+ self.task_queue,
+ [
+ VnfInstantiateWorkflow,
+ MockPrepareVnfWorkflow,
+ MockVduInstantiateWorkflowFailed,
+ ],
+ activities,
+ ):
with self.assertRaises(WorkflowFailureError) as err:
await self.execute_workflow()
- self.check_state_change_call_counts()
- self.workflow_is_failed(err)
- mock_instantiate_vdus.assert_not_called()
- self.assertEqual(
- str(err.exception.cause.cause.message),
- "get_vnf_details failed.",
- )
+ self.assertTrue(isinstance(err.exception.cause, ChildWorkflowError))
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
- )
- async def test_vnf_instantiate_workflow_get_vim_cloud_raises_exception(
- self, mock_instantiate_vdus
+ async def test_vnf_instantiate_workflow__get_vnf_descriptor_failed__raises_activity_error(
+ self,
):
- workflows = [VnfInstantiateWorkflow, MockPrepareVnfWorkflow]
activities = [
mock_get_task_queue,
self.mock_change_vnf_instantiation_state,
self.mock_change_vnf_state,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details,
- mock_get_vim_cloud_raise_exception,
+ mock_get_vnf_descriptor_raise_exception,
+ mock_get_vnf_record,
+ mock_get_vim_cloud,
]
- async with self.env, self.get_worker(self.task_queue, workflows, activities):
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
with self.assertRaises(WorkflowFailureError) as err:
await self.execute_workflow()
- self.check_state_change_call_counts()
- self.workflow_is_failed(err)
- mock_instantiate_vdus.assert_not_called()
- self.assertEqual(
- str(err.exception.cause.cause.message),
- "get-vim-cloud failed.",
- )
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_vdu_instantiate_input"
- )
- async def test_vnf_instantiate_workflow_calls_vdu_instantiate_workflow(
- self, mock_vdu_instantiate_input
+ async def test_vnf_instantiate_workflow__get_vnf_record_failed__raises_activity_error(
+ self,
):
- mock_vdu_instantiate_input.return_value = (
- sample_vdu_instantiate_input,
- "vdu-instantiate-workflow-id",
- )
activities = [
mock_get_task_queue,
self.mock_change_vnf_instantiation_state,
self.mock_change_vnf_state,
self.mock_send_notification_for_vnf,
mock_set_vnf_model,
- mock_get_vnf_details,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record_raise_exception,
mock_get_vim_cloud,
]
async with self.env, self.get_worker(
self.task_queue, self.workflows, activities
):
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
+
+ async def test_vnf_instantiate_workflow__get_vim_cloud_failed__raises_activity_error(
+ self,
+ ):
+ activities = [
+ mock_get_task_queue,
+ self.mock_change_vnf_instantiation_state,
+ self.mock_change_vnf_state,
+ self.mock_send_notification_for_vnf,
+ mock_set_vnf_model,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
+ mock_get_vim_cloud_raise_exception,
+ ]
+ async with self.env, self.get_worker(
+ self.task_queue, self.workflows, activities
+ ):
+ with self.assertRaises(WorkflowFailureError) as err:
+ await self.execute_workflow()
+ self.assertTrue(isinstance(err.exception.cause, ActivityError))
+
+ @patch("osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus")
+ async def test_vnf_instantiate_workflow__use_different_task_queue__use_juju_task_queue(
+ self, mock_instantiate_vdus
+ ):
+ workflows = [VnfInstantiateWorkflow, MockPrepareVnfWorkflow]
+ activities = [
+ mock_get_different_task_queue,
+ self.mock_change_vnf_instantiation_state,
+ self.mock_change_vnf_state,
+ self.mock_send_notification_for_vnf,
+ mock_set_vnf_model,
+ mock_get_vnf_descriptor,
+ mock_get_vnf_record,
+ mock_get_vim_cloud,
+ ]
+ async with self.env, self.get_worker(
+ self.task_queue, workflows, activities
+ ), self.get_worker(juju_task_queue, workflows, activities):
await self.execute_workflow()
- self.check_state_change_call_counts()
- self.workflow_is_succeeded()
- call_mock_vdu_instantiate_input = mock_vdu_instantiate_input.call_args_list
- self.assertEqual(call_mock_vdu_instantiate_input[0][1]["vnfr"], sample_vnfr)
- self.assertEqual(call_mock_vdu_instantiate_input[0][1]["vnfd"], sample_vnfd)
- self.assertEqual(call_mock_vdu_instantiate_input[0][1]["vdu"], vdu)
+ mock_instantiate_vdus.assert_called_once_with(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ task_queue=juju_task_queue,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_vdu_instantiate_input"
+
+class TestInstantiateVdus(asynctest.TestCase):
+ @patch(
+ "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow._get_vdu_instantiate_info"
)
- @asynctest.mock.patch("temporalio.workflow.execute_child_workflow")
- async def test_instantiate_vdus_single_vdu(
- self, mock_execute_child_workflow: AsyncMock, mock_get_vdu_instantiate_input
+ @patch("temporalio.workflow.execute_child_workflow")
+ async def test_instantiate_vdus__empty_vnf_instantiation_config__child_wf_executed_with_expected_vdu_instantiate_input(
+ self,
+ mock_execute_child_workflow,
+ mock_get_vdu_instantiate_info,
):
- mock_get_vdu_instantiate_input.return_value = (
+ mock_get_vdu_instantiate_info.return_value = (
sample_vdu_instantiate_input,
- "vdu-instantiate-workflow-id",
+ sample_vdu_instantiate_wf_id_1,
)
await VnfInstantiateWorkflow.instantiate_vdus(
- sample_vnfr, sample_vnfd, LCM_TASK_QUEUE, cloud
- )
- self.assertEqual(mock_execute_child_workflow.call_count, 1)
- mock_execute_child_workflow.assert_called_once_with(
- workflow=WORKFLOW_VDU_INSTANTIATE,
- arg=sample_vdu_instantiate_input,
- task_queue=LCM_TASK_QUEUE,
- id="vdu-instantiate-workflow-id",
+ sample_vnfr, sample_vnfd, LCM_TASK_QUEUE, cloud, {}
)
- mock_get_vdu_instantiate_input.assert_called_once_with(
- vnfr=sample_vnfr, vnfd=sample_vnfd, vdu=vdu, cloud=cloud
+ call_mock_execute_child_workflow = mock_execute_child_workflow.call_args_list
+ self.assertEqual(
+ call_mock_execute_child_workflow[0].kwargs,
+ {
+ "arg": sample_vdu_instantiate_input,
+ "id": sample_vdu_instantiate_wf_id_1,
+ "task_queue": LCM_TASK_QUEUE,
+ "workflow": "vdu-instantiate",
+ },
)
- @asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_vdu_instantiate_input"
+ @patch(
+ "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow._get_vdu_instantiate_info"
)
- @asynctest.mock.patch("temporalio.workflow.execute_child_workflow")
- async def test_instantiate_vdus_multiple_vdus(
- self, mock_execute_child_workflow: AsyncMock, mock_get_vdu_instantiate_input
+ @patch("temporalio.workflow.execute_child_workflow")
+ async def test_instantiate_vdus__vnf_instantiation_config_exists__child_wf_executed_with_expected_vdu_instantiate_input(
+ self,
+ mock_execute_child_workflow,
+ mock_get_vdu_instantiate_info,
):
- sample_vnfd_multi_vdu = deepcopy(sample_vnfd)
- sample_vnfd_multi_vdu["vdu"] = [vdu, vdu]
- mock_get_vdu_instantiate_input.side_effect = [
- (sample_vdu_instantiate_input, "vdu-instantiate-workflow-id-1"),
- (sample_vdu_instantiate_input, "vdu-instantiate-workflow-id-2"),
- ]
+ mock_get_vdu_instantiate_info.return_value = (
+ sample_vdu_instantiate_input_with_config,
+ sample_vdu_instantiate_wf_id_1,
+ )
await VnfInstantiateWorkflow.instantiate_vdus(
- sample_vnfr, sample_vnfd_multi_vdu, LCM_TASK_QUEUE, cloud
+ sample_vnfr, sample_vnfd, LCM_TASK_QUEUE, cloud, vnf_config
)
- self.assertEqual(mock_execute_child_workflow.call_count, 2)
call_mock_execute_child_workflow = mock_execute_child_workflow.call_args_list
self.assertEqual(
- call_mock_execute_child_workflow[0][1],
+ call_mock_execute_child_workflow[0].kwargs,
{
- "arg": sample_vdu_instantiate_input,
- "id": "vdu-instantiate-workflow-id-1",
- "task_queue": "lcm-task-queue",
+ "arg": sample_vdu_instantiate_input_with_config,
+ "id": sample_vdu_instantiate_wf_id_1,
+ "task_queue": LCM_TASK_QUEUE,
"workflow": "vdu-instantiate",
},
)
- self.assertEqual(
- call_mock_execute_child_workflow[1][1],
- {
- "arg": sample_vdu_instantiate_input,
- "id": "vdu-instantiate-workflow-id-2",
- "task_queue": "lcm-task-queue",
- "workflow": "vdu-instantiate",
- },
+
+ @patch(
+ "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow._get_vdu_instantiate_info"
+ )
+ @patch("temporalio.workflow.execute_child_workflow")
+ async def test_instantiate_vdus__vnfd_without_vdu__child_wf_is_not_executed(
+ self,
+ mock_execute_child_workflow,
+ mock_get_vdu_instantiate_info,
+ ):
+ vnfd = deepcopy(sample_vnfd)
+ vnfd["vdu"] = []
+ await VnfInstantiateWorkflow.instantiate_vdus(
+ sample_vnfr, vnfd, LCM_TASK_QUEUE, cloud, {}
)
- call_mock_get_vdu_instantiate_input = (
- mock_get_vdu_instantiate_input.call_args_list
+ mock_execute_child_workflow.assert_not_called()
+
+ @patch(
+ "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow._get_vdu_instantiate_info"
+ )
+ @patch("temporalio.workflow.execute_child_workflow")
+ async def test_instantiate_vdus__use_juju_task_queue__child_wf_executed_with_juju_task_queue(
+ self,
+ mock_execute_child_workflow,
+ mock_get_vdu_instantiate_info,
+ ):
+ mock_get_vdu_instantiate_info.return_value = (
+ sample_vdu_instantiate_input_with_config,
+ sample_vdu_instantiate_wf_id_1,
)
- self.assertEqual(
- call_mock_get_vdu_instantiate_input[0][1],
- {
- "vnfr": sample_vnfr,
- "vnfd": sample_vnfd_multi_vdu,
- "vdu": vdu,
- "cloud": cloud,
- },
+ await VnfInstantiateWorkflow.instantiate_vdus(
+ sample_vnfr, sample_vnfd, juju_task_queue, cloud, vnf_config
)
+ call_mock_execute_child_workflow = mock_execute_child_workflow.call_args_list
self.assertEqual(
- call_mock_get_vdu_instantiate_input[1][1],
+ call_mock_execute_child_workflow[0].kwargs,
{
- "vnfr": sample_vnfr,
- "vnfd": sample_vnfd_multi_vdu,
- "vdu": vdu,
- "cloud": cloud,
+ "arg": sample_vdu_instantiate_input_with_config,
+ "id": sample_vdu_instantiate_wf_id_1,
+ "task_queue": juju_task_queue,
+ "workflow": "vdu-instantiate",
},
)
+
+class TestGetVduInstantiateInfo(asynctest.TestCase):
@asynctest.mock.patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.instantiate_vdus"
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
)
- async def test_vnf_instantiate_workflow_successful_use_different_task_queue(
- self, mock_instantiate_vdus
- ):
- workflows = [VnfInstantiateWorkflow, MockPrepareVnfWorkflow]
- activities = [
- mock_get_different_task_queue,
- self.mock_change_vnf_instantiation_state,
- self.mock_change_vnf_state,
- self.mock_send_notification_for_vnf,
- mock_set_vnf_model,
- mock_get_vnf_details,
- mock_get_vim_cloud,
- ]
- async with self.env, self.get_worker(
- self.task_queue, workflows, activities
- ), self.get_worker(juju_task_queue, workflows, activities):
- await self.execute_workflow()
- self.check_state_change_call_counts()
- self.workflow_is_succeeded()
- mock_instantiate_vdus.assert_called_once_with(
- vnfr=sample_vnfr, vnfd=sample_vnfd, task_queue=juju_task_queue, cloud=cloud
- )
-
-
-class TestGetVduInstantiateInputMethods(TestCase):
- def test_get_flavor_details_successful(self):
- compute_desc_id = "compute-id-1"
- result = VnfInstantiateWorkflow.get_flavor_details(compute_desc_id, sample_vnfd)
- self.assertEqual(result, flavor_1)
-
- def test_get_flavor_details_empty_compute_desc(self):
- compute_desc_id = ""
- result = VnfInstantiateWorkflow.get_flavor_details(compute_desc_id, sample_vnfd)
- self.assertEqual(result, {})
-
- def test_get_flavor_details_compute_desc_not_found(self):
- compute_desc_id = "compute-id-5"
- result = VnfInstantiateWorkflow.get_flavor_details(compute_desc_id, sample_vnfd)
- self.assertEqual(result, {})
-
- def test_get_flavor_details_empty_vnfd(self):
- compute_desc_id = "compute-id-5"
- result = VnfInstantiateWorkflow.get_flavor_details(compute_desc_id, {})
- self.assertEqual(result, {})
-
- def test_get_flavor_details_wrong_vnfd_format(self):
- compute_desc_id = "compute-id-2"
- sample_vnfd = {
- "_id": vnfd_id,
- "vdu": [vdu],
- "virtual-compute-desc": [
- {
- "virtual-memory": {"size": "4"},
- }
- ],
- }
- result = VnfInstantiateWorkflow.get_flavor_details(compute_desc_id, sample_vnfd)
- self.assertEqual(result, {})
-
- @patch("osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_flavor_details")
- def test_get_compute_constraints(self, mock_get_flavor_details):
- mock_get_flavor_details.return_value = flavor_1
- result = VnfInstantiateWorkflow.get_compute_constraints(vdu, sample_vnfd)
- self.assertEqual(VduComputeConstraints(cores=2, mem=4), result)
-
- @patch("osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_flavor_details")
- def test_get_compute_constraints_empty_flavor_details(
- self, mock_get_flavor_details
- ):
- mock_get_flavor_details.return_value = {}
- result = VnfInstantiateWorkflow.get_compute_constraints(vdu, sample_vnfd)
- self.assertEqual(VduComputeConstraints(cores=0, mem=0), result)
-
- @patch("osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_flavor_details")
- def test_get_compute_constraints_flavor_details_is_none(
- self, mock_get_flavor_details
- ):
- mock_get_flavor_details.return_value = None
- result = VnfInstantiateWorkflow.get_compute_constraints(vdu, sample_vnfd)
- self.assertEqual(VduComputeConstraints(cores=0, mem=0), result)
-
- @patch("osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_flavor_details")
- def test_get_compute_constraints_flavor_has_only_cpu(self, mock_get_flavor_details):
- mock_get_flavor_details.return_value = flavor_2
- result = VnfInstantiateWorkflow.get_compute_constraints(vdu, sample_vnfd)
- self.assertEqual(VduComputeConstraints(cores=2, mem=0), result)
-
- @patch("osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_flavor_details")
- def test_get_compute_constraints_flavor_has_only_memory(
- self, mock_get_flavor_details
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__empty_vnf_instantiation_config__get_expected_vdu_inst_input_and_wf_id(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
):
- mock_get_flavor_details.return_value = flavor_3
- result = VnfInstantiateWorkflow.get_compute_constraints(vdu, sample_vnfd)
- self.assertEqual(VduComputeConstraints(cores=0, mem=4), result)
+ mock_get_compute_constraints.return_value = sample_constraints
+ mock_get_charm_info.return_value = sample_charm_info
+ mock_get_vdu_instantiation_params.return_value = {}
+ mock_get_application_config.return_value = {}
+ (
+ vdu_instantiate_input,
+ vdu_instantiate_workflow_id,
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+ self.assertTupleEqual(
+ (vdu_instantiate_input, vdu_instantiate_workflow_id),
+ (sample_vdu_instantiate_input, "my-model-name-my-app"),
+ )
- @patch("osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info")
- @patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_compute_constraints"
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
)
- def test_get_vdu_instantiate_input(
- self, mock_get_compute_constraints, mock_get_charm_info
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__with_vnf_instantiation_config__get_expected_vdu_inst_input_and_wf_id(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
):
mock_get_compute_constraints.return_value = sample_constraints
mock_get_charm_info.return_value = sample_charm_info
+ mock_get_vdu_instantiation_params.return_value = config
+ mock_get_application_config.return_value = app_config
(
vdu_instantiate_input,
- vdu_instantiate_wf_id,
- ) = VnfInstantiateWorkflow.get_vdu_instantiate_input(
- sample_vnfr, sample_vnfd, vdu, cloud
+ vdu_instantiate_workflow_id,
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config=vnf_config,
+ )
+ self.assertTupleEqual(
+ (vdu_instantiate_input, vdu_instantiate_workflow_id),
+ (sample_vdu_instantiate_input_with_config, "my-model-name-my-app"),
)
- self.assertEqual(vdu_instantiate_input, sample_vdu_instantiate_input)
- self.assertEqual(vdu_instantiate_wf_id, "my-model-name-my-app")
- mock_get_charm_info.assert_called_once()
- mock_get_compute_constraints.assert_called_once()
- @patch("osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info")
- @patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_compute_constraints"
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
)
- def test_get_vdu_instantiate_input_vnfr_without_namespace(
- self, mock_get_compute_constraints, mock_get_charm_info
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__vnfr_without_namespace__raise_type_error(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
):
vnfr = deepcopy(sample_vnfr)
vnfr.pop("namespace")
mock_get_compute_constraints.return_value = sample_constraints
mock_get_charm_info.return_value = sample_charm_info
- with self.assertRaises(TypeError) as err:
- VnfInstantiateWorkflow.get_vdu_instantiate_input(
- vnfr, sample_vnfd, vdu, cloud
+ with self.assertRaises(TypeError):
+ VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
)
- self.assertEqual(
- str(err.exception),
- "unsupported operand type(s) for +: 'NoneType' and 'str'",
- )
- mock_get_charm_info.assert_called_once()
- mock_get_compute_constraints.assert_called_once()
- @patch("osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info")
- @patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_compute_constraints"
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
)
- def test_get_vdu_instantiate_input_app_name_is_empty(
- self, mock_get_compute_constraints, mock_get_charm_info
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__app_name_is_empty__expected_wf_id(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
):
mock_get_compute_constraints.return_value = sample_constraints
charm_info = CharmInfo(app_name="", channel="latest", entity_url="my-url")
+ mock_get_application_config.return_value = app_config
mock_get_charm_info.return_value = charm_info
(
- vdu_instantiate_input,
- vdu_instantiate_wf_id,
- ) = VnfInstantiateWorkflow.get_vdu_instantiate_input(
- sample_vnfr, sample_vnfd, vdu, cloud
+ _,
+ vdu_instantiate_workflow_id,
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
)
- self.assertEqual(
- vdu_instantiate_input,
- VduInstantiateInput(
- vim_uuid=vim_account_id,
- model_name=model_name,
- charm_info=charm_info,
- constraints=sample_constraints,
- cloud=cloud,
- config=config,
- ),
+ self.assertEqual(vdu_instantiate_workflow_id, "my-model-name-")
+
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_compute_constraints_failed__no_vdu_inst_wf_input_and_vdu_wf_id(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
+ ):
+ mock_get_compute_constraints.side_effect = GetComputeConstraintsException(
+ "get_compute_constraints failed"
)
- self.assertEqual(vdu_instantiate_wf_id, "my-model-name-")
- mock_get_charm_info.assert_called_once()
- mock_get_compute_constraints.assert_called_once()
+ mock_get_charm_info.return_value = sample_charm_info
+ with self.assertRaises(Exception):
+ (
+ vdu_instantiate_input,
+ vdu_instantiate_workflow_id,
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+ self.assertEqual(
+ (vdu_instantiate_input, vdu_instantiate_workflow_id), (None, None)
+ )
- @patch("osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info")
- @patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_compute_constraints"
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
)
- def test_get_vdu_instantiate_input_get_compute_constraints_raises(
- self, mock_get_compute_constraints, mock_get_charm_info
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_compute_constraints_failed__raise_compute_constraints_exception(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
):
- mock_get_compute_constraints.side_effect = TestException(
+ mock_get_compute_constraints.side_effect = GetComputeConstraintsException(
"get_compute_constraints failed"
)
mock_get_charm_info.return_value = sample_charm_info
- with self.assertRaises(TestException) as err:
- result = VnfInstantiateWorkflow.get_vdu_instantiate_input(
- sample_vnfr, sample_vnfd, vdu, cloud
+ with self.assertRaises(GetComputeConstraintsException):
+ VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
)
- self.assertEqual(result, None)
- self.assertEqual(str(err.exception), "get_compute_constraints failed")
- mock_get_charm_info.assert_called_once()
- mock_get_compute_constraints.assert_called_once()
- @patch("osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info")
- @patch(
- "osm_lcm.temporal.vnf_workflows.VnfInstantiateWorkflow.get_compute_constraints"
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
)
- def test_get_vdu_instantiate_input_get_charm_info_raises(
- self, mock_get_compute_constraints, mock_get_charm_info
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_charm_info_failed__raise_get_charm_info_exception(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
):
mock_get_compute_constraints.return_value = sample_constraints
- mock_get_charm_info.side_effect = TestException(
+ mock_get_charm_info.side_effect = GetCharmInfoException(
"get_compute_constraints failed"
)
- with self.assertRaises(TestException) as err:
- result = VnfInstantiateWorkflow.get_vdu_instantiate_input(
- sample_vnfr, sample_vnfd, vdu, cloud
+ with self.assertRaises(GetCharmInfoException):
+ VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_charm_info_failed__no_vdu_inst_wf_input_and_vdu_wf_id(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
+ ):
+ mock_get_compute_constraints.return_value = sample_constraints
+ mock_get_charm_info.side_effect = GetCharmInfoException(
+ "get_compute_constraints failed"
+ )
+ with self.assertRaises(Exception):
+ (
+ vdu_instantiate_input,
+ vdu_instantiate_workflow_id,
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+ self.assertEqual(
+ (vdu_instantiate_input, vdu_instantiate_workflow_id), (None, None)
+ )
+
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_vdu_instantiation_params_failed__raise_get_vdu_instantiation_params_exception(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
+ ):
+ mock_get_compute_constraints.return_value = sample_constraints
+ mock_get_charm_info.return_value = sample_charm_info
+ mock_get_vdu_instantiation_params.side_effect = (
+ GetVduInstantiationParamsException("get_vdu_instantiation_params failed")
+ )
+ mock_get_application_config.return_value = {}
+ with self.assertRaises(GetVduInstantiationParamsException):
+ VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_vdu_instantiation_params_failed__no_vdu_inst_wf_input_and_vdu_wf_id(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
+ ):
+ mock_get_compute_constraints.return_value = sample_constraints
+ mock_get_charm_info.return_value = sample_charm_info
+ mock_get_vdu_instantiation_params.side_effect = (
+ GetVduInstantiationParamsException("get_vdu_instantiation_params failed")
+ )
+ mock_get_application_config.return_value = {}
+ with self.assertRaises(Exception):
+ (
+ vdu_instantiate_input,
+ vdu_instantiate_workflow_id,
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+
+ self.assertEqual(
+ (vdu_instantiate_input, vdu_instantiate_workflow_id), (None, None)
+ )
+
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_application_config_failed__raise_get_application_config_exception(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
+ ):
+ mock_get_compute_constraints.return_value = sample_constraints
+ mock_get_charm_info.return_value = sample_charm_info
+ mock_get_vdu_instantiation_params.return_value = config
+ mock_get_application_config.side_effect = GetApplicationConfigException(
+ "get_vdu_instantiation_params failed"
+ )
+ with self.assertRaises(GetApplicationConfigException):
+ VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_application_config"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_vdu_instantiation_params"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.juju_paas_activities.CharmInfoUtils.get_charm_info"
+ )
+ @asynctest.mock.patch(
+ "osm_lcm.temporal.vnf_activities.VnfOperations.get_compute_constraints"
+ )
+ async def test_get_vdu_instantiate_info__get_application_config_failed__no_vdu_inst_wf_input_and_vdu_wf_id(
+ self,
+ mock_get_compute_constraints,
+ mock_get_charm_info,
+ mock_get_vdu_instantiation_params,
+ mock_get_application_config,
+ ):
+ mock_get_compute_constraints.return_value = sample_constraints
+ mock_get_charm_info.return_value = sample_charm_info
+ mock_get_vdu_instantiation_params.return_value = config
+ mock_get_application_config.side_effect = GetApplicationConfigException(
+ "get_vdu_instantiation_params failed"
+ )
+ with self.assertRaises(Exception):
+ (
+ vdu_instantiate_input,
+ vdu_instantiate_workflow_id,
+ ) = VnfInstantiateWorkflow._get_vdu_instantiate_info(
+ vnfr=sample_vnfr,
+ vnfd=sample_vnfd,
+ vdu=vdu,
+ cloud=cloud,
+ vnf_instantiation_config={},
+ )
+ self.assertEqual(
+ (vdu_instantiate_input, vdu_instantiate_workflow_id), (None, None)
)
- self.assertEqual(result, None)
- self.assertEqual(str(err.exception), "get_compute_constraints failed")
- mock_get_charm_info.assert_called_once()
- mock_get_compute_constraints.assert_not_called()
if __name__ == "__main__":