OSMENG-1048 Implement day1 configuration for VDU
Day1 config implementation, arranging existing unit tests and imports
adding task and execution timeout policy for workflows in tests.
Change-Id: Ie5a2626eec01176723d8130576facbf4934d5285
Signed-off-by: Gulsum Atici <gulsum.atici@canonical.com>
diff --git a/osm_lcm/temporal/juju_paas_activities.py b/osm_lcm/temporal/juju_paas_activities.py
index 3182317..5082254 100644
--- a/osm_lcm/temporal/juju_paas_activities.py
+++ b/osm_lcm/temporal/juju_paas_activities.py
@@ -17,6 +17,7 @@
import base64
import logging
from dataclasses import dataclass
+
from juju.application import Application
from juju.controller import Controller
from n2vc.config import EnvironConfig
@@ -245,6 +246,7 @@
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)
diff --git a/osm_lcm/temporal/lcm_activities.py b/osm_lcm/temporal/lcm_activities.py
index 5f360f1..6ddb0f3 100644
--- a/osm_lcm/temporal/lcm_activities.py
+++ b/osm_lcm/temporal/lcm_activities.py
@@ -14,8 +14,8 @@
# 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,
@@ -25,6 +25,7 @@
ACTIVITY_NSLCM_NO_OP,
)
from osm_lcm.data_utils.database.database import Database
+from temporalio import activity
class NsLcmActivity:
diff --git a/osm_lcm/temporal/lcm_workflows.py b/osm_lcm/temporal/lcm_workflows.py
index 2dc7096..6c8c28f 100644
--- a/osm_lcm/temporal/lcm_workflows.py
+++ b/osm_lcm/temporal/lcm_workflows.py
@@ -17,9 +17,6 @@
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,
@@ -31,6 +28,9 @@
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):
@@ -84,11 +84,11 @@
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
@@ -98,7 +98,7 @@
await self.update_operation_state(
LcmOperationState.FAILED,
error_message=str(e),
- detailed_status=err_details,
+ detailed_status=str(e),
)
raise e
diff --git a/osm_lcm/temporal/ns_activities.py b/osm_lcm/temporal/ns_activities.py
index b937717..8c7c182 100644
--- a/osm_lcm/temporal/ns_activities.py
+++ b/osm_lcm/temporal/ns_activities.py
@@ -18,17 +18,19 @@
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:
@@ -36,12 +38,12 @@
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
@@ -55,10 +57,36 @@
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:
diff --git a/osm_lcm/temporal/ns_workflows.py b/osm_lcm/temporal/ns_workflows.py
index 343a9c9..6281ee6 100644
--- a/osm_lcm/temporal/ns_workflows.py
+++ b/osm_lcm/temporal/ns_workflows.py
@@ -15,14 +15,13 @@
# 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,
@@ -31,12 +30,16 @@
)
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)
@@ -50,8 +53,7 @@
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)
@@ -63,27 +65,40 @@
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
)
)
@@ -94,7 +109,7 @@
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
@@ -125,3 +140,19 @@
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 {}
diff --git a/osm_lcm/temporal/vdu_workflows.py b/osm_lcm/temporal/vdu_workflows.py
index 0c91e99..7349535 100644
--- a/osm_lcm/temporal/vdu_workflows.py
+++ b/osm_lcm/temporal/vdu_workflows.py
@@ -16,9 +16,6 @@
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 (
@@ -32,6 +29,9 @@
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)
diff --git a/osm_lcm/temporal/vim_activities.py b/osm_lcm/temporal/vim_activities.py
index 4bd5514..e9db668 100644
--- a/osm_lcm/temporal/vim_activities.py
+++ b/osm_lcm/temporal/vim_activities.py
@@ -15,8 +15,8 @@
# 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,
@@ -28,6 +28,7 @@
UpdateVimStateInput,
)
from osm_lcm.data_utils.database.database import Database
+from temporalio import activity
class VimDbActivity:
diff --git a/osm_lcm/temporal/vim_workflows.py b/osm_lcm/temporal/vim_workflows.py
index cb7d636..5d6b08c 100644
--- a/osm_lcm/temporal/vim_workflows.py
+++ b/osm_lcm/temporal/vim_workflows.py
@@ -16,9 +16,6 @@
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 (
@@ -40,6 +37,9 @@
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)
diff --git a/osm_lcm/temporal/vnf_activities.py b/osm_lcm/temporal/vnf_activities.py
index 2e8ab1c..9581db0 100644
--- a/osm_lcm/temporal/vnf_activities.py
+++ b/osm_lcm/temporal/vnf_activities.py
@@ -14,12 +14,15 @@
# 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,
@@ -31,14 +34,20 @@
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
@@ -81,7 +90,7 @@
"""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.
@@ -104,14 +113,14 @@
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, vnfds
+ DB read: vnfrs
Raises (retryable):
DbException: If DB read operations fail, the collection or DB record ID does not exist.
@@ -126,10 +135,93 @@
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"]})
+ 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: vnfds
+
+ Raises (retryable):
+ DbException: If DB read operations fail, the collection or DB record ID does not exist.
+
+ Activity Lifecycle:
+ This activity should complete relatively quickly (less than 10
+ second).
+
+ This activity will not report a heartbeat due to its
+ short-running nature.
+
+ This is an idempotent activity.
+
+ """
+ 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:
@@ -208,7 +300,7 @@
)
@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:
diff --git a/osm_lcm/temporal/vnf_workflows.py b/osm_lcm/temporal/vnf_workflows.py
index c97f908..c121b05 100644
--- a/osm_lcm/temporal/vnf_workflows.py
+++ b/osm_lcm/temporal/vnf_workflows.py
@@ -13,14 +13,11 @@
# 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,
@@ -29,22 +26,25 @@
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,
@@ -52,6 +52,11 @@
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)
@@ -107,21 +112,27 @@
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}",
@@ -130,12 +141,16 @@
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(
@@ -170,7 +185,7 @@
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
@@ -241,13 +256,23 @@
)
@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,
@@ -257,53 +282,26 @@
)
@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
@@ -326,11 +324,11 @@
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,