diff options
author | Michal Jagiello <michal.jagiello@t-mobile.pl> | 2022-10-17 12:46:49 +0000 |
---|---|---|
committer | Michal Jagiello <michal.jagiello@t-mobile.pl> | 2022-10-17 14:05:09 +0000 |
commit | f2adf542e878c96895210f97ebf1ebb763b2f465 (patch) | |
tree | 91fc0faeb3436e723d07aed1f38ce59a6e7cc7c5 /src/onapsdk/so | |
parent | 49071a0d0425ef67fa552dbf14c81e5a11cc49e7 (diff) |
Release ONAP SDKv10.2
Issue-ID: INT-2150
Signed-off-by: Michal Jagiello <michal.jagiello@t-mobile.pl>
Change-Id: I650047c599a5aae6de7c6b42d38e34aea88578e2
Diffstat (limited to 'src/onapsdk/so')
22 files changed, 2392 insertions, 0 deletions
diff --git a/src/onapsdk/so/__init__.py b/src/onapsdk/so/__init__.py new file mode 100644 index 0000000..15a483f --- /dev/null +++ b/src/onapsdk/so/__init__.py @@ -0,0 +1,14 @@ +"""ONAP SDK SO package.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/onapsdk/so/deletion.py b/src/onapsdk/so/deletion.py new file mode 100644 index 0000000..35ff0ee --- /dev/null +++ b/src/onapsdk/so/deletion.py @@ -0,0 +1,167 @@ +"""Deletion module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from abc import ABC + +from onapsdk.onap_service import OnapService +from onapsdk.utils.headers_creator import headers_so_creator +from onapsdk.utils.jinja import jinja_env + +from onapsdk.so.so_element import OrchestrationRequest + + +class DeletionRequest(OrchestrationRequest, ABC): + """Deletion request base class.""" + + @classmethod + def send_request(cls, instance: "AaiResource", a_la_carte: bool = True) -> "Deletion": + """Abstract method to send instance deletion request. + + Raises: + NotImplementedError: Needs to be implemented in inheriting classes + + """ + raise NotImplementedError + + +class VfModuleDeletionRequest(DeletionRequest): # pytest: disable=too-many-ancestors + """VF module deletion class.""" + + @classmethod + def send_request(cls, + instance: "VfModuleInstance", + a_la_carte: bool = True) -> "VfModuleDeletion": + """Send request to SO to delete VNF instance. + + Args: + instance (VfModuleInstance): Vf Module instance to delete + a_la_carte (boolean): deletion mode + + Returns: + VnfDeletionRequest: Deletion request object + + """ + cls._logger.debug("VF module %s deletion request", instance.vf_module_id) + response = cls.send_message_json("DELETE", + (f"Create {instance.vf_module_id} VF module" + "deletion request"), + (f"{cls.base_url}/onap/so/infra/" + f"serviceInstantiation/{cls.api_version}/" + "serviceInstances/" + f"{instance.vnf_instance.service_instance.instance_id}/" + f"vnfs/{instance.vnf_instance.vnf_id}/" + f"vfModules/{instance.vf_module_id}"), + data=jinja_env(). + get_template("deletion_vf_module.json.j2"). + render(vf_module_instance=instance, + a_la_carte=a_la_carte), + headers=headers_so_creator(OnapService.headers)) + return cls(request_id=response["requestReferences"]["requestId"]) + + +class VnfDeletionRequest(DeletionRequest): # pytest: disable=too-many-ancestors + """VNF deletion class.""" + + @classmethod + def send_request(cls, + instance: "VnfInstance", + a_la_carte: bool = True) -> "VnfDeletionRequest": + """Send request to SO to delete VNF instance. + + Args: + instance (VnfInstance): VNF instance to delete + a_la_carte (boolean): deletion mode + + Returns: + VnfDeletionRequest: Deletion request object + + """ + cls._logger.debug("VNF %s deletion request", instance.vnf_id) + response = cls.send_message_json("DELETE", + f"Create {instance.vnf_id} VNF deletion request", + (f"{cls.base_url}/onap/so/infra/" + f"serviceInstantiation/{cls.api_version}/" + "serviceInstances/" + f"{instance.service_instance.instance_id}/" + f"vnfs/{instance.vnf_id}"), + data=jinja_env(). + get_template("deletion_vnf.json.j2"). + render(vnf_instance=instance, + a_la_carte=a_la_carte), + headers=headers_so_creator(OnapService.headers)) + return cls(request_id=response["requestReferences"]["requestId"]) + + +class ServiceDeletionRequest(DeletionRequest): # pytest: disable=too-many-ancestors + """Service deletion request class.""" + + @classmethod + def send_request(cls, + instance: "ServiceInstance", + a_la_carte: bool = True) -> "ServiceDeletionRequest": + """Send request to SO to delete service instance. + + Args: + instance (ServiceInstance): service instance to delete + a_la_carte (boolean): deletion mode + + Returns: + ServiceDeletionRequest: Deletion request object + + """ + cls._logger.debug("Service %s deletion request", instance.instance_id) + response = cls.send_message_json("DELETE", + f"Create {instance.instance_id} Service deletion request", + (f"{cls.base_url}/onap/so/infra/" + f"serviceInstantiation/{cls.api_version}/" + f"serviceInstances/{instance.instance_id}"), + data=jinja_env(). + get_template("deletion_service.json.j2"). + render(service_instance=instance, + a_la_carte=a_la_carte), + headers=headers_so_creator(OnapService.headers)) + return cls(request_id=response["requestReferences"]["requestId"]) + + +class NetworkDeletionRequest(DeletionRequest): # pylint: disable=too-many-ancestors + """Network deletion request class.""" + + @classmethod + def send_request(cls, + instance: "NetworkInstance", + a_la_carte: bool = True) -> "VnfDeletionRequest": + """Send request to SO to delete Network instance. + + Args: + instance (NetworkInstance): Network instance to delete + a_la_carte (boolean): deletion mode + + Returns: + NetworkDeletionRequest: Deletion request object + + """ + cls._logger.debug("Network %s deletion request", instance.network_id) + response = cls.send_message_json("DELETE", + f"Create {instance.network_id} Network deletion request", + (f"{cls.base_url}/onap/so/infra/" + f"serviceInstantiation/{cls.api_version}/" + "serviceInstances/" + f"{instance.service_instance.instance_id}/" + f"networks/{instance.network_id}"), + data=jinja_env(). + get_template("deletion_network.json.j2"). + render(network_instance=instance, + a_la_carte=a_la_carte), + headers=headers_so_creator(OnapService.headers)) + return cls(request_id=response["requestReferences"]["requestId"]) diff --git a/src/onapsdk/so/instantiation.py b/src/onapsdk/so/instantiation.py new file mode 100644 index 0000000..bb0bde2 --- /dev/null +++ b/src/onapsdk/so/instantiation.py @@ -0,0 +1,957 @@ +"""Instantion module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from abc import ABC +from dataclasses import dataclass, field +from typing import Any, Dict, Iterable, List, Optional +from uuid import uuid4 +from dacite import from_dict + +from onapsdk.aai.business.owning_entity import OwningEntity +from onapsdk.exceptions import ( + APIError, InvalidResponse, ParameterError, ResourceNotFound, StatusError +) +from onapsdk.onap_service import OnapService +from onapsdk.sdnc import NetworkPreload, VfModulePreload +from onapsdk.sdc.service import Network, Service as SdcService, Vnf, VfModule +from onapsdk.utils.jinja import jinja_env +from onapsdk.utils.headers_creator import headers_so_creator +from onapsdk.configuration import settings + +from .so_element import OrchestrationRequest + + +@dataclass +class Operation: + """Operation class with data about method and suffix for VnfOperation.""" + + request_method: str + request_suffix: str + + +class VnfOperation(Operation): # pylint: disable=too-few-public-methods + """Class to store possible operations' data for vnfs (request method and suffix).""" + + UPDATE = Operation("PUT", "") + HEALTHCHECK = Operation("POST", "/healthcheck") + + +@dataclass +class SoServiceVfModule: + """Class to store a VfModule instance parameters.""" + + model_name: str + instance_name: str + parameters: Dict[str, Any] = field(default_factory=dict) + processing_priority: Optional[int] = None + + +@dataclass +class SoServiceXnf: + """Class to store a Xnf instance parameters.""" + + model_name: str + instance_name: str + parameters: Dict[str, Any] = field(default_factory=dict) + processing_priority: Optional[int] = None + + @classmethod + def load(cls, data: Dict[str, Any]) -> "SoServiceVnf": + """Create a vnf instance description object from the dict. + + Useful if you keep your instance data in file. + + Returns: + SoServiceVnf: SoServiceVnf object created from the dictionary + + """ + return from_dict(data_class=cls, data=data) + + +@dataclass +class SoServiceVnf(SoServiceXnf): + """Class to store a Vnf instance parameters.""" + + vf_modules: List[SoServiceVfModule] = field(default_factory=list) + + +@dataclass +class SoServicePnf(SoServiceXnf): + """Class to store a Pnf instance parameters.""" + + +@dataclass +class SoService: + """Class to store SO Service parameters used for macro instantiation. + + Contains value list: List of vnfs to instantiate + Contains value: subscription service type + """ + + subscription_service_type: str + vnfs: List[SoServiceVnf] = field(default_factory=list) + pnfs: List[SoServicePnf] = field(default_factory=list) + instance_name: Optional[str] = None + + @classmethod + def load(cls, data: Dict[str, Any]) -> "SoService": + """Create a service instance description object from the dict. + + Useful if you keep your instance data in file. + + Returns: + SoService: SoService object created from the dictionary + + """ + return from_dict(data_class=cls, data=data) + + + +@dataclass +class VnfParameters: + """Class to store vnf parameters used for macro instantiation. + + Contains value lists: List vnf Instantiation parameters and list of + vfModule parameters + """ + + name: str + vnf_parameters: Iterable["InstantiationParameter"] = None + vfmodule_parameters: Iterable["VfmoduleParameters"] = None + +@dataclass +class VfmoduleParameters: + """Class to store vfmodule parameters used for macro instantiation. + + Contains value lists: List of vfModule parameters + """ + + name: str + vfmodule_parameters: Iterable["InstantiationParameter"] = None + + +@dataclass +class InstantiationParameter: + """Class to store instantiation parameters used for preload or macro instantiation. + + Contains two values: name of parameter and it's value + """ + + name: str + value: str + + +@dataclass +class Subnet: # pylint: disable=too-many-instance-attributes + """Class to store subnet parameters used for preload.""" + + name: str + start_address: str + gateway_address: str + role: str = None + cidr_mask: str = "24" + ip_version: str = "4" + dhcp_enabled: bool = False + dhcp_start_address: Optional[str] = None + dhcp_end_address: Optional[str] = None + + def __post_init__(self) -> None: + """Post init subnet method. + + Checks if both dhcp_start_address and dhcp_end_address values are + provided if dhcp is enabled. + + Raises: + ParameterError: Neither dhcp_start_addres + nor dhcp_end_address are provided + + """ + if self.dhcp_enabled and \ + not all([self.dhcp_start_address, + self.dhcp_end_address]): + msg = "DHCP is enabled but neither DHCP " \ + "start nor end adresses are provided." + raise ParameterError(msg) + + +class Instantiation(OrchestrationRequest, ABC): + """Abstract class used for instantiation.""" + + def __init__(self, + name: str, + request_id: str, + instance_id: str) -> None: + """Instantiate object initialization. + + Initializator used by classes inherited from this abstract class. + + Args: + name (str): instantiated object name + request_id (str): request ID + instance_id (str): instance ID + """ + super().__init__(request_id) + self.name: str = name + self.instance_id: str = instance_id + + +class VfModuleInstantiation(Instantiation): # pytest: disable=too-many-ancestors + """VF module instantiation class.""" + + def __init__(self, + name: str, + request_id: str, + instance_id: str, + vf_module: VfModule) -> None: + """Initialize class object. + + Args: + name (str): vf module name + request_id (str): request ID + instance_id (str): instance ID + vnf_instantiation (VnfInstantiation): VNF instantiation class object + vf_module (VfModule): VF module used for instantiation + """ + super().__init__(name, request_id, instance_id) + self.vf_module: VfModule = vf_module + + @classmethod + def instantiate_ala_carte(cls, # pylint: disable=too-many-arguments + vf_module: "VfModule", + vnf_instance: "VnfInstance", + cloud_region: "CloudRegion", + tenant: "Tenant", + vf_module_instance_name: str = None, + vnf_parameters: Iterable["InstantiationParameter"] = None, + use_preload: bool = True) -> "VfModuleInstantiation": + """Instantiate VF module. + + Iterate throught vf modules from service Tosca file and instantiate vf modules. + + Args: + vf_module (VfModule): VfModule to instantiate + vnf_instance (VnfInstance): VnfInstance object + cloud_region (CloudRegion, optional): Cloud region to use in instantiation request. + Defaults to None. + tenant (Tenant, optional): Tenant to use in instnatiation request. + Defaults to None. + vf_module_instance_name_factory (str, optional): Factory to create VF module names. + It's going to be a prefix of name. Index of vf module in Tosca file will be + added to it. + If no value is provided it's going to be + "Python_ONAP_SDK_vf_module_service_instance_{str(uuid4())}". + Defaults to None. + vnf_parameters (Iterable[InstantiationParameter], optional): Parameters which are + going to be used in preload upload for vf modules or passed in "userParams". + Defaults to None. + use_preload (bool, optional): This flag determines whether instantiation parameters + are used as preload or "userParams" content. Defaults to True + + Yields: + Iterator[VfModuleInstantiation]: VfModuleInstantiation class object. + + """ + if vf_module_instance_name is None: + vf_module_instance_name = \ + f"Python_ONAP_SDK_vf_module_instance_{str(uuid4())}" + if use_preload: + VfModulePreload.upload_vf_module_preload( + vnf_instance, + vf_module_instance_name, + vf_module, + vnf_parameters + ) + vnf_parameters = None + sdc_service: SdcService = vnf_instance.service_instance.sdc_service + response: dict = cls.send_message_json( + "POST", + (f"Instantiate {sdc_service.name} " + f"service vf module {vf_module.name}"), + (f"{cls.base_url}/onap/so/infra/serviceInstantiation/{cls.api_version}/" + f"serviceInstances/{vnf_instance.service_instance.instance_id}/vnfs/" + f"{vnf_instance.vnf_id}/vfModules"), + data=jinja_env().get_template("instantiate_vf_module_ala_carte.json.j2"). + render( + vf_module_instance_name=vf_module_instance_name, + vf_module=vf_module, + service=sdc_service, + cloud_region=cloud_region, + tenant=tenant, + vnf_instance=vnf_instance, + vf_module_parameters=vnf_parameters or [] + ), + headers=headers_so_creator(OnapService.headers) + ) + return VfModuleInstantiation( + name=vf_module_instance_name, + request_id=response["requestReferences"].get("requestId"), + instance_id=response["requestReferences"].get("instanceId"), + vf_module=vf_module + ) + + +class NodeTemplateInstantiation(Instantiation, ABC): # pytest: disable=too-many-ancestors + """Base class for service's node_template object instantiation.""" + + def __init__(self, # pylint: disable=too-many-arguments + name: str, + request_id: str, + instance_id: str, + line_of_business: str, + platform: str) -> None: + """Node template object initialization. + + Args: + name (str): Node template name + request_id (str): Node template instantiation request ID + instance_id (str): Node template instance ID + line_of_business (str): LineOfBusiness name + platform (str): Platform name + """ + super().__init__(name, request_id, instance_id) + self.line_of_business = line_of_business + self.platform = platform + + +class VnfInstantiation(NodeTemplateInstantiation): # pylint: disable=too-many-ancestors + """VNF instantiation class.""" + + def __init__(self, # pylint: disable=too-many-arguments + name: str, + request_id: str, + instance_id: str, + line_of_business: str, + platform: str, + vnf: Vnf) -> None: + """Class VnfInstantion object initialization. + + Args: + name (str): VNF name + request_id (str): request ID + instance_id (str): instance ID + service_instantiation ([type]): ServiceInstantiation class object + line_of_business (str): LineOfBusiness name + platform (str): Platform name + vnf (Vnf): Vnf class object + """ + super().__init__(name, request_id, instance_id, line_of_business, platform) + self.vnf = vnf + + @classmethod + def create_from_request_response(cls, request_response: dict) -> "VnfInstantiation": + """Create VNF instantiation object based on request details. + + Raises: + ResourceNotFound: Service related with given object doesn't exist + ResourceNotFound: No ServiceInstantiation related with given VNF instantiation + ResourceNotFound: VNF related with given object doesn't exist + InvalidResponse: Invalid dictionary - couldn't create VnfInstantiation object + + Returns: + VnfInstantiation: VnfInstantiation object + + """ + if request_response.get("request", {}).get("requestScope") == "vnf" and \ + request_response.get("request", {}).get("requestType") == "createInstance": + service: SdcService = None + for related_instance in request_response.get("request", {}).get("requestDetails", {})\ + .get("relatedInstanceList", []): + if related_instance.get("relatedInstance", {}).get("modelInfo", {})\ + .get("modelType") == "service": + service = SdcService(related_instance.get("relatedInstance", {})\ + .get("modelInfo", {}).get("modelName")) + if not service: + raise ResourceNotFound("No related service in Vnf instance details response") + vnf: Vnf = None + for service_vnf in service.vnfs: + if service_vnf.name == request_response.get("request", {})\ + .get("requestDetails", {}).get("modelInfo", {}).get("modelCustomizationName"): + vnf = service_vnf + if not vnf: + raise ResourceNotFound("No vnf in service vnfs list") + return cls( + name=request_response.get("request", {})\ + .get("instanceReferences", {}).get("vnfInstanceName"), + request_id=request_response.get("request", {}).get("requestId"), + instance_id=request_response.get("request", {})\ + .get("instanceReferences", {}).get("vnfInstanceId"), + line_of_business=request_response.get("request", {})\ + .get("requestDetails", {}).get("lineOfBusiness", {}).get("lineOfBusinessName"), + platform=request_response.get("request", {})\ + .get("requestDetails", {}).get("platform", {}).get("platformName"), + vnf=vnf + ) + raise InvalidResponse("Invalid vnf instantions in response dictionary's requestList") + + @classmethod + def get_by_vnf_instance_name(cls, vnf_instance_name: str) -> "VnfInstantiation": + """Get VNF instantiation request by instance name. + + Raises: + InvalidResponse: Vnf instance with given name does not contain + requestList or the requestList does not contain any details. + + Returns: + VnfInstantiation: Vnf instantiation request object + + """ + response: dict = cls.send_message_json( + "GET", + f"Check {vnf_instance_name} service instantiation status", + (f"{cls.base_url}/onap/so/infra/orchestrationRequests/{cls.api_version}?" + f"filter=vnfInstanceName:EQUALS:{vnf_instance_name}"), + headers=headers_so_creator(OnapService.headers) + ) + key = "requestList" + if not response.get(key, []): + raise InvalidResponse(f"{key} of a Vnf instance is missing.") + for details in response[key]: + return cls.create_from_request_response(details) + msg = f"No details available in response dictionary's {key}." + raise InvalidResponse(msg) + + @classmethod + def instantiate_ala_carte(cls, # pylint: disable=too-many-arguments + aai_service_instance: "ServiceInstance", + vnf_object: "Vnf", + line_of_business: str, + platform: str, + cloud_region: "CloudRegion", + tenant: "Tenant", + sdc_service: "SdcService", + vnf_instance_name: str = None, + vnf_parameters: Iterable["InstantiationParameter"] = None + ) -> "VnfInstantiation": + """Instantiate Vnf using a'la carte method. + + Args: + vnf_object (Vnf): Vnf to instantiate + line_of_business_object (LineOfBusiness): LineOfBusiness to use in instantiation request + platform_object (Platform): Platform to use in instantiation request + cloud_region (CloudRegion): Cloud region to use in instantiation request. + tenant (Tenant): Tenant to use in instnatiation request. + vnf_instance_name (str, optional): Vnf instance name. Defaults to None. + vnf_parameters (Iterable[InstantiationParameter], optional): Instantiation parameters + that are sent in the request. Defaults to None + + Returns: + VnfInstantiation: VnfInstantiation object + + """ + if vnf_instance_name is None: + vnf_instance_name = \ + f"Python_ONAP_SDK_vnf_instance_{str(uuid4())}" + response: dict = cls.send_message_json( + "POST", + (f"Instantiate {sdc_service.name} " + f"service vnf {vnf_object.name}"), + (f"{cls.base_url}/onap/so/infra/serviceInstantiation/{cls.api_version}/" + f"serviceInstances/{aai_service_instance.instance_id}/vnfs"), + data=jinja_env().get_template("instantiate_vnf_ala_carte.json.j2"). + render( + instance_name=vnf_instance_name, + vnf=vnf_object, + service=sdc_service, + cloud_region=cloud_region or \ + next(aai_service_instance.service_subscription.cloud_regions), + tenant=tenant or next(aai_service_instance.service_subscription.tenants), + line_of_business=line_of_business, + platform=platform, + service_instance=aai_service_instance, + vnf_parameters=vnf_parameters or [] + ), + headers=headers_so_creator(OnapService.headers) + ) + return VnfInstantiation( + name=vnf_instance_name, + request_id=response["requestReferences"]["requestId"], + instance_id=response["requestReferences"]["instanceId"], + line_of_business=line_of_business, + platform=platform, + vnf=vnf_object + ) + + @classmethod + def instantiate_macro(cls, # pylint: disable=too-many-arguments, too-many-locals + aai_service_instance: "ServiceInstance", + vnf_object: "Vnf", + line_of_business: str, + platform: str, + cloud_region: "CloudRegion", + tenant: "Tenant", + sdc_service: "SdcService", + vnf_instance_name: str = None, + vnf_parameters: Iterable["InstantiationParameter"] = None, + so_vnf: "SoServiceVnf" = None + ) -> "VnfInstantiation": + """Instantiate Vnf using macro method. + + Args: + aai_service_instance (ServiceInstance): Service instance associated with request + vnf_object (Vnf): Vnf to instantiate + line_of_business (LineOfBusiness): LineOfBusiness to use in instantiation request + platform (Platform): Platform to use in instantiation request + cloud_region (CloudRegion): Cloud region to use in instantiation request. + tenant (Tenant): Tenant to use in instantiation request. + vnf_instance_name (str, optional): Vnf instance name. Defaults to None. + vnf_parameters (Iterable[InstantiationParameter], optional): Instantiation parameters + that are sent in the request. Defaults to None + so_vnf (SoServiceVnf): object with vnf instance parameters + + Returns: + VnfInstantiation: VnfInstantiation object + + """ + owning_entity_id = None + project = settings.PROJECT + + for relationship in aai_service_instance.relationships: + if relationship.related_to == "owning-entity": + owning_entity_id = relationship.relationship_data.pop().get("relationship-value") + if relationship.related_to == "project": + project = relationship.relationship_data.pop().get("relationship-value") + + owning_entity = OwningEntity.get_by_owning_entity_id( + owning_entity_id=owning_entity_id) + + if so_vnf: + template_file = "instantiate_vnf_macro_so_vnf.json.j2" + if so_vnf.instance_name: + vnf_instance_name = so_vnf.instance_name + else: + template_file = "instantiate_vnf_macro.json.j2" + if vnf_instance_name is None: + vnf_instance_name = \ + f"Python_ONAP_SDK_vnf_instance_{str(uuid4())}" + + response: dict = cls.send_message_json( + "POST", + (f"Instantiate {sdc_service.name} " + f"service vnf {vnf_object.name}"), + (f"{cls.base_url}/onap/so/infra/serviceInstantiation/{cls.api_version}/" + f"serviceInstances/{aai_service_instance.instance_id}/vnfs"), + data=jinja_env().get_template(template_file).render( + instance_name=vnf_instance_name, + vnf=vnf_object, + service=sdc_service, + cloud_region=cloud_region or \ + next(aai_service_instance.service_subscription.cloud_regions), + tenant=tenant or next(aai_service_instance.service_subscription.tenants), + project=project, + owning_entity=owning_entity, + line_of_business=line_of_business, + platform=platform, + service_instance=aai_service_instance, + vnf_parameters=vnf_parameters or [], + so_vnf=so_vnf + ), + headers=headers_so_creator(OnapService.headers) + ) + + return VnfInstantiation( + name=vnf_instance_name, + request_id=response["requestReferences"]["requestId"], + instance_id=response["requestReferences"]["instanceId"], + line_of_business=line_of_business, + platform=platform, + vnf=vnf_object + ) + + @classmethod + def so_action(cls, # pylint: disable=too-many-arguments, too-many-locals + vnf_instance: "VnfInstance", + operation_type: VnfOperation, + aai_service_instance: "ServiceInstance", + line_of_business: str, + platform: str, + sdc_service: "SdcService", + so_service: "SoService" = None + ) -> "VnfInstantiation": + """Execute SO action (update or healthcheck) for selected vnf with SO macro request. + + Args: + vnf_instance (VnfInstance): vnf instance object + operation_type (VnfOperation): name of the operation to trigger + aai_service_instance (AaiService): Service Instance object from aai + line_of_business (LineOfBusiness): LineOfBusiness name to use + in instantiation request + platform (Platform): Platform name to use in instantiation request + sdc_service (SdcService): Service model information + so_service (SoService, optional): SO values to use in SO request + + Raises: + StatusError: if the provided operation is not supported + + Returns: + VnfInstantiation: VnfInstantiation object + + """ + if operation_type not in (VnfOperation.HEALTHCHECK, VnfOperation.UPDATE): + raise StatusError("Operation not supported!") + + owning_entity_id = None + project = settings.PROJECT + + for relationship in aai_service_instance.relationships: + if relationship.related_to == "owning-entity": + owning_entity_id = relationship.relationship_data.pop().get("relationship-value") + if relationship.related_to == "project": + project = relationship.relationship_data.pop().get("relationship-value") + + owning_entity = OwningEntity.get_by_owning_entity_id( + owning_entity_id=owning_entity_id) + + response: dict = cls.send_message_json( + operation_type.request_method, + (f"So Action {sdc_service.name} " + f" vnf instance {vnf_instance.vnf_id}"), + (f"{cls.base_url}/onap/so/infra/serviceInstantiation/{cls.api_version}/" + f"serviceInstances/{aai_service_instance.instance_id}/vnfs/{vnf_instance.vnf_id}" + f"{operation_type.request_suffix}"), + data=jinja_env().get_template("instantiate_multi_vnf_service_macro.json.j2").render( + sdc_service=sdc_service, + cloud_region=next(aai_service_instance.service_subscription.cloud_regions), + tenant=next(aai_service_instance.service_subscription.tenants), + customer=aai_service_instance.service_subscription.customer, + project=project, + owning_entity=owning_entity, + line_of_business=line_of_business, + platform=platform, + service_instance_name=aai_service_instance.instance_name, + so_service=so_service + ), + headers=headers_so_creator(OnapService.headers) + ) + + return VnfInstantiation( + name=vnf_instance.vnf_name, + request_id=response["requestReferences"]["requestId"], + instance_id=response["requestReferences"]["instanceId"], + line_of_business=line_of_business, + platform=platform, + vnf=vnf_instance + ) + + +class ServiceInstantiation(Instantiation): # pylint: disable=too-many-ancestors + """Service instantiation class.""" + + def __init__(self, # pylint: disable=too-many-arguments + name: str, + request_id: str, + instance_id: str, + sdc_service: "SdcService", + cloud_region: "CloudRegion", + tenant: "Tenant", + customer: "Customer", + owning_entity: OwningEntity, + project: str) -> None: + """Class ServiceInstantiation object initialization. + + Args: + name (str): service instance name + request_id (str): service instantiation request ID + instance_id (str): service instantiation ID + sdc_service (SdcService): SdcService class object + cloud_region (CloudRegion): CloudRegion class object + tenant (Tenant): Tenant class object + customer (Customer): Customer class object + owning_entity (OwningEntity): OwningEntity class object + project (str): Project name + + """ + super().__init__(name, request_id, instance_id) + self.sdc_service = sdc_service + self.cloud_region = cloud_region + self.tenant = tenant + self.customer = customer + self.owning_entity = owning_entity + self.project = project + + @classmethod + def instantiate_ala_carte(cls, # pylint: disable=too-many-arguments + sdc_service: "SdcService", + cloud_region: "CloudRegion", + tenant: "Tenant", + customer: "Customer", + owning_entity: OwningEntity, + project: str, + service_subscription: "ServiceSubscription", + service_instance_name: str = None, + enable_multicloud: bool = False) -> "ServiceInstantiation": + """Instantiate service using SO a'la carte request. + + Args: + sdc_service (SdcService): Service to instantiate + cloud_region (CloudRegion): Cloud region to use in instantiation request + tenant (Tenant): Tenant to use in instantiation request + customer (Customer): Customer to use in instantiation request + owning_entity (OwningEntity): Owning entity to use in instantiation request + project (str): Project name to use in instantiation request + service_subscription (ServiceSubscription): Customer's service subsription. + service_instance_name (str, optional): Service instance name. Defaults to None. + enable_multicloud (bool, optional): Determines if Multicloud should be enabled + for instantiation request. Defaults to False. + + Raises: + StatusError: if a service is not distributed. + + Returns: + ServiceInstantiation: instantiation request object + + """ + if not sdc_service.distributed: + msg = f"Service {sdc_service.name} is not distributed." + raise StatusError(msg) + if service_instance_name is None: + service_instance_name = f"Python_ONAP_SDK_service_instance_{str(uuid4())}" + response: dict = cls.send_message_json( + "POST", + f"Instantiate {sdc_service.name} service a'la carte", + (f"{cls.base_url}/onap/so/infra/" + f"serviceInstantiation/{cls.api_version}/serviceInstances"), + data=jinja_env().get_template("instantiate_service_ala_carte.json.j2"). + render( + sdc_service=sdc_service, + cloud_region=cloud_region, + tenant=tenant, + customer=customer, + owning_entity=owning_entity, + service_instance_name=service_instance_name, + project=project, + enable_multicloud=enable_multicloud, + service_subscription=service_subscription + ), + headers=headers_so_creator(OnapService.headers) + ) + return cls( + name=service_instance_name, + request_id=response["requestReferences"].get("requestId"), + instance_id=response["requestReferences"].get("instanceId"), + sdc_service=sdc_service, + cloud_region=cloud_region, + tenant=tenant, + customer=customer, + owning_entity=owning_entity, + project=project + ) + + # pylint: disable=too-many-arguments, too-many-locals + @classmethod + def instantiate_macro(cls, + sdc_service: "SdcService", + customer: "Customer", + owning_entity: OwningEntity, + project: str, + line_of_business: str, + platform: str, + aai_service: "AaiService" = None, + cloud_region: "CloudRegion" = None, + tenant: "Tenant" = None, + service_instance_name: str = None, + vnf_parameters: Iterable["VnfParameters"] = None, + enable_multicloud: bool = False, + so_service: "SoService" = None, + service_subscription: "ServiceSubscription" = None + ) -> "ServiceInstantiation": + """Instantiate service using SO macro request. + + Args: + sdc_service (SdcService): Service to instantiate + customer (Customer): Customer to use in instantiation request + owning_entity (OwningEntity): Owning entity to use in instantiation request + project (Project): Project name to use in instantiation request + line_of_business_object (LineOfBusiness): LineOfBusiness name to use + in instantiation request + platform_object (Platform): Platform name to use in instantiation request + aai_service (AaiService): Service object from aai sdc + cloud_region (CloudRegion): Cloud region to use in instantiation request + tenant (Tenant): Tenant to use in instantiation request + service_instance_name (str, optional): Service instance name. Defaults to None. + vnf_parameters: (Iterable[VnfParameters]): Parameters which are + going to be used for vnfs instantiation. Defaults to None. + enable_multicloud (bool, optional): Determines if Multicloud should be enabled + for instantiation request. Defaults to False. + so_service (SoService, optional): SO values to use in instantiation request + service_subscription(ServiceSubscription, optional): Customer service subscription + for the instantiated service. Required if so_service is not provided. + + Raises: + StatusError: if a service is not distributed. + + Returns: + ServiceInstantiation: instantiation request object + + """ + template_file = "instantiate_service_macro.json.j2" + if so_service: + template_file = "instantiate_multi_vnf_service_macro.json.j2" + if so_service.instance_name: + service_instance_name = so_service.instance_name + else: + if not service_subscription: + raise ParameterError("If no so_service is provided, " + "service_subscription parameter is required!") + if service_instance_name is None: + service_instance_name = f"Python_ONAP_SDK_service_instance_{str(uuid4())}" + if not sdc_service.distributed: + msg = f"Service {sdc_service.name} is not distributed." + raise StatusError(msg) + + response: dict = cls.send_message_json( + "POST", + f"Instantiate {sdc_service.name} service macro", + (f"{cls.base_url}/onap/so/infra/" + f"serviceInstantiation/{cls.api_version}/serviceInstances"), + data=jinja_env().get_template(template_file). \ + render( + so_service=so_service, + sdc_service=sdc_service, + cloud_region=cloud_region, + tenant=tenant, + customer=customer, + owning_entity=owning_entity, + project=project, + aai_service=aai_service, + line_of_business=line_of_business, + platform=platform, + service_instance_name=service_instance_name, + vnf_parameters=vnf_parameters, + enable_multicloud=enable_multicloud, + service_subscription=service_subscription + ), + headers=headers_so_creator(OnapService.headers) + ) + return cls( + name=service_instance_name, + request_id=response["requestReferences"].get("requestId"), + instance_id=response["requestReferences"].get("instanceId"), + sdc_service=sdc_service, + cloud_region=cloud_region, + tenant=tenant, + customer=customer, + owning_entity=owning_entity, + project=project + ) + + @property + def aai_service_instance(self) -> "ServiceInstance": + """Service instance associated with service instantiation request. + + Raises: + StatusError: if a service is not instantiated - + not in COMPLETE status. + APIError: A&AI resource is not created + + Returns: + ServiceInstance: ServiceInstance + + """ + required_status = self.StatusEnum.COMPLETED + if self.status != required_status: + msg = (f"Service {self.name} is not instantiated - " + f"not in {required_status} status.") + raise StatusError(msg) + try: + service_subscription: "ServiceSubscription" = \ + self.customer.get_service_subscription_by_service_type(self.sdc_service.name) + return service_subscription.get_service_instance_by_name(self.name) + except APIError as exc: + self._logger.error("A&AI resources not created properly") + raise exc + + +class NetworkInstantiation(NodeTemplateInstantiation): # pylint: disable=too-many-ancestors + """Network instantiation class.""" + + def __init__(self, # pylint: disable=too-many-arguments + name: str, + request_id: str, + instance_id: str, + line_of_business: str, + platform: str, + network: Network) -> None: + """Class NetworkInstantiation object initialization. + + Args: + name (str): VNF name + request_id (str): request ID + instance_id (str): instance ID + service_instantiation ([type]): ServiceInstantiation class object + line_of_business (str): LineOfBusiness name + platform (str): Platform name + vnf (Network): Network class object + """ + super().__init__(name, request_id, instance_id, line_of_business, platform) + self.network = network + + @classmethod + def instantiate_ala_carte(cls, # pylint: disable=too-many-arguments + aai_service_instance: "ServiceInstance", + network_object: "Network", + line_of_business: str, + platform: str, + cloud_region: "CloudRegion", + tenant: "Tenant", + network_instance_name: str = None, + subnets: Iterable[Subnet] = None) -> "NetworkInstantiation": + """Instantiate Network using a'la carte method. + + Args: + network_object (Network): Network to instantiate + line_of_business (str): LineOfBusiness name to use in instantiation request + platform (str): Platform name to use in instantiation request + cloud_region (CloudRegion): Cloud region to use in instantiation request. + tenant (Tenant): Tenant to use in instnatiation request. + network_instance_name (str, optional): Network instance name. Defaults to None. + + Returns: + NetworkInstantiation: NetworkInstantiation object + + """ + if network_instance_name is None: + network_instance_name = \ + f"Python_ONAP_SDK_network_instance_{str(uuid4())}" + NetworkPreload.upload_network_preload(network=network_object, + network_instance_name=network_instance_name, + subnets=subnets) + response: dict = cls.send_message_json( + "POST", + (f"Instantiate {aai_service_instance.sdc_service.name} " + f"service network {network_object.name}"), + (f"{cls.base_url}/onap/so/infra/serviceInstantiation/{cls.api_version}/" + f"serviceInstances/{aai_service_instance.instance_id}/networks"), + data=jinja_env().get_template("instantiate_network_ala_carte.json.j2"). + render( + instance_name=network_instance_name, + network=network_object, + service=aai_service_instance.sdc_service, + cloud_region=cloud_region or \ + next(aai_service_instance.service_subscription.cloud_regions), + tenant=tenant or next(aai_service_instance.service_subscription.tenants), + line_of_business=line_of_business, + platform=platform, + service_instance=aai_service_instance, + subnets=subnets + ), + headers=headers_so_creator(OnapService.headers) + ) + return cls( + name=network_instance_name, + request_id=response["requestReferences"]["requestId"], + instance_id=response["requestReferences"]["instanceId"], + line_of_business=line_of_business, + platform=platform, + network=network_object + ) diff --git a/src/onapsdk/so/so_db_adapter.py b/src/onapsdk/so/so_db_adapter.py new file mode 100644 index 0000000..b3694d1 --- /dev/null +++ b/src/onapsdk/so/so_db_adapter.py @@ -0,0 +1,94 @@ +"""Database Adapter module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from abc import ABC +from dataclasses import dataclass +from typing import Dict, Any + +from onapsdk.so.so_element import SoElement +from onapsdk.onap_service import OnapService +from onapsdk.utils.headers_creator import headers_so_creator, headers_so_catelog_db_creator +from onapsdk.utils.jinja import jinja_env + + +@dataclass +class IdentityService: # pylint: disable=too-many-instance-attributes + """Class to store identity service details.""" + + identity_id: str + url: str = "http://1.2.3.4:5000/v2.0" + mso_id: str = "onapsdk_user" + mso_pass: str = "mso_pass_onapsdk" + project_domain_name: str = "NULL" + user_domain_name: str = "NULL" + admin_tenant: str = "service" + member_role: str = "admin" + identity_server_type: str = "KEYSTONE" + identity_authentication_type: str = "USERNAME_PASSWORD" + hibernate_lazy_initializer = {} + server_type_as_string: str = "KEYSTONE" + tenant_metadata: bool = True + + +class SoDbAdapter(SoElement, ABC): + """DB Adapter class.""" + + @classmethod + def add_cloud_site(cls, + cloud_region_id: str, + complex_id: str, + identity_service: IdentityService, + orchestrator: str = "multicloud" + ): + """Add cloud_site data with identity_service to SO db. + + Args: + cloud_region_id (str): The id of cloud region + complex_id (str): The id of complex + identity_service (IdentityService): Identity service related to the cloud region + orchestrator (str, optional): Orchestrator type. Defaults to multicloud. + + Important: + identity_services data will be overwrite, but in the same time + cloud_sites data will not (shouldn't) be overwrite! + SOCatalogDB REST API has some limitations reported: https://jira.onap.org/browse/SO-2727 + + Return: + response object + """ + response = cls.send_message_json( + "POST", + "Create a region in SO db", + f"{cls.base_url}/cloudSite", + data=jinja_env().get_template("add_cloud_site_with_identity_service.json.j2"). + render( + cloud_region_id=cloud_region_id, + complex_id=complex_id, + orchestrator=orchestrator, + identity_service=identity_service + ), + headers=headers_so_creator(OnapService.headers) + ) + return response + @classmethod + def get_service_vnf_info(cls, identifier: str) -> Dict[Any, Any]: + """Get Service VNF and VF details. + + Returns: + The response in a dict format + + """ + url = f"{cls.base_url}/ecomp/mso/catalog/v2/serviceVnfs?serviceModelUuid={identifier}" + headers = headers_so_catelog_db_creator(OnapService.headers) + return cls.send_message_json("GET", "Get Service Details", url, headers=headers) diff --git a/src/onapsdk/so/so_element.py b/src/onapsdk/so/so_element.py new file mode 100644 index 0000000..fca6ba7 --- /dev/null +++ b/src/onapsdk/so/so_element.py @@ -0,0 +1,223 @@ +"""SO Element module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import json +from abc import ABC +from dataclasses import dataclass +from enum import Enum +from typing import Dict + +from onapsdk.configuration import settings +from onapsdk.sdc.service import Service +from onapsdk.sdc.vf import Vf +from onapsdk.onap_service import OnapService +from onapsdk.utils.headers_creator import headers_so_creator +from onapsdk.utils.jinja import jinja_env +from onapsdk.utils.mixins import WaitForFinishMixin +from onapsdk.utils.tosca_file_handler import get_modules_list_from_tosca_file +from onapsdk.utils.gui import GuiItem, GuiList + +@dataclass +class SoElement(OnapService): + """Mother Class of all SO elements.""" + + name: str = None + _server: str = "SO" + base_url = settings.SO_URL + api_version = settings.SO_API_VERSION + _status: str = None + + @property + def headers(self): + """Create headers for SO request. + + It is used as a property because x-transactionid header should be unique for each request. + """ + return headers_so_creator(OnapService.headers) + + @classmethod + def get_subscription_service_type(cls, vf_name): + """Retrieve the model info of the VFs.""" + vf_object = Vf(name=vf_name) + return vf_object.name + + @classmethod + def get_service_model_info(cls, service_name): + """Retrieve Service Model info.""" + service = Service(name=service_name) + template_service = jinja_env().get_template("service_instance_model_info.json.j2") + # Get service instance model + parsed = json.loads( + template_service.render( + model_invariant_id=service.unique_uuid, + model_name_version_id=service.identifier, + model_name=service.name, + model_version=service.version, + ) + ) + return json.dumps(parsed, indent=4) + + @classmethod + def get_vnf_model_info(cls, vf_name): + """Retrieve the model info of the VFs.""" + vf_object = Vf(name=vf_name) + template_service = jinja_env().get_template("vnf_model_info.json.j2") + parsed = json.loads( + template_service.render( + vnf_model_invariant_uuid=vf_object.unique_uuid, + vnf_model_customization_id="????", + vnf_model_version_id=vf_object.identifier, + vnf_model_name=vf_object.name, + vnf_model_version=vf_object.version, + vnf_model_instance_name=(vf_object.name + " 0"), + ) + ) + # we need also a vnf instance Name + # Usually it is found like that + # name: toto + # instance name: toto 0 + # it can be retrieved from the toscafrom onapsdk.configuration import settings + return json.dumps(parsed, indent=4) + + @classmethod + def get_vf_model_info(cls, vf_model: str) -> str: + """Retrieve the VF model info From Tosca?.""" + modules: Dict = get_modules_list_from_tosca_file(vf_model) + template_service = jinja_env().get_template("vf_model_info.json.j2") + parsed = json.loads(template_service.render(modules=modules)) + return json.dumps(parsed, indent=4) + + @classmethod + def _base_create_url(cls) -> str: + """ + Give back the base url of SO. + + Returns: + str: the base url + + """ + return "{}/onap/so/infra/serviceInstantiation/{}/serviceInstances".format( + cls.base_url, cls.api_version + ) + + @classmethod + def get_guis(cls) -> GuiItem: + """Retrieve the status of the SO GUIs. + + Only one GUI is referenced for SO: SO monitor + + Return the list of GUIs + """ + gui_url = settings.SO_MONITOR_GUI_SERVICE + so_gui_response = cls.send_message( + "GET", "Get SO GUI Status", gui_url) + guilist = GuiList([]) + guilist.add(GuiItem( + gui_url, + so_gui_response.status_code)) + return guilist + + +class OrchestrationRequest(SoElement, WaitForFinishMixin, ABC): + """Base SO orchestration request class.""" + + WAIT_FOR_SLEEP_TIME = 10 + + def __init__(self, + request_id: str) -> None: + """Instantiate object initialization. + + Initializator used by classes inherited from this abstract class. + + Args: + request_id (str): request ID + """ + super().__init__() + self.request_id: str = request_id + + class StatusEnum(Enum): + """Status enum. + + Store possible statuses for instantiation: + - IN_PROGRESS, + - FAILED, + - COMPLETE. + If instantiation has status which is not covered by these values + UNKNOWN value is used. + + """ + + IN_PROGRESS = "IN_PROGRESS" + FAILED = "FAILED" + COMPLETED = "COMPLETE" + UNKNOWN = "UNKNOWN" + + @property + def status(self) -> "StatusEnum": + """Object instantiation status. + + It's populated by call SO orchestation request endpoint. + + Returns: + StatusEnum: Instantiation status. + + """ + response: dict = self.send_message_json( + "GET", + f"Check {self.request_id} orchestration request status", + (f"{self.base_url}/onap/so/infra/" + f"orchestrationRequests/{self.api_version}/{self.request_id}"), + headers=headers_so_creator(OnapService.headers) + ) + try: + return self.StatusEnum(response["request"]["requestStatus"]["requestState"]) + except (KeyError, ValueError): + self._logger.exception("Invalid status") + return self.StatusEnum.UNKNOWN + + @property + def finished(self) -> bool: + """Store an information if instantion is finished or not. + + Instantiation is finished if it's status is COMPLETED or FAILED. + + Returns: + bool: True if instantiation is finished, False otherwise. + + """ + return self.status in [self.StatusEnum.COMPLETED, self.StatusEnum.FAILED] + + @property + def completed(self) -> bool: + """Store an information if instantion is completed or not. + + Instantiation is completed if it's status is COMPLETED. + + Returns: + bool: True if instantiation is completed, False otherwise. + + """ + return self.finished and self.status == self.StatusEnum.COMPLETED + + @property + def failed(self) -> bool: + """Store an information if instantion is failed or not. + + Instantiation is failed if it's status is FAILED. + + Returns: + bool: True if instantiation is failed, False otherwise. + + """ + return self.finished and self.status == self.StatusEnum.FAILED diff --git a/src/onapsdk/so/templates/add_cloud_site_with_identity_service.json.j2 b/src/onapsdk/so/templates/add_cloud_site_with_identity_service.json.j2 new file mode 100644 index 0000000..31599f5 --- /dev/null +++ b/src/onapsdk/so/templates/add_cloud_site_with_identity_service.json.j2 @@ -0,0 +1,22 @@ +{ + "id": "{{ cloud_region_id }}", + "region_id": "{{ cloud_region_id }}", + "aic_version": "2.5", + "clli": "{{ complex_id }}", + "orchestrator": "{{ orchestrator }}", + "identityService": { + "id": "{{ identity_service.identity_id }}", + "identityServerTypeAsString": "{{ identity_service.server_type_as_string }}", + "hibernateLazyInitializer": {{ identity_service.hibernate_lazy_initializer }}, + "identity_url": "{{ identity_service.url }}", + "mso_id": "{{ identity_service.mso_id }}", + "mso_pass": "{{ identity_service.mso_pass }}", + "project_domain_name": "{{ identity_service.project_domain_name }}", + "user_domain_name": "{{ identity_service.user_domain_name }}", + "admin_tenant": "{{ identity_service.admin_tenant }}", + "member_role": "{{ identity_service.member_role }}", + "tenant_metadata": "{{ identity_service.tenant_metadata }}", + "identity_server_type": "{{ identity_service.identity_server_type }}", + "identity_authentication_type": "{{ identity_service.identity_authentication_type }}" + } +}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/deletion_network.json.j2 b/src/onapsdk/so/templates/deletion_network.json.j2 new file mode 100644 index 0000000..93f0990 --- /dev/null +++ b/src/onapsdk/so/templates/deletion_network.json.j2 @@ -0,0 +1,22 @@ +{ + "requestDetails": { + "requestInfo": { + "source": "VID", + "requestorId": "demo" + }, + "modelInfo": { + "modelType": "network" + }, + "requestParameters": { + "testApi": "GR_API", + "aLaCarte": {{ a_la_carte | tojson }} + }, + {# the code below is needed to be refactored #} + {# https://gitlab.com/Orange-OpenSource/lfn/onap/python-onapsdk/-/issues/133 #} + "cloudConfiguration": { + "cloudOwner": "{{ network_instance.service_instance.service_subscription.cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ network_instance.service_instance.service_subscription.cloud_region.cloud_region_id }}", + "tenantId": "{{ network_instance.service_instance.service_subscription.tenant.tenant_id }}" + } + } +}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/deletion_service.json.j2 b/src/onapsdk/so/templates/deletion_service.json.j2 new file mode 100644 index 0000000..1244e97 --- /dev/null +++ b/src/onapsdk/so/templates/deletion_service.json.j2 @@ -0,0 +1,26 @@ +{ + "requestDetails": { + "requestInfo": { + "source": "VID", + "requestorId": "demo" + }, + "modelInfo": { + "modelType": "service", + "modelName": "{{ service_instance.sdc_service.name }}", + "modelInvariantId": "{{ service_instance.sdc_service.unique_uuid }}", + "modelVersion": "1.0", + "modelVersionId": "{{ service_instance.sdc_service.identifier }}" + }, + "requestParameters": { + "testApi": "GR_API", + "aLaCarte": {{ a_la_carte | tojson }} + }{% if service_instance.sdc_service.has_vnfs %}, + {# the code below is needed to be refactored #} + {# https://gitlab.com/Orange-OpenSource/lfn/onap/python-onapsdk/-/issues/133 #} + "cloudConfiguration": { + "cloudOwner": "{{ service_instance.service_subscription.cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ service_instance.service_subscription.cloud_region.cloud_region_id }}", + "tenantId": "{{ service_instance.service_subscription.tenant.tenant_id }}" + }{% endif %} + } +}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/deletion_vf_module.json.j2 b/src/onapsdk/so/templates/deletion_vf_module.json.j2 new file mode 100644 index 0000000..8f83717 --- /dev/null +++ b/src/onapsdk/so/templates/deletion_vf_module.json.j2 @@ -0,0 +1,27 @@ +{ + "requestDetails": { + "requestInfo": { + "source": "VID", + "requestorId": "demo" + }, + "modelInfo": { + "modelType": "vfModule", + "modelInvariantId": "{{ vf_module_instance.model_invariant_id }}", + "modelVersionId": "{{ vf_module_instance.model_version_id }}", + "modelName": "{{ vf_module_instance.vf_module_name }}", + "modelVersion": "{{ vf_module_instance.resource_version }}", + "modelCustomizationId": "{{ vf_module_instance.model_customization_id }}" + }, + "requestParameters": { + "testApi": "GR_API", + "aLaCarte": {{ a_la_carte | tojson }} + }, + {# the code below is needed to be refactored #} + {# https://gitlab.com/Orange-OpenSource/lfn/onap/python-onapsdk/-/issues/133 #} + "cloudConfiguration": { + "cloudOwner": "{{ vf_module_instance.vnf_instance.service_instance.service_subscription.cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ vf_module_instance.vnf_instance.service_instance.service_subscription.cloud_region.cloud_region_id }}", + "tenantId": "{{ vf_module_instance.vnf_instance.service_instance.service_subscription.tenant.tenant_id }}" + } + } +}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/deletion_vnf.json.j2 b/src/onapsdk/so/templates/deletion_vnf.json.j2 new file mode 100644 index 0000000..fb640ec --- /dev/null +++ b/src/onapsdk/so/templates/deletion_vnf.json.j2 @@ -0,0 +1,28 @@ +{ + "requestDetails": { + "requestInfo": { + "source": "VID", + "requestorId": "demo" + }, + "modelInfo": { + "modelType": "vnf", + "modelName": "{{ vnf_instance.vnf.model_name }}", + "modelInvariantId": "{{ vnf_instance.vnf.model_invariant_id }}", + "modelVersion": "{{ vnf_instance.vnf.model_version }}", + "modelVersionId": "{{ vnf_instance.vnf.model_version_id }}", + "modelCustomizationId": "{{ vnf_instance.vnf.model_customization_id }}", + "modelCustomizationName": "{{ vnf_instance.vnf.name }}" + }, + "requestParameters": { + "testApi": "GR_API", + "aLaCarte": {{ a_la_carte | tojson }} + }, + {# the code below is needed to be refactored #} + {# https://gitlab.com/Orange-OpenSource/lfn/onap/python-onapsdk/-/issues/133 #} + "cloudConfiguration": { + "cloudOwner": "{{ vnf_instance.service_instance.service_subscription.cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ vnf_instance.service_instance.service_subscription.cloud_region.cloud_region_id }}", + "tenantId": "{{ vnf_instance.service_instance.service_subscription.tenant.tenant_id }}" + } + } +}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/instantiate_multi_vnf_service_macro.json.j2 b/src/onapsdk/so/templates/instantiate_multi_vnf_service_macro.json.j2 new file mode 100644 index 0000000..32e1b68 --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_multi_vnf_service_macro.json.j2 @@ -0,0 +1,121 @@ +{% extends "instantiate_service_macro.json.j2" %} + +{% block subscriptionServiceType %} + "subscriptionServiceType": "{{ so_service.subscription_service_type }}", +{% endblock %} + +{% block pnfs %} + {% if so_service.pnfs %} + "pnfs": [ + {% for pnf in so_service.pnfs %} + { + "modelInfo":{ + {% for sdc_pnf in sdc_service.pnfs %} + {% if sdc_pnf.model_name == pnf.model_name %} + "modelCustomizationName":"{{ sdc_pnf.name }}", + "modelCustomizationId":"{{ sdc_pnf.model_customization_id }}", + "modelInvariantId":"{{ sdc_service.unique_uuid }}", + "modelVersionId":"{{ sdc_service.identifier }}", + "modelName":"{{ sdc_service.name }}", + "modelType":"pnf", + "modelVersion":"{{ sdc_pnf.model_version }}" + {% endif %} + {% endfor %} + }, + "platform":{ + "platformName":"{{ platform }}" + }, + "lineOfBusiness":{ + "lineOfBusinessName":"{{ line_of_business }}" + }, + "productFamilyId":"{{ aai_service.service_id }}", + "instanceParams":[], + {% if pnf.processing_priority %} + "processingPriority": "{{ pnf.processing_priority }}", + {% endif %} + "instanceName": "{{ pnf.instance_name }}" + }{% if not loop.last %},{% endif %} + {% endfor %} + ]{% if so_service.vnfs %},{% endif %} + {% endif %} +{% endblock %} + +{% block vnfs %} + {% if so_service.vnfs %} + "vnfs": [ + {% for vnf in so_service.vnfs %} + { + "modelInfo": { + {% for sdc_vnf in sdc_service.vnfs %} + {% if sdc_vnf.model_name == vnf.model_name %} + "modelName": "{{ sdc_vnf.model_name }}", + "modelVersionId": "{{ sdc_vnf.model_version_id }}", + "modelInvariantUuid": "{{ sdc_vnf.model_invariant_uuid }}", + "modelVersion": "{{ sdc_vnf.model_version }}", + "modelCustomizationId": "{{ sdc_vnf.model_customization_id }}", + "modelInstanceName": "{{ sdc_vnf.model_name }}" + {% endif %} + {% endfor %} + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "platform": { + "platformName": "{{ platform }}" + }, + "lineOfBusiness": { + "lineOfBusinessName": "{{ line_of_business }}" + }, + "productFamilyId": "1234", + "instanceName": "{{ vnf.instance_name }}", + "instanceParams": [ + { + {% for key, value in vnf.parameters.items() %} + "{{ key }}": "{{ value }}"{% if not loop.last %},{% endif %} + {% endfor %} + } + ], + {% if vnf.processing_priority %} + "processingPriority": "{{ vnf.processing_priority }}", + {% endif %} + "vfModules": [ + {% for vf_module in vnf.vf_modules %} + { + "modelInfo": { + {% for sdc_vnf in sdc_service.vnfs %} + {% if sdc_vnf.model_name == vnf.model_name %} + {% for sdc_vf_module in sdc_vnf.vf_modules %} + {% set mylist = sdc_vf_module.name.split('..') %} + {% set item = mylist|length-2 %} + {% if vf_module.model_name == mylist[item] %} + "modelName": "{{ sdc_vf_module.model_name }}", + "modelVersionId": "{{ sdc_vf_module.model_version_id }}", + "modelInvariantUuid": "{{ sdc_vf_module.model_invariant_uuid }}", + "modelVersion": "{{ sdc_vf_module.model_version }}", + "modelCustomizationId": "{{ sdc_vf_module.model_customization_id }}" + {% endif %} + {% endfor %} + {% endif %} + {% endfor %} + }, + "instanceName": "{{ vf_module.instance_name }}", + {% if vf_module.processing_priority %} + "processingPriority": "{{ vf_module.processing_priority }}", + {% endif %} + "instanceParams": [ + { + {% for key, value in vf_module.parameters.items() %} + "{{ key }}": "{{ value }}"{% if not loop.last %},{% endif %} + {% endfor %} + } + ] + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + {% endif %} +{% endblock %} diff --git a/src/onapsdk/so/templates/instantiate_network_ala_carte.json.j2 b/src/onapsdk/so/templates/instantiate_network_ala_carte.json.j2 new file mode 100644 index 0000000..90b3c16 --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_network_ala_carte.json.j2 @@ -0,0 +1,10 @@ +{% extends "instantiate_network_vnf_ala_carte_base.json.j2" %} +{% block model_info %} + "modelType": "network", + "modelInvariantId": "{{ network.model_invariant_id }}", + "modelVersionId": "{{ network.model_version_id }}", + "modelName": "{{ network.model_name }}", + "modelVersion": "{{ network.model_version }}", + "modelCustomizationId": "{{ network.model_customization_id }}", + "modelCustomizationName": "{{ network.name }}" +{% endblock %}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/instantiate_network_vnf_ala_carte_base.json.j2 b/src/onapsdk/so/templates/instantiate_network_vnf_ala_carte_base.json.j2 new file mode 100644 index 0000000..757cdd8 --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_network_vnf_ala_carte_base.json.j2 @@ -0,0 +1,44 @@ +{ + "requestDetails": { + "requestInfo": { + "instanceName": "{{ instance_name }}", + "source": "VID", + "suppressRollback": false, + "requestorId": "test", + "productFamilyId": "{{ service_instance.model_invariant_id }}" + }, + "modelInfo": { + {% block model_info %}{% endblock %} + }, + "requestParameters": { + "userParams": [ + {% block user_params %}{% endblock %} + ], + "aLaCarte": true, + "testApi": "GR_API" + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "lineOfBusiness": { + "lineOfBusinessName": "{{ line_of_business }}" + }, + "platform": { + "platformName": "{{ platform }}" + }, + "relatedInstanceList": [{ + "relatedInstance": { + "instanceId": "{{ service_instance.instance_id }}", + "modelInfo": { + "modelType": "service", + "modelName": "{{ service.name }}", + "modelInvariantId": "{{ service.unique_uuid }}", + "modelVersion": "1.0", + "modelVersionId": "{{ service.identifier }}" + } + } + }] + } +}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/instantiate_service_ala_carte.json.j2 b/src/onapsdk/so/templates/instantiate_service_ala_carte.json.j2 new file mode 100644 index 0000000..4954cde --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_service_ala_carte.json.j2 @@ -0,0 +1,45 @@ +{ + "requestDetails": { + "requestInfo": { + "instanceName": "{{ service_instance_name }}", + "source": "VID", + "suppressRollback": false, + "requestorId": "demo" + }, + "modelInfo": { + "modelType": "service", + "modelInvariantId": "{{ sdc_service.unique_uuid }}", + "modelVersionId": "{{ sdc_service.identifier }}", + "modelName": "{{ sdc_service.name }}", + "modelVersion": "1.0" + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "requestParameters": { + "userParams": [ + {% if enable_multicloud %} + { + "name":"orchestrator", + "value":"multicloud" + } + {% endif %} + ], + "testApi": "GR_API", + "subscriptionServiceType": "{{ service_subscription.service_type }}", + "aLaCarte": true + }, + "subscriberInfo": { + "globalSubscriberId": "{{ customer.global_customer_id }}" + }, + "project": { + "projectName": "{{ project }}" + }, + "owningEntity": { + "owningEntityId": "{{ owning_entity.owning_entity_id }}", + "owningEntityName": "{{ owning_entity.name }}" + } + } +}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/instantiate_service_macro.json.j2 b/src/onapsdk/so/templates/instantiate_service_macro.json.j2 new file mode 100644 index 0000000..43b92ee --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_service_macro.json.j2 @@ -0,0 +1,173 @@ +{ + "requestDetails": { + "requestInfo": { + "suppressRollback": false, + {% if aai_service %} + "productFamilyId":"{{ aai_service.service_id }}", + {% else %} + "productFamilyId": "1234", + {% endif %} + "requestorId": "demo", + "instanceName": "{{ service_instance_name }}", + "source": "VID" + }, + "modelInfo": { + "modelType": "service", + "modelInvariantId": "{{ sdc_service.unique_uuid }}", + "modelVersionId": "{{ sdc_service.identifier }}", + "modelName": "{{ sdc_service.name }}", + "modelVersion": "1.0" + }, + {% if sdc_service.has_vnfs %} + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + {% endif %} + "subscriberInfo": { + "globalSubscriberId": "{{ customer.global_customer_id }}" + }, + "requestParameters": { + {% block subscriptionServiceType %} + "subscriptionServiceType": "{{ service_subscription.service_type }}", + {% endblock %} + "userParams": [ + { + "Homing_Solution": "none" + }, + {% if enable_multicloud %} + { + "name":"orchestrator", + "value":"multicloud" + }, + {% endif %} + { + "service": { + "instanceParams": [], + "instanceName": "{{ service_instance_name }}", + "resources": { + {% block pnfs %} + {% if sdc_service.pnfs %} + "pnfs":[ + {% for pnf in sdc_service.pnfs %} + { + "modelInfo":{ + "modelCustomizationName":"{{ pnf.name }}", + "modelCustomizationId":"{{ pnf.model_customization_id }}", + "modelInvariantId":"{{ sdc_service.unique_uuid }}", + "modelVersionId":"{{ sdc_service.identifier }}", + "modelName":"{{ sdc_service.name }}", + "modelType":"pnf", + "modelVersion":"1.0" + }, + "platform":{ + "platformName":"{{ platform }}" + }, + "lineOfBusiness":{ + "lineOfBusinessName":"{{ line_of_business }}" + }, + "productFamilyId":"{{ aai_service.service_id }}", + "instanceParams":[], + "instanceName":"{{ service_instance_name }}" + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + {% if sdc_service.vnfs %},{% endif %} + {% endif %} + {% endblock %} + {% block vnfs %} + {% if sdc_service.vnfs %} + "vnfs": [ + {% for vnf in sdc_service.vnfs %} + { + "modelInfo": { + "modelName": "{{ vnf.model_name }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelInvariantUuid": "{{ vnf.model_invariant_id }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelInstanceName": "{{ vnf.model_name }}" + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "platform": { + "platformName": "{{ platform }}" + }, + "lineOfBusiness": { + "lineOfBusinessName": "{{ line_of_business }}" + }, + "productFamilyId": "1234", + "instanceName": "{{ vnf.model_name }}", + "instanceParams": [ + { + {% for vnf_parameter in vnf_parameters %} + {% if vnf_parameter.name == vnf.model_name %} + {% for parameter in vnf_parameter.vnf_parameters %} + "{{ parameter.name }}": "{{ parameter.value }}"{% if not loop.last %},{% endif %} + {% endfor %} + {% endif %} + {% endfor %} + } + ], + "vfModules": [ + {% for vf_module in vnf.vf_modules %} + { + "modelInfo": { + "modelName": "{{ vf_module.model_name }}", + "modelVersionId": "{{ vf_module.model_version_id }}", + "modelInvariantUuid": "{{ vf_module.model_invariant_uuid }}", + "modelVersion": "{{ vf_module.model_version }}", + "modelCustomizationId": "{{ vf_module.model_customization_id }}" + }, + "instanceName": "{{ service_instance_name }}_{{ vf_module.name }}", + "instanceParams": [ + { + {% for vnf_parameter in vnf_parameters %} + {% if vnf_parameter.name == vnf.model_name %} + {% set mylist = vf_module.name.split('..') %} + {% set item = mylist|length-2 %} + {% for vf_module_parameter in vnf_parameter.vfmodule_parameters %} + {% if vf_module_parameter.name == mylist[item] %} + {% for parameter in vf_module_parameter.vfmodule_parameters %} + "{{ parameter.name }}": "{{ parameter.value }}"{% if not loop.last %},{% endif %} + {% endfor %} + {% endif %} + {% endfor %} + {% endif %} + {% endfor %} + } + ] + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + {% endif %} + {% endblock %} + }, + "modelInfo": { + "modelVersion": "1.0", + "modelVersionId": "{{ sdc_service.identifier }}", + "modelInvariantId": "{{ sdc_service.unique_uuid }}", + "modelName": "{{ sdc_service.name }}", + "modelType": "service" + } + } + } + ], + "aLaCarte": false + }, + "project": { + "projectName": "{{ project }}" + }, + "owningEntity": { + "owningEntityId": "{{ owning_entity.owning_entity_id }}", + "owningEntityName": "{{ owning_entity.name }}" + } + } +} diff --git a/src/onapsdk/so/templates/instantiate_vf_module_ala_carte.json.j2 b/src/onapsdk/so/templates/instantiate_vf_module_ala_carte.json.j2 new file mode 100644 index 0000000..0738379 --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_vf_module_ala_carte.json.j2 @@ -0,0 +1,66 @@ +{ + "requestDetails": { + "requestInfo": + { + "instanceName": "{{ vf_module_instance_name }}", + "source": "VID", + "suppressRollback": false, + "requestorId": "test" + }, + "modelInfo": { + "modelType": "vfModule", + "modelInvariantId": "{{ vf_module.model_invariant_uuid }}", + "modelVersionId": "{{ vf_module.model_version_id }}", + "modelName": "{{ vf_module.model_name }}", + "modelVersion": "{{ vf_module.model_version }}", + "modelCustomizationId": "{{ vf_module.model_customization_id }}", + "modelCustomizationName": "{{ vf_module.model_name }}" + }, + "requestParameters": { + "userParams": [ + {% for parameter in vf_module_parameters %} + { + "name": "{{ parameter.name }}", + "value": "{{ parameter.value }}" + }{% if not loop.last %},{% endif %} + {% endfor %} + ], + "testApi": "GR_API", + "usePreload": true, + "aLaCarte": true + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "{{ vnf_instance.service_instance.instance_id }}", + "modelInfo": { + "modelType": "service", + "modelName": "{{ service.name }}", + "modelInvariantId": "{{ service.unique_uuid }}", + "modelVersion": "1.0", + "modelVersionId": "{{ service.identifier }}" + } + } + }, + { + "relatedInstance": { + "instanceId": "{{ vnf_instance.vnf_id }}", + "modelInfo": { + "modelType": "vnf", + "modelName": "{{ vnf_instance.vnf.model_name }}", + "modelInvariantId": "{{ vnf_instance.vnf.model_invariant_id }}", + "modelVersion": "{{ vnf_instance.vnf.model_version }}", + "modelVersionId": "{{ vnf_instance.vnf.model_version_id }}", + "modelCustomizationId": "{{ vnf_instance.vnf.model_customization_id }}", + "modelCustomizationName": "{{ vnf_instance.vnf.name }}" + } + } + } + ] + } +} diff --git a/src/onapsdk/so/templates/instantiate_vnf_ala_carte.json.j2 b/src/onapsdk/so/templates/instantiate_vnf_ala_carte.json.j2 new file mode 100644 index 0000000..9fbf989 --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_vnf_ala_carte.json.j2 @@ -0,0 +1,18 @@ +{% extends "instantiate_network_vnf_ala_carte_base.json.j2" %} +{% block model_info %} + "modelType": "vnf", + "modelInvariantId": "{{ vnf.model_invariant_id }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelName": "{{ vnf.model_name }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelCustomizationName": "{{ vnf.name }}" +{% endblock %} +{% block user_params %} +{% for parameter in vnf_parameters %} +{ + "name": "{{ parameter.name }}", + "value": "{{ parameter.value }}" +}{% if not loop.last %},{% endif %} +{% endfor %} +{% endblock %}
\ No newline at end of file diff --git a/src/onapsdk/so/templates/instantiate_vnf_macro.json.j2 b/src/onapsdk/so/templates/instantiate_vnf_macro.json.j2 new file mode 100644 index 0000000..2d7aeee --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_vnf_macro.json.j2 @@ -0,0 +1,153 @@ +{ + "requestDetails": { + "requestInfo": { + "instanceName": "{{ service_instance.instance_name }}", + "source": "VID", + "suppressRollback": false, + "requestorId": "demo", + "productFamilyId": "1234" + }, + "modelInfo": { + "modelType": "vnf", + "modelInvariantId": "{{ vnf.model_invariant_id }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelName": "{{ vnf.model_name }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelInstanceName": "{{ vnf.name }}" + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "platform": { + "platformName": "{{ platform }}" + }, + "lineOfBusiness": { + "lineOfBusinessName": "{{ line_of_business }}" + }, + "subscriberInfo": { + "globalSubscriberId": "{{ service_instance.service_subscription.customer.global_customer_id }}" + }, + "requestParameters": { + {% block subscriptionServiceType %} + "subscriptionServiceType": "{{ service.name }}", + {% endblock %} + "userParams": [ + { + "Homing_Solution": "none" + }, + { + "service": { + "instanceParams": [], + "resources": { + {% block vnfs %} + "vnfs": [ + { + "modelInfo": { + "modelName": "{{ vnf.model_name }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelInvariantUuid": "{{ vnf.model_invariant_id }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelInstanceName": "{{ vnf.name }}" + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "platform": { + "platformName": "{{ platform }}" + }, + "lineOfBusiness": { + "lineOfBusinessName": "{{ line_of_business }}" + }, + "productFamilyId": "1234", + "instanceName": "{{ instance_name }}", + "instanceParams": [ + { + {% for vnf_parameter in vnf_parameters %} + {% if vnf_parameter.name == vnf.model_name %} + {% for parameter in vnf_parameter.vnf_parameters %} + "{{ parameter.name }}": "{{ parameter.value }}"{% if not loop.last %},{% endif %} + {% endfor %} + {% endif %} + {% endfor %} + } + ], + "vfModules": [ + {% for vf_module in vnf.vf_modules %} + + { + "modelInfo": { + "modelName": "{{ vf_module.model_name }}", + "modelVersionId": "{{ vf_module.model_version_id }}", + "modelInvariantUuid": "{{ vf_module.model_invariant_uuid }}", + "modelVersion": "{{ vf_module.model_version }}", + "modelCustomizationId": "{{ vf_module.model_customization_id }}" + }, + "instanceName": "{{instance_name}}_{{ vf_module.name }}", + "instanceParams": [ + { + {% for vnf_parameter in vnf_parameters %} + {% if vnf_parameter.name == vnf.model_name %} + {% set mylist = vf_module.name.split('..') %} + {% set item = mylist|length-2 %} + {% for vf_module_parameter in vnf_parameter.vfmodule_parameters %} + {% if vf_module_parameter.name == mylist[item] %} + {% for parameter in vf_module_parameter.vfmodule_parameters %} + "{{ parameter.name }}": "{{ parameter.value }}"{% if not loop.last %},{% endif %} + {% endfor %} + {% endif %} + {% endfor %} + {% endif %} + {% endfor %} + } + ] + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + } + ] + {% endblock %} + }, + "modelInfo": { + "modelType": "vnf", + "modelInvariantId": "{{ vnf.model_invariant_id }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelName": "{{ vnf.model_name }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelCustomizationName": "{{ vnf.name }}" + } + } + } + ], + "aLaCarte": false + }, + "project": { + "projectName": "{{ project }}" + }, + "owningEntity": { + "owningEntityId": "{{ owning_entity.owning_entity_id }}", + "owningEntityName": "{{ owning_entity.name }}" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "{{ service_instance.instance_id }}", + "modelInfo": { + "modelType": "service", + "modelInvariantId": "{{ service.unique_uuid }}", + "modelVersionId": "{{ service.identifier }}", + "modelName": "{{ service.name }}", + "modelVersion": "1.0" + } + } + } + ] + }, + "serviceInstanceId": "{{ service_instance.instance_id }}" +} diff --git a/src/onapsdk/so/templates/instantiate_vnf_macro_so_vnf.json.j2 b/src/onapsdk/so/templates/instantiate_vnf_macro_so_vnf.json.j2 new file mode 100644 index 0000000..c7f4356 --- /dev/null +++ b/src/onapsdk/so/templates/instantiate_vnf_macro_so_vnf.json.j2 @@ -0,0 +1,151 @@ +{ + "requestDetails": { + "requestInfo": { + "instanceName": "{{ service_instance.instance_name }}", + "source": "VID", + "suppressRollback": false, + "requestorId": "demo", + "productFamilyId": "1234" + }, + "modelInfo": { + "modelType": "vnf", + "modelInvariantId": "{{ vnf.model_invariant_id }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelName": "{{ vnf.model_name }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelInstanceName": "{{ vnf.name }}" + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "platform": { + "platformName": "{{ platform }}" + }, + "lineOfBusiness": { + "lineOfBusinessName": "{{ line_of_business }}" + }, + "subscriberInfo": { + "globalSubscriberId": "{{ service_instance.service_subscription.customer.global_customer_id }}" + }, + "requestParameters": { + {% block subscriptionServiceType %} + "subscriptionServiceType": "{{ service.name }}", + {% endblock %} + "userParams": [ + { + "Homing_Solution": "none" + }, + { + "service": { + "instanceParams": [], + "resources": { + {% block vnfs %} + "vnfs": [ + { + "modelInfo": { + "modelName": "{{ vnf.model_name }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelInvariantUuid": "{{ vnf.model_invariant_id }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelInstanceName": "{{ vnf.name }}" + }, + "cloudConfiguration": { + "tenantId": "{{ tenant.tenant_id }}", + "cloudOwner": "{{ cloud_region.cloud_owner }}", + "lcpCloudRegionId": "{{ cloud_region.cloud_region_id }}" + }, + "platform": { + "platformName": "{{ platform }}" + }, + "lineOfBusiness": { + "lineOfBusinessName": "{{ line_of_business }}" + }, + "productFamilyId": "1234", + "instanceName": "{{ instance_name }}", + "instanceParams": [ + { + {% for key, value in so_vnf.parameters.items() %} + "{{ key }}": "{{ value }}"{% if not loop.last %},{% endif %} + {% endfor %} + } + ], + "vfModules": [ + {% for vf_module in so_vnf.vf_modules %} + { + "modelInfo": { + + {% if vnf.model_name == so_vnf.model_name %} + {% for sdc_vf_module in vnf.vf_modules %} + {% set mylist = sdc_vf_module.name.split('..') %} + {% set item = mylist|length-2 %} + {% if vf_module.model_name == mylist[item] %} + "modelName": "{{ sdc_vf_module.model_name }}", + "modelVersionId": "{{ sdc_vf_module.model_version_id}}", + "modelInvariantUuid": "{{ sdc_vf_module.model_invariant_uuid }}", + "modelVersion": "{{ sdc_vf_module.model_version }}", + "modelCustomizationId": "{{ sdc_vf_module.model_customization_id }}" + {% endif %} + {% endfor %} + {% endif %} + + }, + "instanceName": "{{ vf_module.instance_name }}", + {% if vf_module.processing_priority %} + "processingPriority": "{{ vf_module.processing_priority }}", + {% endif %} + "instanceParams": [ + { + {% for key, value in vf_module.parameters.items() %} + "{{ key }}": "{{ value }}"{% if not loop.last %},{% endif %} + {% endfor %} + } + ] + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + } + ] + {% endblock %} + }, + "modelInfo": { + "modelType": "vnf", + "modelInvariantId": "{{ vnf.model_invariant_id }}", + "modelVersionId": "{{ vnf.model_version_id }}", + "modelName": "{{ vnf.model_name }}", + "modelVersion": "{{ vnf.model_version }}", + "modelCustomizationId": "{{ vnf.model_customization_id }}", + "modelCustomizationName": "{{ vnf.name }}" + } + } + } + ], + "aLaCarte": false + }, + "project": { + "projectName": "{{ project }}" + }, + "owningEntity": { + "owningEntityId": "{{ owning_entity.owning_entity_id }}", + "owningEntityName": "{{ owning_entity.name }}" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "{{ service_instance.instance_id }}", + "modelInfo": { + "modelType": "service", + "modelInvariantId": "{{ service.unique_uuid }}", + "modelVersionId": "{{ service.identifier }}", + "modelName": "{{ service.name }}", + "modelVersion": "1.0" + } + } + } + ] + }, + "serviceInstanceId": "{{ service_instance.instance_id }}" +} diff --git a/src/onapsdk/so/templates/service_instance_model_info.json.j2 b/src/onapsdk/so/templates/service_instance_model_info.json.j2 new file mode 100644 index 0000000..fc66de4 --- /dev/null +++ b/src/onapsdk/so/templates/service_instance_model_info.json.j2 @@ -0,0 +1,7 @@ +{ + "modelType": "service", + "modelInvariantId": "{{ model_invariant_id }}", + "modelName": "{{ model_name }}", + "modelVersion": "{{ model_version }}", + "modelVersionId": "{{ model_name_version_id }}" +} diff --git a/src/onapsdk/so/templates/vf_model_info.json.j2 b/src/onapsdk/so/templates/vf_model_info.json.j2 new file mode 100644 index 0000000..4b40898 --- /dev/null +++ b/src/onapsdk/so/templates/vf_model_info.json.j2 @@ -0,0 +1,15 @@ +[ +{% for _, module in modules.items() %} + { + "modelInfo": { + "modelName": "{{ module["metadata"]["vfModuleModelName"] }}", + "modelVersion": "{{ module.metadata.vfModuleModelVersion }}", + "modelVersionId": "{{ module.metadata.vfModuleModelUUID }}", + "modelInvariantUuid": "{{ module.metadata.vfModuleInvariantUUID }}", + "modelCustomizationId": "{{ module.metadata.vfModuleModelCustomizationUUID }}" + }, + "instanceName": "{{ module.metadata.vfModuleModelName }}", + "instanceParams": [] + }{% if not loop.last %},{% endif %} +{% endfor %} +]
\ No newline at end of file diff --git a/src/onapsdk/so/templates/vnf_model_info.json.j2 b/src/onapsdk/so/templates/vnf_model_info.json.j2 new file mode 100644 index 0000000..ecc788b --- /dev/null +++ b/src/onapsdk/so/templates/vnf_model_info.json.j2 @@ -0,0 +1,9 @@ +{ + "modelType": "vnf", + "modelName": "{{ vnf_model_name }}", + "modelVersion": "{{ vnf_model_version }}", + "modelVersionId": "{{ vnf_model_version_id }}", + "modelInvariantUuid": "{{ vnf_model_invariant_uuid }}", + "modelCustomizationId": "{{ vnf_model_customization_id }}", + "modelInstanceName": "{{ vnf_model_instance_name }}" +} |