aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSreeja Gattagouni <sg00744975@techmahindra.com>2023-05-19 07:20:37 +0000
committerLukasz Rajewski <lukasz.rajewski@t-mobile.pl>2023-05-25 10:34:45 +0000
commit3860bac3bf74c485eebb0327e9125d6b45685278 (patch)
treefdce842bbf15f9ffcb4b549cb46b06515abdf4cb
parent676cfced1bf3b1602e99288f20ae1d3e91031f49 (diff)
Addition-Deletion PNF Support in Automation(Macro-Flow)
-PNF Additon Support -PNF Deletion Support Issue-ID: INT-2211 Change-ID:I73f97f986a817d423f92f8d925dcd0947b8a2525 Signed-off-by: Sreeja Gattagouni <sg00744975@techmahindra.com>
-rw-r--r--integration_tests/test_07_instantiation.py170
-rw-r--r--src/onapsdk/so/instantiation.py186
-rwxr-xr-xsrc/onapsdk/so/templates/instantiate_pnf_macro.json.j2121
-rwxr-xr-xsrc/onapsdk/so/templates/instantiate_pnf_macro_so_pnf.json.j2117
-rw-r--r--tests/test_so_instantiation.py174
5 files changed, 765 insertions, 3 deletions
diff --git a/integration_tests/test_07_instantiation.py b/integration_tests/test_07_instantiation.py
index c6cbc85..8fbb22d 100644
--- a/integration_tests/test_07_instantiation.py
+++ b/integration_tests/test_07_instantiation.py
@@ -21,10 +21,10 @@ from onapsdk.exceptions import StatusError
from onapsdk.aai.business import Customer, ServiceInstance
from onapsdk.aai.cloud_infrastructure import CloudRegion
from onapsdk.configuration import settings
-from onapsdk.sdc.service import Service, Vnf, VfModule
+from onapsdk.sdc.service import Service, Vnf, VfModule, Pnf
from onapsdk.so.deletion import ServiceDeletionRequest, VfModuleDeletionRequest, VnfDeletionRequest
from onapsdk.so.instantiation import (ServiceInstantiation, SoService,
- VfModuleInstantiation, VnfInstantiation, InstantiationParameter,
+ VfModuleInstantiation, VnfInstantiation, PnfInstantiation, InstantiationParameter,
VfmoduleParameters, VnfParameters)
@@ -303,6 +303,79 @@ def test_instantiate_macro(mock_service_components, mock_service_vnfs):
assert service_deletion_request.status == ServiceDeletionRequest.StatusEnum.COMPLETED
assert len(list(service_subscription.service_instances)) == 0
+@patch.object(Service, "pnfs", new_callable=PropertyMock)
+@patch.object(Service, "components", new_callable=PropertyMock)
+@pytest.mark.integration
+def test_instantiate_macro_for_pnf(mock_service_components, mock_service_pnfs):
+ requests.get(f"{ServiceInstantiation.base_url}/reset")
+ requests.get(f"{Customer.base_url}/reset")
+ requests.post(f"{ServiceInstantiation.base_url}/set_aai_mock", json={"AAI_MOCK": settings.AAI_URL})
+
+ customer = Customer.create(global_customer_id="test_global_customer_id",
+ subscriber_name="test_subscriber_name",
+ subscriber_type="test_subscriber_type")
+ service = Service("test_service")
+ service._tosca_template = "n/a"
+
+ mock_service_pnfs.return_value = [
+ Pnf(
+ name="test_pnf",
+ node_template_type="pnf",
+ model_name= "test_pnf_model",
+ model_version_id = str(uuid4()),
+ model_invariant_id=str(uuid4()),
+ model_version="1.0",
+ model_customization_id=str(uuid4()),
+ model_instance_name=str(uuid4()),
+ component=MagicMock(),
+ )
+ ]
+ service.unique_uuid = str(uuid4())
+ service.identifier = str(uuid4())
+ service.name = str(uuid4())
+ customer.subscribe_service("service_type")
+ service_subscription = customer.get_service_subscription_by_service_type("service_type")
+ cloud_region = CloudRegion.create(
+ "test_owner", "test_cloud_region", orchestration_disabled=True, in_maint=False
+ )
+ cloud_region.add_tenant(
+ tenant_id="test_tenant_name", tenant_name="test_tenant_name", tenant_context="test_tenant_context"
+ )
+ tenant = cloud_region.get_tenant(tenant_id="test_tenant_name")
+ service_subscription.link_to_cloud_region_and_tenant(cloud_region=cloud_region, tenant=tenant)
+ owning_entity = "test_owning_entity"
+ project = "test_project"
+ line_of_business = "test_line_of_business"
+ platform = "test_platform"
+
+ # Service instantiation
+ service._distributed = True
+ assert len(list(service_subscription.service_instances)) == 0
+ service_instantiation_request = ServiceInstantiation.instantiate_macro(
+ sdc_service=service,
+ customer=customer,
+ owning_entity=owning_entity,
+ project=project,
+ line_of_business=line_of_business,
+ platform=platform,
+ cloud_region=cloud_region,
+ tenant=tenant,
+ service_subscription=service_subscription
+ )
+ assert service_instantiation_request.status == ServiceInstantiation.StatusEnum.IN_PROGRESS
+ time.sleep(2) # After 1 second mocked server changed request status to complete
+ assert service_instantiation_request.status == ServiceInstantiation.StatusEnum.COMPLETED
+ assert len(list(service_subscription.service_instances)) == 1
+ service_instance = next(service_subscription.service_instances)
+
+ # Cleanup
+ with patch.object(ServiceInstance, "sdc_service", return_value=service) as service_mock:
+ service_deletion_request = service_instance.delete()
+ assert service_deletion_request.status == ServiceDeletionRequest.StatusEnum.IN_PROGRESS
+ time.sleep(2) # After 1 second mocked server changed request status to complete
+ assert service_deletion_request.status == ServiceDeletionRequest.StatusEnum.COMPLETED
+ assert len(list(service_subscription.service_instances)) == 0
+
@patch.object(Service, "vnfs", new_callable=PropertyMock)
@patch.object(Service, "components", new_callable=PropertyMock)
@pytest.mark.integration
@@ -425,3 +498,96 @@ def test_instantiate_macro_multiple_vnf(mock_service_components, mock_service_vn
time.sleep(2) # After 1 second mocked server changed request status to complete
assert service_deletion_request.status == ServiceDeletionRequest.StatusEnum.COMPLETED
assert len(list(service_subscription.service_instances)) == 0
+
+@patch.object(Service, "pnfs", new_callable=PropertyMock)
+@patch.object(Service, "components", new_callable=PropertyMock)
+@pytest.mark.integration
+def test_instantiate_macro_multiple_pnf(mock_service_components, mock_service_pnfs):
+ requests.get(f"{ServiceInstantiation.base_url}/reset")
+ requests.get(f"{Customer.base_url}/reset")
+ requests.post(f"{ServiceInstantiation.base_url}/set_aai_mock", json={"AAI_MOCK": settings.AAI_URL})
+
+ customer = Customer.create(global_customer_id="test_global_customer_id",
+ subscriber_name="test_subscriber_name",
+ subscriber_type="test_subscriber_type")
+ service = Service("test_service")
+ service._tosca_template = "n/a"
+
+ mock_service_pnfs.return_value = [
+ Pnf(
+ name="test_pnf",
+ node_template_type="pnf",
+ model_name= "test_pnf_model",
+ model_version_id = str(uuid4()),
+ model_invariant_id=str(uuid4()),
+ model_version="1.0",
+ model_customization_id=str(uuid4()),
+ model_instance_name=str(uuid4()),
+ component=MagicMock(),
+ )
+ ]
+ service.unique_uuid = str(uuid4())
+ service.identifier = str(uuid4())
+ service.name = str(uuid4())
+ customer.subscribe_service("service_type")
+ service_subscription = customer.get_service_subscription_by_service_type("service_type")
+ cloud_region = CloudRegion.create(
+ "test_owner", "test_cloud_region", orchestration_disabled=True, in_maint=False
+ )
+ cloud_region.add_tenant(
+ tenant_id="test_tenant_name", tenant_name="test_tenant_name", tenant_context="test_tenant_context"
+ )
+ tenant = cloud_region.get_tenant(tenant_id="test_tenant_name")
+ service_subscription.link_to_cloud_region_and_tenant(cloud_region=cloud_region, tenant=tenant)
+ owning_entity = "test_owning_entity"
+ project = "test_project"
+ line_of_business = "test_line_of_business"
+ platform = "test_platform"
+
+ so_service = SoService.load({
+ "subscription_service_type": "service_type",
+ "pnfs": [
+ {
+ "model_name": "test_pnf_model",
+ "instance_name": "pnf0",
+ "parameters": {
+ "param1": "value1"
+ },
+ },
+ {
+ "model_name": "test_pnf_model",
+ "instance_name": "pnf1",
+ "parameters": {
+ "param2": "value2"
+ },
+ }
+ ]
+ })
+
+ # Service instantiation
+ service._distributed = True
+ assert len(list(service_subscription.service_instances)) == 0
+ service_instantiation_request = ServiceInstantiation.instantiate_macro(
+ sdc_service=service,
+ customer=customer,
+ owning_entity=owning_entity,
+ project=project,
+ line_of_business=line_of_business,
+ platform=platform,
+ cloud_region=cloud_region,
+ tenant=tenant,
+ so_service=so_service
+ )
+ assert service_instantiation_request.status == ServiceInstantiation.StatusEnum.IN_PROGRESS
+ time.sleep(2) # After 1 second mocked server changed request status to complete
+ assert service_instantiation_request.status == ServiceInstantiation.StatusEnum.COMPLETED
+ assert len(list(service_subscription.service_instances)) == 1
+ service_instance = next(service_subscription.service_instances)
+
+ # Cleanup
+ with patch.object(ServiceInstance, "sdc_service", return_value=service) as service_mock:
+ service_deletion_request = service_instance.delete()
+ assert service_deletion_request.status == ServiceDeletionRequest.StatusEnum.IN_PROGRESS
+ time.sleep(2) # After 1 second mocked server changed request status to complete
+ assert service_deletion_request.status == ServiceDeletionRequest.StatusEnum.COMPLETED
+ assert len(list(service_subscription.service_instances)) == 0
diff --git a/src/onapsdk/so/instantiation.py b/src/onapsdk/so/instantiation.py
index c1bf10e..8130b00 100644
--- a/src/onapsdk/so/instantiation.py
+++ b/src/onapsdk/so/instantiation.py
@@ -24,7 +24,7 @@ from onapsdk.exceptions import (
)
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.sdc.service import Network, Service as SdcService, Vnf, Pnf, VfModule
from onapsdk.utils.jinja import jinja_env
from onapsdk.utils.headers_creator import headers_so_creator
from onapsdk.configuration import settings
@@ -657,6 +657,190 @@ class VnfInstantiation(NodeTemplateInstantiation): # pylint: disable=too-many-a
vnf=vnf_instance
)
+class PnfInstantiation(NodeTemplateInstantiation): # pylint: disable=too-many-ancestors
+ """PNF instantiation class."""
+
+ def __init__(self, # pylint: disable=too-many-arguments
+ name: str,
+ request_id: str,
+ instance_id: str,
+ line_of_business: str,
+ platform: str,
+ pnf: Pnf) -> None:
+ """Class PnfInstantion object initialization.
+
+ Args:
+ name (str): PNF 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
+ pnf (Pnf): Pnf class object
+ """
+ super().__init__(name, request_id, instance_id, line_of_business, platform)
+ self.pnf = pnf
+
+ @classmethod
+ def create_from_request_response(cls, request_response: dict) -> "PnfInstantiation":
+ """Create PNF instantiation object based on request details.
+
+ Raises:
+ ResourceNotFound: Service related with given object doesn't exist
+ ResourceNotFound: No ServiceInstantiation related with given PNF instantiation
+ ResourceNotFound: PNF related with given object doesn't exist
+ InvalidResponse: Invalid dictionary - couldn't create PnfInstantiation object
+
+ Returns:
+ PnfInstantiation: PnfInstantiation object
+
+ """
+ if request_response.get("request", {}).get("requestScope") == "pnf" 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 Pnf instance details response")
+ pnf: Pnf = None
+ for service_pnf in service.pnfs:
+ if service_pnf.name == request_response.get("request", {})\
+ .get("requestDetails", {}).get("modelInfo", {}).get("modelCustomizationName"):
+ pnf: Pnf = service_pnf
+ break
+ else:
+ raise ResourceNotFound("No pnf in service pnfs list")
+ return cls(
+ name=request_response.get("request", {})\
+ .get("instanceReferences", {}).get("pnfInstanceName"),
+ request_id=request_response.get("request", {}).get("requestId"),
+ instance_id=request_response.get("request", {})\
+ .get("instanceReferences", {}).get("pnfInstanceId"),
+ line_of_business=request_response.get("request", {})\
+ .get("requestDetails", {}).get("lineOfBusiness", {}).get("lineOfBusinessName"),
+ platform=request_response.get("request", {})\
+ .get("requestDetails", {}).get("platform", {}).get("platformName"),
+ pnf=pnf
+ )
+ raise InvalidResponse("Invalid pnf instantions in response dictionary's requestList")
+
+ @classmethod
+ def get_by_pnf_instance_name(cls, pnf_instance_name: str) -> "PnfInstantiation":
+ """Get PNF instantiation request by instance name.
+
+ Raises:
+ InvalidResponse: Pnf instance with given name does not contain
+ requestList or the requestList does not contain any details.
+
+ Returns:
+ PnfInstantiation: Pnf instantiation request object
+
+ """
+ response: dict = cls.send_message_json(
+ "GET",
+ f"Check {pnf_instance_name} service instantiation status",
+ (f"{cls.base_url}/onap/so/infra/orchestrationRequests/{cls.api_version}?"
+ f"filter=pnfInstanceName:EQUALS:{pnf_instance_name}"),
+ headers=headers_so_creator(OnapService.headers)
+ )
+ key = "requestList"
+ if not response.get(key, []):
+ raise InvalidResponse(f"{key} of a Pnf 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_macro(cls, # pylint: disable=too-many-arguments, too-many-locals
+ aai_service_instance: "ServiceInstance",
+ pnf_object: "Pnf",
+ line_of_business: str,
+ platform: str,
+ cloud_region: "CloudRegion",
+ tenant: "Tenant",
+ sdc_service: "SdcService",
+ pnf_instance_name: str = None,
+ pnf_parameters: Iterable["InstantiationParameter"] = None,
+ so_pnf: "SoServicePnf" = None
+ ) -> "PnfInstantiation":
+ """Instantiate Pnf using macro method.
+
+ Args:
+ aai_service_instance (ServiceInstance): Service instance associated with request
+ pnf_object (Pnf): Pnf 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.
+ pnf_instance_name (str, optional): Pnf instance name. Defaults to None.
+ pnf_parameters (Iterable[InstantiationParameter], optional): Instantiation parameters
+ that are sent in the request. Defaults to None
+ so_pnf (SoServicePnf): object with pnf instance parameters
+
+
+ Returns:
+ PnfInstantiation: PnfInstantiation 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_pnf:
+ template_file = "instantiate_pnf_macro_so_pnf.json.j2"
+ if so_pnf.instance_name:
+ pnf_instance_name = so_pnf.instance_name
+ else:
+ template_file = "instantiate_pnf_macro.json.j2"
+ if pnf_instance_name is None:
+ pnf_instance_name = \
+ f"Python_ONAP_SDK_pnf_instance_{str(uuid4())}"
+
+ response: dict = cls.send_message_json(
+ "POST",
+ (f"Instantiate {sdc_service.name} "
+ f"service pnf {pnf_object.name}"),
+ (f"{cls.base_url}/onap/so/infra/serviceInstantiation/{cls.api_version}/"
+ f"serviceInstances/{aai_service_instance.instance_id}/pnfs"),
+ data=jinja_env().get_template(template_file).render(
+ instance_name=pnf_instance_name,
+ pnf=pnf_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,
+ pnf_parameters=pnf_parameters or [],
+ so_pnf=so_pnf
+ ),
+ headers=headers_so_creator(OnapService.headers)
+ )
+
+ return PnfInstantiation(
+ name=pnf_instance_name,
+ request_id=response["requestReferences"]["requestId"],
+ instance_id=response["requestReferences"]["instanceId"],
+ line_of_business=line_of_business,
+ platform=platform,
+ pnf=pnf_object
+ )
class ServiceInstantiation(Instantiation): # pylint: disable=too-many-ancestors
"""Service instantiation class."""
diff --git a/src/onapsdk/so/templates/instantiate_pnf_macro.json.j2 b/src/onapsdk/so/templates/instantiate_pnf_macro.json.j2
new file mode 100755
index 0000000..6abfe84
--- /dev/null
+++ b/src/onapsdk/so/templates/instantiate_pnf_macro.json.j2
@@ -0,0 +1,121 @@
+{
+ "requestDetails": {
+ "requestInfo": {
+ "instanceName": "{{ service_instance.instance_name }}",
+ "source": "VID",
+ "suppressRollback": false,
+ "requestorId": "demo",
+ "productFamilyId": "1234"
+ },
+ "modelInfo": {
+ "modelType": "pnf",
+ "modelInvariantId": "{{ pnf.model_invariant_id }}",
+ "modelVersionId": "{{ pnf.model_version_id }}",
+ "modelName": "{{ pnf.model_name }}",
+ "modelVersion": "{{ pnf.model_version }}",
+ "modelCustomizationId": "{{ pnf.model_customization_id }}",
+ "modelInstanceName": "{{ pnf.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 pnfs %}
+ "pnfs": [
+ {
+ "modelInfo": {
+ "modelName": "{{ pnf.model_name }}",
+ "modelVersionId": "{{ pnf.model_version_id }}",
+ "modelInvariantUuid": "{{ pnf.model_invariant_id }}",
+ "modelVersion": "{{ pnf.model_version }}",
+ "modelCustomizationId": "{{ pnf.model_customization_id }}",
+ "modelInstanceName": "{{ pnf.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 pnf_parameter in pnf_parameters %}
+ {% if pnf_parameter.name == pnf.model_name %}
+ {% for parameter in pnf_parameter.pnf_parameters %}
+ "{{ parameter.name }}": "{{ parameter.value }}"{% if not loop.last %},{% endif %}
+ {% endfor %}
+ {% endif %}
+ {% endfor %}
+ }
+ ],
+ }
+ ]
+ {% endblock %}
+ },
+ "modelInfo": {
+ "modelType": "pnf",
+ "modelInvariantId": "{{ pnf.model_invariant_id }}",
+ "modelVersionId": "{{ pnf.model_version_id }}",
+ "modelName": "{{ pnf.model_name }}",
+ "modelVersion": "{{ pnf.model_version }}",
+ "modelCustomizationId": "{{ pnf.model_customization_id }}",
+ "modelCustomizationName": "{{ pnf.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_pnf_macro_so_pnf.json.j2 b/src/onapsdk/so/templates/instantiate_pnf_macro_so_pnf.json.j2
new file mode 100755
index 0000000..a6571bd
--- /dev/null
+++ b/src/onapsdk/so/templates/instantiate_pnf_macro_so_pnf.json.j2
@@ -0,0 +1,117 @@
+{
+ "requestDetails": {
+ "requestInfo": {
+ "instanceName": "{{ service_instance.instance_name }}",
+ "source": "VID",
+ "suppressRollback": false,
+ "requestorId": "demo",
+ "productFamilyId": "1234"
+ },
+ "modelInfo": {
+ "modelType": "pnf",
+ "modelInvariantId": "{{ pnf.model_invariant_id }}",
+ "modelVersionId": "{{ pnf.model_version_id }}",
+ "modelName": "{{ pnf.model_name }}",
+ "modelVersion": "{{ pnf.model_version }}",
+ "modelCustomizationId": "{{ pnf.model_customization_id }}",
+ "modelInstanceName": "{{ pnf.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 pnfs %}
+ "pnfs": [
+ {
+ "modelInfo": {
+ "modelName": "{{ pnf.model_name }}",
+ "modelVersionId": "{{ pnf.model_version_id }}",
+ "modelInvariantUuid": "{{ pnf.model_invariant_id }}",
+ "modelVersion": "{{ pnf.model_version }}",
+ "modelCustomizationId": "{{ pnf.model_customization_id }}",
+ "modelInstanceName": "{{ pnf.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_pnf.parameters.items() %}
+ "{{ key }}": "{{ value }}"{% if not loop.last %},{% endif %}
+ {% endfor %}
+ }
+ ],
+ }
+ ]
+ {% endblock %}
+ },
+ "modelInfo": {
+ "modelType": "pnf",
+ "modelInvariantId": "{{ pnf.model_invariant_id }}",
+ "modelVersionId": "{{ pnf.model_version_id }}",
+ "modelName": "{{ pnf.model_name }}",
+ "modelVersion": "{{ pnf.model_version }}",
+ "modelCustomizationId": "{{ pnf.model_customization_id }}",
+ "modelCustomizationName": "{{ pnf.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/tests/test_so_instantiation.py b/tests/test_so_instantiation.py
index ec796a9..1374b84 100644
--- a/tests/test_so_instantiation.py
+++ b/tests/test_so_instantiation.py
@@ -31,6 +31,7 @@ from onapsdk.so.instantiation import (
SoServiceVnf,
VfModuleInstantiation,
VnfInstantiation,
+ PnfInstantiation,
ServiceOperation,
VnfOperation
)
@@ -344,6 +345,71 @@ def test_vnf_instantiation_macro(mock_owning_entity_get, mock_vnf_instantiation_
so_vnf=so_vnf_mock)
assert vnf_instantiation.name == "SoVnfInstanceName"
+@mock.patch.object(PnfInstantiation, "send_message_json")
+@mock.patch.object(OwningEntity, "get_by_owning_entity_id")
+def test_pnf_instantiation_macro(mock_owning_entity_get, mock_pnf_instantiation_send_message):
+ aai_service_instance_mock = mock.MagicMock()
+ aai_service_instance_mock.instance_id = "test_instance_id"
+
+ relation_1 = mock.MagicMock()
+ relation_1.related_to = "owning-entity"
+ relation_1.relationship_data = [{"relationship-value": "test"}]
+ relation_2 = mock.MagicMock()
+ relation_2.related_to = "project"
+ relation_2.relationship_data = [{"relationship-value": "test"}]
+
+ aai_service_instance_mock.relationships = (item for item in [relation_1, relation_2])
+
+ pnf_instantiation = PnfInstantiation.\
+ instantiate_macro(aai_service_instance=aai_service_instance_mock,
+ pnf_object=mock.MagicMock(),
+ line_of_business="test_lob",
+ platform="test_platform",
+ cloud_region=mock.MagicMock(),
+ tenant=mock.MagicMock(),
+ sdc_service=mock.MagicMock())
+ assert pnf_instantiation.name.startswith("Python_ONAP_SDK_pnf_instance_")
+ mock_pnf_instantiation_send_message.assert_called_once()
+ method, _, url = mock_pnf_instantiation_send_message.call_args[0]
+ assert method == "POST"
+ assert url == (f"{PnfInstantiation.base_url}/onap/so/infra/serviceInstantiation/"
+ f"{PnfInstantiation.api_version}/serviceInstances/"
+ f"{aai_service_instance_mock.instance_id}/pnfs")
+
+ pnf_instantiation = PnfInstantiation. \
+ instantiate_macro(aai_service_instance=aai_service_instance_mock,
+ pnf_object=mock.MagicMock(),
+ line_of_business="test_lob",
+ platform="test_platform",
+ pnf_instance_name="test",
+ cloud_region=mock.MagicMock(),
+ tenant=mock.MagicMock(),
+ sdc_service=mock.MagicMock())
+ assert pnf_instantiation.name == "test"
+
+ pnf_instantiation = PnfInstantiation. \
+ instantiate_macro(aai_service_instance=aai_service_instance_mock,
+ pnf_object=mock.MagicMock(),
+ line_of_business="test_lob",
+ platform="test_platform",
+ cloud_region=mock.MagicMock(),
+ tenant=mock.MagicMock(),
+ sdc_service=mock.MagicMock(),
+ so_pnf=mock.MagicMock())
+ assert pnf_instantiation.name.startswith("Python_ONAP_SDK_service_instance_")
+
+ so_pnf_mock = mock.MagicMock()
+ so_pnf_mock.instance_name = "SoPnfInstanceName"
+ pnf_instantiation = PnfInstantiation. \
+ instantiate_macro(aai_service_instance=aai_service_instance_mock,
+ pnf_object=mock.MagicMock(),
+ line_of_business="test_lob",
+ platform="test_platform",
+ cloud_region=mock.MagicMock(),
+ tenant=mock.MagicMock(),
+ sdc_service=mock.MagicMock(),
+ so_pnf=so_pnf_mock)
+ assert pnf_instantiation.name == "SoPnfInstanceName"
@mock.patch.object(VnfInstantiation, "send_message_json")
@mock.patch.object(OwningEntity, "get_by_owning_entity_id")
@@ -626,6 +692,114 @@ def test_vnf_instantiation_get_by_vnf_instance_name(mock_sdc_service, mock_send_
}
assert VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") is not None
+@mock.patch.object(Vid, "send_message")
+@mock.patch.object(PnfInstantiation, "send_message_json")
+@mock.patch("onapsdk.so.instantiation.SdcService")
+def test_pnf_instantiation_get_by_pnf_instance_name(mock_sdc_service, mock_send_message_json, mock_send):
+ mock_sdc_service.return_value.pnfs = []
+ mock_send_message_json.return_value = {}
+ with pytest.raises(InvalidResponse):
+ PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name")
+ mock_send_message_json.return_value = {
+ "requestList": [
+ ]
+ }
+ with pytest.raises(InvalidResponse):
+ PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name")
+ mock_send_message_json.return_value = {
+ "requestList1": [
+ ]
+ }
+ with pytest.raises(InvalidResponse):
+ PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name")
+ mock_send_message_json.return_value = {
+ "requestList": [
+ {
+ "request": {
+ "requestScope": "not_pnf"
+ }
+ }
+ ]
+ }
+ with pytest.raises(InvalidResponse):
+ PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name")
+ mock_send_message_json.return_value = {
+ "requestList": [
+ {
+ "request": {
+ "requestScope": "pnf",
+ "requestType": "updateInstance"
+ }
+ }
+ ]
+ }
+ with pytest.raises(InvalidResponse):
+ PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name")
+ mock_send_message_json.return_value = {
+ "requestList": [
+ {
+ "request": {
+ "requestScope": "pnf",
+ "requestType": "createInstance"
+ }
+ }
+ ]
+ }
+ with pytest.raises(ResourceNotFound):
+ PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name")
+ mock_send_message_json.return_value = {
+ "requestList": [
+ {
+ "request": {
+ "requestScope": "pnf",
+ "requestType": "createInstance",
+ "requestDetails": {
+ "relatedInstanceList": [
+ {
+ "relatedInstance": {
+ "modelInfo": {
+ "modelType": "service",
+ "modelName": "test_service"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ with pytest.raises(ResourceNotFound):
+ PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name")
+ mock_pnf = mock.MagicMock()
+ mock_pnf.name = "test_pnf_name"
+ mock_sdc_service.return_value.pnfs = [mock_pnf]
+ mock_send_message_json.return_value = {
+ "requestList": [
+ {
+ "request": {
+ "requestScope": "pnf",
+ "requestType": "createInstance",
+ "requestDetails": {
+ "modelInfo": {
+ "modelCustomizationName": "test_pnf_name"
+ },
+ "relatedInstanceList": [
+ {
+ "relatedInstance": {
+ "modelInfo": {
+ "modelType": "service",
+ "modelName": "test_service"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ assert PnfInstantiation.get_by_pnf_instance_name("test_pnf_instance_name") is not None
@mock.patch.object(VfModuleInstantiation, "send_message_json")
@mock.patch.object(VfModulePreload, "upload_vf_module_preload")