aboutsummaryrefslogtreecommitdiffstats
path: root/onap_data_provider/resources
diff options
context:
space:
mode:
authorMichal Jagiello <michal.jagiello@t-mobile.pl>2021-11-30 08:25:09 +0000
committerMichal Jagiello <michal.jagiello@t-mobile.pl>2021-12-03 09:58:59 +0000
commit66e44262b8eb996c06670dcededd899dd1cbd7dc (patch)
tree3fcea0fe3317f8069281cb93c61add4b1599ab83 /onap_data_provider/resources
parent2416a1a546c1d2922c37d513df42e9d26bbaaa42 (diff)
Data provider release
Change-Id: Ia041a07152e8dabd87de05992d3670cbdc1ddaae Issue-ID: INT-2010 Signed-off-by: Michal Jagiello <michal.jagiello@t-mobile.pl>
Diffstat (limited to 'onap_data_provider/resources')
-rw-r--r--onap_data_provider/resources/__init__.py16
-rw-r--r--onap_data_provider/resources/aai_service_resource.py83
-rw-r--r--onap_data_provider/resources/cloud_region_resource.py177
-rw-r--r--onap_data_provider/resources/complex_resource.py92
-rw-r--r--onap_data_provider/resources/customer_resource.py189
-rw-r--r--onap_data_provider/resources/esr_system_info_resource.py114
-rw-r--r--onap_data_provider/resources/line_of_business_resource.py73
-rw-r--r--onap_data_provider/resources/msb_k8s_definition.py85
-rw-r--r--onap_data_provider/resources/msb_k8s_profile.py80
-rw-r--r--onap_data_provider/resources/owning_entity_resource.py75
-rw-r--r--onap_data_provider/resources/platform_resource.py73
-rw-r--r--onap_data_provider/resources/pnf_resource.py78
-rw-r--r--onap_data_provider/resources/project_resource.py73
-rw-r--r--onap_data_provider/resources/resource.py45
-rw-r--r--onap_data_provider/resources/resource_creator.py177
-rw-r--r--onap_data_provider/resources/service_instance_resource.py271
-rw-r--r--onap_data_provider/resources/service_resource.py100
-rw-r--r--onap_data_provider/resources/tenant_resource.py85
-rw-r--r--onap_data_provider/resources/vendor_resource.py75
-rw-r--r--onap_data_provider/resources/vnf_resource.py75
-rw-r--r--onap_data_provider/resources/vsp_resource.py71
-rw-r--r--onap_data_provider/resources/xnf_resource.py60
22 files changed, 2167 insertions, 0 deletions
diff --git a/onap_data_provider/resources/__init__.py b/onap_data_provider/resources/__init__.py
new file mode 100644
index 0000000..dbcdf74
--- /dev/null
+++ b/onap_data_provider/resources/__init__.py
@@ -0,0 +1,16 @@
+"""Resources package."""
+"""
+ Copyright 2021 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/onap_data_provider/resources/aai_service_resource.py b/onap_data_provider/resources/aai_service_resource.py
new file mode 100644
index 0000000..8fbc119
--- /dev/null
+++ b/onap_data_provider/resources/aai_service_resource.py
@@ -0,0 +1,83 @@
+"""A&AI service model resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.aai.service_design_and_creation import Service as AaiService # type: ignore
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+from .resource import Resource
+
+
+class AaiServiceResource(Resource):
+ """A&AI service model resource class."""
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize A&AI SDC service resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._aai_service: AaiService = None
+
+ def create(self) -> None:
+ """Create aai service resource."""
+ if not self.exists:
+ logging.debug("Create AaiService %s", self.data["service-id"])
+ AaiService.create(
+ service_id=self.data["service-id"],
+ service_description=self.data["service-description"],
+ )
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.aai_service is not None
+
+ @property
+ def aai_service(self) -> AaiService:
+ """A&AI service property.
+
+ A&AI servic emodel which is represented by the data provided by user.
+
+ Returns:
+ AaiService: A&AI service model object
+
+ """
+ if not self._aai_service:
+ try:
+ for aai_service in AaiService.get_all():
+ if (
+ aai_service.service_id == self.data["service-id"]
+ and aai_service.service_description
+ == self.data["service-description"]
+ ):
+ self._aai_service = aai_service
+ return self._aai_service
+ except ResourceNotFound:
+ logging.error(
+ "A&AI service %s does not exist",
+ self.data["service-id"],
+ )
+ return self._aai_service
diff --git a/onap_data_provider/resources/cloud_region_resource.py b/onap_data_provider/resources/cloud_region_resource.py
new file mode 100644
index 0000000..7bcc3b4
--- /dev/null
+++ b/onap_data_provider/resources/cloud_region_resource.py
@@ -0,0 +1,177 @@
+"""Cloud region resource module."""
+"""
+ Copyright 2021 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 onap_data_provider.resources.esr_system_info_resource import (
+ EsrSystemInfoResource,
+)
+import logging
+from typing import Any, Dict
+
+from onapsdk.aai.cloud_infrastructure import CloudRegion, Complex # type: ignore
+from onapsdk.msb.k8s.connectivity_info import ConnectivityInfo # type: ignore
+from onapsdk.so.so_db_adapter import SoDbAdapter, IdentityService # type: ignore
+
+from .resource import Resource
+from .tenant_resource import TenantResource
+from onapsdk.exceptions import APIError, ResourceNotFound # type: ignore
+
+
+class CloudRegionResource(Resource):
+ """Cloud region resource class.
+
+ Creates cloud region.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize cloud region resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._cloud_region: CloudRegion = None
+
+ def create(self) -> None:
+ """Create cloud region resource.
+
+ Create cloud region resource and all related resources.
+
+ """
+ logging.debug("Create CloudRegion %s", self.data["cloud-region-id"])
+ if not self.exists:
+ self._cloud_region = CloudRegion.create(
+ cloud_owner=self.data["cloud-owner"],
+ cloud_region_id=self.data["cloud-region-id"],
+ orchestration_disabled=self.data["orchestration-disabled"],
+ in_maint=self.data["in-maint"],
+ cloud_type=self.data.get("cloud-region-type", "openstack"),
+ cloud_region_version="pike",
+ )
+
+ # Create tenants
+ for tenant_data in self.data.get("tenants", []):
+ tenant_resource = TenantResource(
+ tenant_data, cloud_region=self._cloud_region
+ )
+ tenant_resource.create()
+
+ # Link with complex
+ if (
+ complex_physical_id := self.data.get("complex", {}).get(
+ "physical-location-id"
+ )
+ ) is not None:
+ self._link_to_complex(complex_physical_id)
+
+ # Add availability zones
+ try:
+ for az_data in self.data.get("availability-zones", []):
+ self.cloud_region.add_availability_zone(
+ availability_zone_name=az_data["availability-zone-name"],
+ availability_zone_hypervisor_type=az_data["hypervisor-type"],
+ )
+ except APIError:
+ logging.error("Availability zone update not supported.")
+
+ # Create external system infos
+ for esr_system_info_data in self.data.get("esr-system-infos", []):
+ esr_system_info_resource: EsrSystemInfoResource = EsrSystemInfoResource(
+ esr_system_info_data, cloud_region=self._cloud_region
+ )
+ esr_system_info_resource.create()
+
+ if self.data.get("register-to-multicloud", False):
+ self.cloud_region.register_to_multicloud()
+
+ # Create connectivity info for Cloud region if it's type is k8s
+ if self.cloud_region.cloud_type == "k8s":
+ try:
+ ConnectivityInfo.get_connectivity_info_by_region_id(
+ self.cloud_region.cloud_region_id
+ )
+ except APIError:
+ with open(self.data["kube-config"], "rb") as kube_config:
+ ConnectivityInfo.create(
+ cloud_owner=self.cloud_region.cloud_owner,
+ cloud_region_id=self.cloud_region.cloud_region_id,
+ kubeconfig=kube_config.read(),
+ )
+ if not self.cloud_region.complex:
+ logging.error(
+ "k8s cloud region should have complex linked to create SO cloud site DB entry"
+ )
+ else:
+ SoDbAdapter.add_cloud_site(
+ self.cloud_region.cloud_region_id,
+ self.cloud_region.complex.physical_location_id,
+ IdentityService("DEFAULT_KEYSTONE"),
+ )
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.cloud_region is not None
+
+ @property
+ def cloud_region(self) -> CloudRegion:
+ """Cloud region property.
+
+ Cloud region which is represented by the data provided by user.
+
+ Returns:
+ CloudRegion: Cloud region object
+
+ """
+ if not self._cloud_region:
+ try:
+ self._cloud_region = CloudRegion.get_by_id(
+ self.data["cloud-owner"], self.data["cloud-region-id"]
+ )
+ except ResourceNotFound:
+ logging.error(
+ "Cloud region %s does not exist",
+ self.data["cloud-region-id"],
+ )
+ return None
+ return self._cloud_region
+
+ def _link_to_complex(self, complex_physical_id: str) -> None:
+ try: # TODO: change it when https://gitlab.com/Orange-OpenSource/lfn/onap/python-onapsdk/-/issues/120 is fixed
+ if self.cloud_region.complex:
+ logging.info(
+ "Cloud region has relationship with complex: %s. New relationship can't be created",
+ self.cloud_region.complex.physical_location_id,
+ )
+ return
+ except ResourceNotFound:
+ logging.debug("Cloud region has no complex linked with")
+ try:
+ complex: Complex = next(
+ Complex.get_all(physical_location_id=complex_physical_id)
+ )
+ self.cloud_region.link_to_complex(complex)
+ except StopIteration:
+ logging.error(
+ "Complex %s does not exist, please create it before cloud region creation",
+ complex_physical_id,
+ )
diff --git a/onap_data_provider/resources/complex_resource.py b/onap_data_provider/resources/complex_resource.py
new file mode 100644
index 0000000..82ab462
--- /dev/null
+++ b/onap_data_provider/resources/complex_resource.py
@@ -0,0 +1,92 @@
+"""Complex resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.aai.cloud_infrastructure import Complex # type: ignore
+
+from .resource import Resource
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+
+class ComplexResource(Resource):
+ """Complex resource class."""
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Complex resource initialization.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create complex
+
+ """
+ super().__init__(data)
+ self._complex: Complex = None
+
+ def create(self) -> None:
+ """Create complex resource."""
+ if not self.exists:
+ self._complex = Complex.create(
+ physical_location_id=self.data["physical-location-id"],
+ name=self.data.get("complex-name"),
+ data_center_code=self.data.get("data-center-code"),
+ identity_url=self.data.get("identity-url"),
+ physical_location_type=self.data.get("physical-location-type"),
+ street1=self.data.get("street1"),
+ street2=self.data.get("street2"),
+ city=self.data.get("city"),
+ state=self.data.get("state"),
+ postal_code=self.data.get("postal-code"),
+ country=self.data.get("country"),
+ region=self.data.get("region"),
+ latitude=self.data.get("latitude"),
+ longitude=self.data.get("longitude"),
+ elevation=self.data.get("elevation"),
+ lata=self.data.get("lata"),
+ )
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.complex is not None
+
+ @property
+ def complex(self) -> Complex:
+ """Complex property.
+
+ Returns:
+ Complex: Complex object
+
+ """
+ if not self._complex:
+ try:
+ self._complex = next(
+ Complex.get_all(
+ physical_location_id=self.data["physical-location-id"]
+ )
+ )
+ except ResourceNotFound:
+ logging.error(
+ "Complex %s does not exist", self.data["physical-location-id"]
+ )
+ return None
+ return self._complex
diff --git a/onap_data_provider/resources/customer_resource.py b/onap_data_provider/resources/customer_resource.py
new file mode 100644
index 0000000..2bbb1ef
--- /dev/null
+++ b/onap_data_provider/resources/customer_resource.py
@@ -0,0 +1,189 @@
+"""Customer resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.aai.business import Customer, ServiceSubscription # type: ignore
+from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant # type: ignore
+
+from onapsdk.sdc.service import Service # type: ignore
+
+from .resource import Resource
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+
+class CustomerResource(Resource):
+ """Customer resource class.
+
+ Creates customer.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize customer resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._customer: Customer = None
+
+ def create(self) -> None:
+ """Create customer resource.
+
+ Create customer resource and all related resources.
+
+ """
+ logging.debug("Create Customer %s", self.data["global-customer-id"])
+ if not self.exists:
+ self._customer = Customer.create(
+ global_customer_id=self.data["global-customer-id"],
+ subscriber_name=self.data["subscriber-name"],
+ subscriber_type=self.data["subscriber-type"],
+ )
+
+ for service_subscription in self.data.get("service-subscriptions", []):
+ resource = CustomerResource.ServiceSubscriptionResource(
+ service_subscription, self._customer
+ )
+ resource.create()
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.customer is not None
+
+ @property
+ def customer(self) -> Customer:
+ """Access to customer property.
+
+ Customer property containing Customer object.
+
+ Returns:
+ Customer: Customer object
+
+ """
+ if not self._customer:
+ try:
+ self._customer = Customer.get_by_global_customer_id(
+ self.data["global-customer-id"]
+ )
+ except ResourceNotFound:
+ logging.error(
+ "Customer %s does not exist",
+ self.data["global-customer-id"],
+ )
+ return None
+ return self._customer
+
+ class ServiceSubscriptionResource(Resource):
+ """Service subscription class.
+
+ Creates service subscription.
+ """
+
+ def __init__(self, data: Dict[str, str], customer: Customer) -> None:
+ """Initialize service subscription resource.
+
+ Args:
+ data (Dict[str, str]): Data needed to create resource.
+ customer (Customer): Related Customer object.
+
+ """
+ super().__init__(data)
+ self._service_subscription: ServiceSubscription = None
+ self._customer: Customer = customer
+
+ def create(self) -> None:
+ """Create Service subscription resource.
+
+ Create service subscription resource belonging to a customer.
+
+ """
+ logging.debug("Create ServiceSubscription %s", self.data["service-type"])
+ if not self.exists:
+ self._service_subscription = self._customer.subscribe_service(
+ Service(self.data["service-type"])
+ )
+
+ for tenant_cloud_region_data in self.data.get("tenants", []):
+ try:
+ cloud_region: CloudRegion = CloudRegion.get_by_id(
+ tenant_cloud_region_data["cloud-owner"],
+ tenant_cloud_region_data["cloud-region-id"],
+ )
+ except ResourceNotFound:
+ logging.error(
+ f"Cloud region {tenant_cloud_region_data['cloud-owner']} {tenant_cloud_region_data['cloud-region-id']} does not exists"
+ )
+ continue
+ try:
+ tenant: Tenant = cloud_region.get_tenant(
+ tenant_cloud_region_data["tenant-id"]
+ )
+ except ResourceNotFound:
+ logging.error(
+ f"Tenant {tenant_cloud_region_data['tenant-id']} does not exist"
+ )
+ continue
+
+ self.service_subscription.link_to_cloud_region_and_tenant(
+ cloud_region, tenant
+ )
+ logging.debug(
+ f"Service subscription linked to {tenant.name} tenant and {cloud_region.cloud_region_id} cloud region"
+ )
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.service_subscription is not None
+
+ @property
+ def service_subscription(self) -> ServiceSubscription:
+ """Get ServiceSubscription instance.
+
+ Get ServiceSubscription instance.
+
+ Returns:
+ ServiceSubscription: Created `ServiceSubscription` subclass instance.
+ """
+ if not self._service_subscription:
+ try:
+ self._service_subscription = (
+ self._customer.get_service_subscription_by_service_type(
+ self.data["service-type"]
+ )
+ )
+ except ResourceNotFound:
+ logging.error(
+ "Service type %s does not exist",
+ self.data["service-type"],
+ )
+ return None
+ return self._service_subscription
diff --git a/onap_data_provider/resources/esr_system_info_resource.py b/onap_data_provider/resources/esr_system_info_resource.py
new file mode 100644
index 0000000..4c26bbb
--- /dev/null
+++ b/onap_data_provider/resources/esr_system_info_resource.py
@@ -0,0 +1,114 @@
+"""External system info resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.aai.cloud_infrastructure import CloudRegion, EsrSystemInfo # type: ignore
+from onapsdk.exceptions import APIError # type: ignore
+
+from .resource import Resource
+
+
+class EsrSystemInfoResource(Resource):
+ """ESR system info resource class."""
+
+ def __init__(self, data: Dict[str, Any], cloud_region: CloudRegion) -> None:
+ """ESR system info resource initialization.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create esr system info
+ cloud_region (CloudRegion): Cloud region for which esr system info is going to be created
+
+ """
+ super().__init__(data)
+ self.cloud_region: CloudRegion = cloud_region
+ self._esr_system_info: EsrSystemInfo = None
+
+ @staticmethod
+ def get_esr_info_by_id(
+ cloud_region: CloudRegion, esr_syste_info_id: str
+ ) -> EsrSystemInfo:
+ """Get esr system info from Cloud region by it's ID.
+
+ Iterate through cloud region's esr system infos and check
+ if it's already have some with provided ID.
+
+ Args:
+ cloud_region (CloudRegion): CloudRegion object to check if esr system info already exists
+ esr_syste_info_id (str): ESR system info ID to check.
+
+ Returns:
+ EsrSystemInfo: ESR system info object
+ """
+ for esr_system_info in cloud_region.esr_system_infos:
+ if esr_system_info.esr_system_info_id == esr_syste_info_id:
+ return esr_system_info
+
+ def create(self) -> None:
+ """Create ESR system info resource.
+
+ Add ESR system info to provided cloud region
+
+ """
+ logging.debug(
+ "Create ESR system info for %s cloud region",
+ self.cloud_region.cloud_region_id,
+ )
+ if not self.exists:
+ self.cloud_region.add_esr_system_info(
+ esr_system_info_id=self.data["esr-system-info-id"],
+ user_name=self.data["user-name"],
+ password=self.data["password"],
+ system_type=self.data["system-type"],
+ service_url=self.data["service-url"],
+ system_status="active",
+ cloud_domain=self.data["cloud-domain"],
+ default_tenant=self.data.get("default-tenant"),
+ )
+ self._esr_system_info = self.get_esr_info_by_id(
+ self.cloud_region, self.data["esr-system-info-id"]
+ )
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.esr_system_info is not None
+
+ @property
+ def esr_system_info(self) -> EsrSystemInfo:
+ """External system info property.
+
+ Returns:
+ EsrSystemInfo: EsrSystemInfo object
+
+ """
+ if self._esr_system_info is None:
+ try:
+ if (
+ esr_system_info := self.get_esr_info_by_id(
+ self.cloud_region, self.data["esr-system-info-id"]
+ )
+ ) is not None:
+ self._esr_system_info = esr_system_info
+ except APIError:
+ logging.info("No esr system infos")
+ return self._esr_system_info
diff --git a/onap_data_provider/resources/line_of_business_resource.py b/onap_data_provider/resources/line_of_business_resource.py
new file mode 100644
index 0000000..0150746
--- /dev/null
+++ b/onap_data_provider/resources/line_of_business_resource.py
@@ -0,0 +1,73 @@
+"""Line of business resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict, Optional
+
+from onapsdk.aai.business import LineOfBusiness # type: ignore
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+from .resource import Resource
+
+
+class LineOfBusinessResource(Resource):
+ """Line of business resource class.
+
+ Creates A&AI line of business.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize line of business resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._line_of_business: Optional[LineOfBusiness] = None
+
+ def create(self) -> None:
+ """Create line of business resource."""
+ logging.debug(f"Create Line of business {self.data['name']}")
+ if not self.exists:
+ self._line_of_business = LineOfBusiness.create(self.data["name"])
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return bool(self.line_of_business)
+
+ @property
+ def line_of_business(self) -> LineOfBusiness:
+ """Line of business property.
+
+ Line of business which is represented by the data provided by user.
+
+ Returns:
+ LineOfBusiness: Line of business object
+
+ """
+ if not self._line_of_business:
+ try:
+ self._line_of_business = LineOfBusiness.get_by_name(self.data["name"])
+ except ResourceNotFound:
+ return None
+ return self._line_of_business
diff --git a/onap_data_provider/resources/msb_k8s_definition.py b/onap_data_provider/resources/msb_k8s_definition.py
new file mode 100644
index 0000000..b4b3342
--- /dev/null
+++ b/onap_data_provider/resources/msb_k8s_definition.py
@@ -0,0 +1,85 @@
+"""MSB K8S definition resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict, Optional
+
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+from onapsdk.msb.k8s.definition import Definition # type: ignore
+
+from .msb_k8s_profile import MsbK8SProfileResource
+from .resource import Resource
+
+
+class MsbK8SDefinitionResource(Resource):
+ """Definition resource class.
+
+ Creates MSB Kubernetes plugin's definition.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize definition resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._definition: Optional[Definition] = None
+
+ def create(self) -> None:
+ """Create definition if not already exists."""
+ if not self.exists:
+ self._definition = Definition.create(
+ self.data["name"],
+ self.data["version"],
+ self.data.get("chart-name"),
+ self.data.get("description"),
+ )
+ with open(self.data["artifact"], "rb") as artifact:
+ self._definition.upload_artifact(artifact.read())
+ for profile_data in self.data.get("profiles", []):
+ MsbK8SProfileResource(profile_data, self.definition).create()
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.definition is not None
+
+ @property
+ def definition(self) -> Optional[Definition]:
+ """Definition property.
+
+ Definition which is represented by the data provided by user.
+
+ Returns:
+ Definition: Definition object
+
+ """
+ if not self._definition:
+ try:
+ self._definition = Definition.get_definition_by_name_version(
+ self.data["name"], self.data["version"]
+ )
+ except ResourceNotFound:
+ logging.error("Definition %s does not exist", self.data["rb-name"])
+ return self._definition
diff --git a/onap_data_provider/resources/msb_k8s_profile.py b/onap_data_provider/resources/msb_k8s_profile.py
new file mode 100644
index 0000000..ae884c2
--- /dev/null
+++ b/onap_data_provider/resources/msb_k8s_profile.py
@@ -0,0 +1,80 @@
+"""MSB K8S definition profile resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict, Optional
+
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+from onapsdk.msb.k8s.definition import Definition, Profile # type: ignore
+
+from .resource import Resource
+
+
+class MsbK8SProfileResource(Resource):
+ """Profile resource class.
+
+ Creates MSB Kubernetes plugin's profile
+ """
+
+ def __init__(self, data: Dict[str, Any], definition: Definition) -> None:
+ """Initialize definition resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._profile: Optional[Profile] = None
+ self.definition: Definition = definition
+
+ def create(self) -> None:
+ """Create profile if not already exists."""
+ if not self.exists:
+ self._profile = self.definition.create_profile(
+ self.data["name"], self.data["namespace"], self.data["k8s-version"]
+ )
+ with open(self.data["artifact"], "rb") as artifact:
+ self._profile.upload_artifact(artifact.read())
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.profile is not None
+
+ @property
+ def profile(self) -> Optional[Profile]:
+ """Profile property.
+
+ Profile which is represented by the data provided by user.
+
+ Returns:
+ Profile: Profile object
+
+ """
+ if not self._profile:
+ try:
+ self._profile = self.definition.get_profile_by_name(
+ self.data["rb-name"]
+ )
+ except ResourceNotFound:
+ logging.error("Profile %s not found", self.data["name"])
+ return self._profile
diff --git a/onap_data_provider/resources/owning_entity_resource.py b/onap_data_provider/resources/owning_entity_resource.py
new file mode 100644
index 0000000..496ec22
--- /dev/null
+++ b/onap_data_provider/resources/owning_entity_resource.py
@@ -0,0 +1,75 @@
+"""Owning entity resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict, Optional
+
+from onapsdk.aai.business import OwningEntity # type: ignore
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+from .resource import Resource
+
+
+class OwningEntityResource(Resource):
+ """Owning entity resource class.
+
+ Creates A&AI line of business.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize line of business resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._owning_entity: Optional[OwningEntity] = None
+
+ def create(self) -> None:
+ """Create line of business resource."""
+ logging.debug(f"Create Owning entity {self.data['name']}")
+ if not self.exists:
+ self._owning_entity = OwningEntity.create(self.data["name"])
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return bool(self.owning_entity)
+
+ @property
+ def owning_entity(self) -> OwningEntity:
+ """Owning entity property.
+
+ Owning entity which is represented by the data provided by user.
+
+ Returns:
+ OwningEntity: Owning entity object
+
+ """
+ if not self._owning_entity:
+ try:
+ self._owning_entity = OwningEntity.get_by_owning_entity_name(
+ self.data["name"]
+ )
+ except ResourceNotFound:
+ return None
+ return self._owning_entity
diff --git a/onap_data_provider/resources/platform_resource.py b/onap_data_provider/resources/platform_resource.py
new file mode 100644
index 0000000..5e8893c
--- /dev/null
+++ b/onap_data_provider/resources/platform_resource.py
@@ -0,0 +1,73 @@
+"""Platform resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict, Optional
+
+from onapsdk.aai.business import Platform # type: ignore
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+from .resource import Resource
+
+
+class PlatformResource(Resource):
+ """Platform resource class.
+
+ Creates A&AI platform.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize platform resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._platform: Optional[Platform] = None
+
+ def create(self) -> None:
+ """Create platform resource."""
+ logging.debug(f"Create Platform {self.data['name']}")
+ if not self.exists:
+ self._platform = Platform.create(self.data["name"])
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return bool(self.platform)
+
+ @property
+ def platform(self) -> Platform:
+ """Platform property.
+
+ Platform which is represented by the data provided by user.
+
+ Returns:
+ Platform: Platform object
+
+ """
+ if not self._platform:
+ try:
+ self._platform = Platform.get_by_name(self.data["name"])
+ except ResourceNotFound:
+ return None
+ return self._platform
diff --git a/onap_data_provider/resources/pnf_resource.py b/onap_data_provider/resources/pnf_resource.py
new file mode 100644
index 0000000..553018b
--- /dev/null
+++ b/onap_data_provider/resources/pnf_resource.py
@@ -0,0 +1,78 @@
+"""Pnf resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.sdc.pnf import Pnf # type: ignore
+from onapsdk.sdc.vendor import Vendor # type: ignore
+from .resource import Resource
+from .xnf_resource import XnfResource
+
+
+class PnfResource(Resource, XnfResource):
+ """Pnf resource class.
+
+ Creates pnf.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize pnf resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+
+ def create(self) -> None:
+ """Create pnf resource.
+
+ Create pnf resource and link to provided resources.
+
+ """
+ if not self.exists:
+ logging.debug("Create Pnf %s", self.data["name"])
+ self._xnf = Pnf(self.data["name"])
+ if (vendor_name := self.data.get("vendor")) is not None:
+ self._xnf.vendor = Vendor(vendor_name)
+ self.onboard_resource_with_properties(self.data)
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.pnf is not None
+
+ @property
+ def pnf(self) -> Pnf:
+ """Pnf property.
+
+ Pnf which is represented by the data provided by user.
+
+ Returns:
+ Pnf: Pnf object
+
+ """
+ if (pnf := Pnf(name=self.data["name"])).created():
+ self._xnf = pnf
+ return self._xnf
+ return None
diff --git a/onap_data_provider/resources/project_resource.py b/onap_data_provider/resources/project_resource.py
new file mode 100644
index 0000000..e4c19c2
--- /dev/null
+++ b/onap_data_provider/resources/project_resource.py
@@ -0,0 +1,73 @@
+"""Project resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict, Optional
+
+from onapsdk.aai.business import Project # type: ignore
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+from .resource import Resource
+
+
+class ProjectResource(Resource):
+ """Project resource class.
+
+ Creates A&AI project.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize project resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._project: Optional[Project] = None
+
+ def create(self) -> None:
+ """Create project resource."""
+ logging.debug(f"Create Project {self.data['name']}")
+ if not self.exists:
+ self._project = Project.create(self.data["name"])
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return bool(self.project)
+
+ @property
+ def project(self) -> Project:
+ """Project property.
+
+ Project which is represented by the data provided by user.
+
+ Returns:
+ Project: Project object
+
+ """
+ if not self._project:
+ try:
+ self._project = Project.get_by_name(self.data["name"])
+ except ResourceNotFound:
+ return None
+ return self._project
diff --git a/onap_data_provider/resources/resource.py b/onap_data_provider/resources/resource.py
new file mode 100644
index 0000000..10477d1
--- /dev/null
+++ b/onap_data_provider/resources/resource.py
@@ -0,0 +1,45 @@
+"""Resource base module."""
+"""
+ Copyright 2021 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, abstractmethod
+from typing import Dict, Any
+
+
+class Resource(ABC):
+ """Base Resource class.
+
+ Abstract class which is a base for all other resource classes.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize resource.
+
+ Data contains all needed information to create resource.
+ It's readed from configuration file.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ self.data = data
+
+ @abstractmethod
+ def create(self) -> None:
+ """Create resource.
+
+ Abstract method to create resource
+
+ """
diff --git a/onap_data_provider/resources/resource_creator.py b/onap_data_provider/resources/resource_creator.py
new file mode 100644
index 0000000..34cbafd
--- /dev/null
+++ b/onap_data_provider/resources/resource_creator.py
@@ -0,0 +1,177 @@
+"""Resource creator module."""
+from __future__ import annotations
+
+"""
+ Copyright 2021 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 onap_data_provider.resources.platform_resource import PlatformResource
+import typing
+from abc import ABC
+
+from .aai_service_resource import AaiServiceResource
+from .cloud_region_resource import CloudRegionResource
+from .complex_resource import ComplexResource
+from .customer_resource import CustomerResource
+from .line_of_business_resource import LineOfBusinessResource
+from .msb_k8s_definition import MsbK8SDefinitionResource
+from .owning_entity_resource import OwningEntityResource
+from .pnf_resource import PnfResource
+from .project_resource import ProjectResource
+from .service_resource import ServiceResource
+from .service_instance_resource import (
+ ServiceInstanceResource,
+ ServiceInstanceResource_1_1,
+)
+from .vendor_resource import VendorResource
+from .vnf_resource import VnfResource
+from .vsp_resource import VspResource
+from ..versions import VersionsEnum
+
+if typing.TYPE_CHECKING:
+ from .resource import Resource
+
+
+class ResourceCreator(ABC):
+ """Resource creator.
+
+ Provides a method to create `Resource` instances.
+ """
+
+ RESOURCES_TYPES_DICT: typing.Mapping[
+ str, typing.Mapping[VersionsEnum, typing.Type[Resource]]
+ ] = {
+ "aai-service": {
+ VersionsEnum.NONE: AaiServiceResource,
+ VersionsEnum.V1_0: AaiServiceResource,
+ VersionsEnum.V1_1: AaiServiceResource,
+ },
+ "cloud-region": {
+ VersionsEnum.NONE: CloudRegionResource,
+ VersionsEnum.V1_0: CloudRegionResource,
+ VersionsEnum.V1_1: CloudRegionResource,
+ },
+ "complex": {
+ VersionsEnum.NONE: ComplexResource,
+ VersionsEnum.V1_0: ComplexResource,
+ VersionsEnum.V1_1: ComplexResource,
+ },
+ "customer": {
+ VersionsEnum.NONE: CustomerResource,
+ VersionsEnum.V1_0: CustomerResource,
+ VersionsEnum.V1_1: CustomerResource,
+ },
+ "vsp": {
+ VersionsEnum.NONE: VspResource,
+ VersionsEnum.V1_0: VspResource,
+ VersionsEnum.V1_1: VspResource,
+ },
+ "service": {
+ VersionsEnum.NONE: ServiceResource,
+ VersionsEnum.V1_0: ServiceResource,
+ VersionsEnum.V1_1: ServiceResource,
+ },
+ "vendor": {
+ VersionsEnum.NONE: VendorResource,
+ VersionsEnum.V1_0: VendorResource,
+ VersionsEnum.V1_1: VendorResource,
+ },
+ "pnf": {
+ VersionsEnum.NONE: PnfResource,
+ VersionsEnum.V1_0: PnfResource,
+ VersionsEnum.V1_1: PnfResource,
+ },
+ "vnf": {
+ VersionsEnum.NONE: VnfResource,
+ VersionsEnum.V1_0: VnfResource,
+ VersionsEnum.V1_1: VnfResource,
+ },
+ "service-instance": {
+ VersionsEnum.NONE: ServiceInstanceResource,
+ VersionsEnum.V1_0: ServiceInstanceResource,
+ VersionsEnum.V1_1: ServiceInstanceResource_1_1,
+ },
+ "line-of-business": {
+ VersionsEnum.NONE: LineOfBusinessResource,
+ VersionsEnum.V1_0: LineOfBusinessResource,
+ VersionsEnum.V1_1: LineOfBusinessResource,
+ },
+ "project": {
+ VersionsEnum.NONE: ProjectResource,
+ VersionsEnum.V1_0: ProjectResource,
+ VersionsEnum.V1_1: ProjectResource,
+ },
+ "platform": {
+ VersionsEnum.NONE: PlatformResource,
+ VersionsEnum.V1_0: PlatformResource,
+ VersionsEnum.V1_1: PlatformResource,
+ },
+ "owning-entity": {
+ VersionsEnum.NONE: OwningEntityResource,
+ VersionsEnum.V1_0: OwningEntityResource,
+ VersionsEnum.V1_1: OwningEntityResource,
+ },
+ "msb-k8s-definition": {
+ VersionsEnum.NONE: MsbK8SDefinitionResource,
+ VersionsEnum.V1_0: MsbK8SDefinitionResource,
+ VersionsEnum.V1_1: MsbK8SDefinitionResource,
+ },
+ }
+
+ @classmethod
+ def create(
+ cls,
+ resource_type: str,
+ data: typing.Dict[str, typing.Any],
+ version: VersionsEnum,
+ ) -> Resource:
+ """Resources factory method.
+
+ Based on provided `resource_type` creates `Resource` subclass.
+
+ Supported `resource_type` values:
+ - aai-service: AaiServiceResource
+ - cloud-region: CloudRegionResource
+ - complex: ComplexResource
+ - customer: CustomerResource
+ - vsp: VspResource
+ - service: ServiceResource
+ - vendor: VendorResource
+ - pnf: PnfResource
+ - vnf: VnfResource
+ - service-instance: ServiceInstanceResource
+ - line-of-business: LineOfBusinessResource
+ - project: ProjectResource
+ - platform: PlatformResource
+ - owning-entity: OwningEntityResource
+ - msb-k8s-definition: MsbK8SDefinitionResource
+
+ Args:
+ resource_type (str): Resource type to create
+ data (typing.Dict[str, typing.Any]): Resource data
+
+ Raises:
+ ValueError: Not support `resource_type` value provided.
+
+ Returns:
+ Resource: Created `Resource` subclass instance.
+
+ """
+ try:
+ return cls.RESOURCES_TYPES_DICT[resource_type][version](data)
+ except KeyError as key_error:
+ raise ValueError(
+ "Invalid resource type provided: %d", resource_type
+ ) from key_error
diff --git a/onap_data_provider/resources/service_instance_resource.py b/onap_data_provider/resources/service_instance_resource.py
new file mode 100644
index 0000000..b89f9df
--- /dev/null
+++ b/onap_data_provider/resources/service_instance_resource.py
@@ -0,0 +1,271 @@
+"""Service instance resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant # type: ignore
+from onapsdk.aai.business import Customer, OwningEntity # type: ignore
+from onapsdk.aai.service_design_and_creation import Service as AaiService # type: ignore
+from onapsdk.sdc.service import Service # type: ignore
+from onapsdk.vid import LineOfBusiness, Platform, Project # type: ignore
+from onapsdk.aai.business import ServiceSubscription
+from onapsdk.aai.business import ServiceInstance
+from onapsdk.so.instantiation import ( # type: ignore
+ ServiceInstantiation,
+ SoService,
+)
+
+from .resource import Resource
+from onapsdk.exceptions import APIError, ResourceNotFound # type: ignore
+
+
+class ServiceInstanceResource(Resource):
+ """Service instance resource class.
+
+ Creates service instance.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Service instance resource initialization.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create service instance
+
+ """
+ super().__init__(data)
+ self._customer: Customer = None
+ self._service_subscription: ServiceSubscription = None
+ self._service_instance: ServiceInstance = None
+ self._aai_service: AaiService = None
+
+ def create(self) -> None:
+ """Create ServiceInstance resource."""
+ if not self.exists:
+
+ service: Service = Service(name=self.data["service_name"])
+ if not service.distributed:
+ raise AttributeError(
+ "Service not distrbuted - instance can't be created"
+ )
+ if (cloud_region_id := self.data["cloud_region_id"]) is not None:
+ cloud_region: CloudRegion = CloudRegion.get_by_id(
+ cloud_owner=self.data["cloud_owner"],
+ cloud_region_id=cloud_region_id,
+ )
+ tenant: Tenant = cloud_region.get_tenant(self.data["tenant_id"])
+ self.service_subscription.link_to_cloud_region_and_tenant(
+ cloud_region, tenant
+ )
+ else:
+ cloud_region, tenant = None, None
+ try:
+ owning_entity = OwningEntity.get_by_owning_entity_name(
+ self.data["owning_entity"]
+ )
+ except APIError:
+ owning_entity = OwningEntity.create(self.data["owning_entity"])
+
+ try:
+ aai_service = next(
+ AaiService.get_all(service_id=self.data["aai_service"])
+ )
+ except StopIteration:
+ raise ValueError(
+ f"A&AI Service {self.data['aai_service']} does not exist"
+ )
+
+ service_instantiation: ServiceInstantiation = (
+ ServiceInstantiation.instantiate_macro(
+ sdc_service=service,
+ customer=self.customer,
+ owning_entity=owning_entity,
+ project=Project(self.data["project"]),
+ line_of_business=LineOfBusiness(self.data["line_of_business"]),
+ platform=Platform(self.data["platform"]),
+ cloud_region=cloud_region,
+ tenant=tenant,
+ service_instance_name=self.data["service_instance_name"],
+ so_service=self.so_service,
+ aai_service=aai_service,
+ )
+ )
+ service_instantiation.wait_for_finish(
+ timeout=self.data.get("timeout")
+ ) # 20 minutes timeout
+
+ if service_instantiation.failed == True:
+ logging.error(
+ "Service instantiation failed for %s",
+ self.data["service_instance_name"],
+ )
+ return
+ self._service_instance = (
+ self.service_subscription.get_service_instance_by_name(
+ self.data["service_instance_name"]
+ )
+ )
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.service_instance is not None
+
+ @property
+ def service_instance(self) -> ServiceInstance:
+ """Serviceinstance property.
+
+ Returns:
+ ServiceInstance: ServiceInstance object
+
+ """
+ if not self._service_instance:
+ try:
+ service_instance: ServiceInstance = (
+ self.service_subscription.get_service_instance_by_name(
+ self.data["service_instance_name"]
+ )
+ )
+ if service_instance:
+ self._service_instance = service_instance
+ except ResourceNotFound:
+ logging.error(
+ "Customer %s does not exist",
+ self.data["customer_id"],
+ )
+ return self._service_instance
+
+ @property
+ def customer(self) -> Customer:
+ """Access to Customer object property.
+
+ Returns:
+ Customer: Customer object
+
+ """
+ if not self._customer:
+ self._customer = Customer.get_by_global_customer_id(
+ self.data["customer_id"]
+ )
+ return self._customer
+
+ @property
+ def service_subscription(self) -> ServiceSubscription:
+ """Service subscription property.
+
+ Returns:
+ ServiceSubscription: ServiceSubscription object
+
+ """
+ if not self._service_subscription and self.customer:
+ self._service_subscription = (
+ self.customer.get_service_subscription_by_service_type(
+ service_type=self.data.get(
+ "service_subscription_type", self.data["service_name"]
+ )
+ )
+ )
+ return self._service_subscription
+
+ @property
+ def so_service(self) -> SoService:
+ """Create an object with parameters for the service instantiation.
+
+ Based on the instance definition data create an object
+ which is used for instantiation.
+
+ Returns:
+ SoService: SoService object
+
+ """
+ return SoService(
+ subscription_service_type=self.data.get(
+ "service_subscription_type", self.data["service_name"]
+ ),
+ vnfs=[
+ {
+ "model_name": vnf["vnf_name"],
+ "vnf_name": vnf.get("instance_name", vnf["vnf_name"]),
+ "parameters": vnf.get("parameters", {}),
+ "vf_modules": [
+ {
+ "model_name": vf_module["name"],
+ "vf_module_name": vf_module.get(
+ "instance_name", vf_module["name"]
+ ),
+ "parameters": vf_module.get("parameters", {}),
+ }
+ for vf_module in vnf.get("vf_modules", [])
+ ],
+ }
+ for vnf in self.data.get("instantiation_parameters", [])
+ ],
+ )
+
+ @property
+ def aai_service(self) -> AaiService:
+ """A&AI service which is used during the instantiation.
+
+ Raises:
+ ValueError: AaiService with given service id doesn't exist
+
+ Returns:
+ AaiService: AaiService object
+
+ """
+ if (
+ not self._aai_service
+ and (aai_service_id := self.data.get("aai_service")) is not None
+ ):
+ try:
+ self._aai_service = next(AaiService.get_all(service_id=aai_service_id))
+ except StopIteration:
+ raise ValueError(f"A&AI Service {aai_service_id} does not exist")
+ return self._aai_service
+
+
+class ServiceInstanceResource_1_1(ServiceInstanceResource):
+ """Service instance resource class.
+
+ That's the Service instance resource class for 1.1 schema version.
+ """
+
+ @property
+ def aai_service(self) -> AaiService:
+ """A&AI service which is used during the instantiation.
+
+ Raises:
+ ValueError: AaiService with given service id doesn't exist
+
+ Returns:
+ AaiService: AaiService object
+
+ """
+ if not self._aai_service:
+ try:
+ self._aai_service = next(
+ AaiService.get_all(service_id=self.data["aai_service"])
+ )
+ except StopIteration:
+ raise ValueError(
+ f"A&AI Service {self.data['aai_service']} does not exist"
+ )
+ return self._aai_service
diff --git a/onap_data_provider/resources/service_resource.py b/onap_data_provider/resources/service_resource.py
new file mode 100644
index 0000000..8489982
--- /dev/null
+++ b/onap_data_provider/resources/service_resource.py
@@ -0,0 +1,100 @@
+"""Service resource module."""
+"""
+ Copyright 2021 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 typing import Any, Dict, Mapping, Optional, Type
+
+from onapsdk.sdc.pnf import Pnf # type: ignore
+from onapsdk.sdc.properties import Property # type: ignore
+from onapsdk.sdc.sdc_resource import SdcResource # type: ignore
+from onapsdk.sdc.service import Service, ServiceInstantiationType # type: ignore
+from onapsdk.sdc.vf import Vf # type: ignore
+from onapsdk.sdc.vl import Vl # type: ignore
+
+from .resource import Resource
+
+
+class ServiceResource(Resource):
+ """Service resource class."""
+
+ RESOURCES: Mapping[str, Type[SdcResource]] = {
+ "PNF": Pnf,
+ "VF": Vf,
+ "VL": Vl,
+ }
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize Service resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._service: Optional[Service] = None
+
+ def create(self) -> None:
+ """Create Service resource."""
+ if not self.exists:
+ service = Service(
+ name=self.data["name"],
+ instantiation_type=ServiceInstantiationType.MACRO,
+ )
+ service.create()
+ for resource_data in self.data.get("resources", []):
+ resource = self.RESOURCES[resource_data["type"].upper()](
+ name=resource_data["name"]
+ )
+ service.add_resource(resource)
+ component = service.get_component(resource)
+ for prop_key, prop_value in resource_data.get("properties", {}).items():
+ prop = component.get_property(prop_key)
+ prop.value = prop_value
+ for property_data in self.data.get("properties", []):
+ service.add_property(
+ Property(
+ property_data["name"],
+ property_data["type"],
+ value=property_data.get("value"),
+ )
+ )
+ service.checkin()
+ service.onboard()
+ self._service = service
+
+ @property
+ def exists(self) -> bool:
+ """Check if Service exists in SDC.
+
+ Returns:
+ bool: True if Service exists, False otherwise
+
+ """
+ return self.service is not None and self.service.distributed
+
+ @property
+ def service(self) -> Optional[Service]:
+ """Service property.
+
+ Returns:
+ Service: Service object which is describer by provided data. None if does not exist yet.
+
+ """
+ if not self._service:
+ service: Service = Service(name=self.data["name"])
+ if not service.created():
+ return None
+ self._service = service
+ return self._service
diff --git a/onap_data_provider/resources/tenant_resource.py b/onap_data_provider/resources/tenant_resource.py
new file mode 100644
index 0000000..13d003f
--- /dev/null
+++ b/onap_data_provider/resources/tenant_resource.py
@@ -0,0 +1,85 @@
+"""Tenant resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict, Optional
+
+from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant # type: ignore
+
+from .resource import Resource
+from onapsdk.exceptions import ResourceNotFound # type: ignore
+
+
+class TenantResource(Resource):
+ """Tenant resource class.
+
+ Creates tenant.
+ """
+
+ def __init__(self, data: Dict[str, Any], cloud_region: CloudRegion) -> None:
+ """Tenant resource initialization.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create tenant
+ cloud_region (CloudRegion): Cloud region for which tenant is going to be created
+
+ """
+ super().__init__(data)
+ self.cloud_region: CloudRegion = cloud_region
+ self._tenant: Optional[Tenant] = None
+
+ def create(self) -> None:
+ """Create tenant resource.
+
+ Add tenant to provided cloud region
+
+ """
+ if not self.exists:
+ self.cloud_region.add_tenant(
+ tenant_id=self.data["tenant-id"],
+ tenant_name=self.data["tenant-name"],
+ tenant_context=self.data.get("tenant-context"),
+ )
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.tenant is not None
+
+ @property
+ def tenant(self) -> Tenant:
+ """Tenant property.
+
+ Returns:
+ Tenant: Tenant object
+
+ """
+ if not self._tenant:
+ try:
+ self._tenant = self.cloud_region.get_tenant(self.data["tenant-id"])
+ except ResourceNotFound:
+ logging.error(
+ "Tenant %s does not exist in %s cloud region",
+ self.data["tenant-id"],
+ self.cloud_region.cloud_region_id,
+ )
+ return None
+ return self._tenant
diff --git a/onap_data_provider/resources/vendor_resource.py b/onap_data_provider/resources/vendor_resource.py
new file mode 100644
index 0000000..14f2b18
--- /dev/null
+++ b/onap_data_provider/resources/vendor_resource.py
@@ -0,0 +1,75 @@
+"""Vendor resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.sdc.vendor import Vendor # type: ignore
+from .resource import Resource
+
+
+class VendorResource(Resource):
+ """Vendor resource class.
+
+ Creates vendor.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize vendor resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._vendor: Vendor = None
+
+ def create(self) -> None:
+ """Create vendor resource.
+
+ Create vendor resource.
+
+ """
+ if not self.exists:
+ logging.debug("Create Vendor %s", self.data["name"])
+ self._vendor = Vendor(name=self.data["name"])
+ self._vendor.onboard()
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.vendor is not None
+
+ @property
+ def vendor(self) -> Vendor:
+ """Vendor property.
+
+ Vendor which is represented by the data provided by user.
+
+ Returns:
+ Vendor: Vendor object
+
+ """
+ if (vendor := Vendor(name=self.data["name"])).created():
+ self._vendor = vendor
+ return self._vendor
+ return None
diff --git a/onap_data_provider/resources/vnf_resource.py b/onap_data_provider/resources/vnf_resource.py
new file mode 100644
index 0000000..1d47413
--- /dev/null
+++ b/onap_data_provider/resources/vnf_resource.py
@@ -0,0 +1,75 @@
+"""Vnf resource module."""
+"""
+ Copyright 2021 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 logging
+from typing import Any, Dict
+
+from onapsdk.sdc.vf import Vf # type: ignore
+from .resource import Resource
+from .xnf_resource import XnfResource
+
+
+class VnfResource(Resource, XnfResource):
+ """Vnf resource class.
+
+ Creates vnf.
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize vnf resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+
+ def create(self) -> None:
+ """Create vnf resource.
+
+ Create vnf resource and link to specified resources.
+
+ """
+ if not self.exists:
+ logging.debug("Create Vnf %s", self.data["name"])
+ self._xnf = Vf(name=self.data["name"])
+ self.onboard_resource_with_properties(self.data)
+
+ @property
+ def exists(self) -> bool:
+ """Determine if resource already exists or not.
+
+ Returns:
+ bool: True if object exists, False otherwise
+
+ """
+ return self.vnf is not None
+
+ @property
+ def vnf(self) -> Vf:
+ """Vnf property.
+
+ Vnf which is represented by the data provided by user.
+
+ Returns:
+ Vf: Vf object
+
+ """
+ if (vnf := Vf(name=self.data["name"])).created():
+ self._xnf = vnf
+ return self._xnf
+ return None
diff --git a/onap_data_provider/resources/vsp_resource.py b/onap_data_provider/resources/vsp_resource.py
new file mode 100644
index 0000000..17a4d5b
--- /dev/null
+++ b/onap_data_provider/resources/vsp_resource.py
@@ -0,0 +1,71 @@
+"""VSP resource module."""
+"""
+ Copyright 2021 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 typing import Any, Dict, Optional
+from onapsdk.sdc.vendor import Vendor # type: ignore
+from onapsdk.sdc.vsp import Vsp # type: ignore
+
+from .resource import Resource
+
+
+class VspResource(Resource):
+ """VSP resource class."""
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize VSP resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ super().__init__(data)
+ self._vsp: Optional[Vsp] = None
+
+ def create(self) -> None:
+ """Create VSP resource."""
+ if not self.exists:
+ with open(self.data["package"], "rb") as package:
+ self._vsp = Vsp(
+ name=self.data["name"],
+ vendor=Vendor(self.data["vendor"]),
+ package=package,
+ )
+ self._vsp.onboard()
+
+ @property
+ def exists(self) -> bool:
+ """Check if VSP exists.
+
+ Returns:
+ bool: True if VSP exists, False otherwise
+
+ """
+ return self.vsp is not None
+
+ @property
+ def vsp(self) -> Vsp:
+ """VSP property.
+
+ Returns:
+ Vsp: VSP object which is describer by provided data. None if does not exist yet.
+
+ """
+ if not self._vsp:
+ vsp: Vsp = Vsp(name=self.data["name"])
+ if not vsp.created():
+ return None
+ self._vsp = vsp
+ return self._vsp
diff --git a/onap_data_provider/resources/xnf_resource.py b/onap_data_provider/resources/xnf_resource.py
new file mode 100644
index 0000000..cada088
--- /dev/null
+++ b/onap_data_provider/resources/xnf_resource.py
@@ -0,0 +1,60 @@
+"""Xnf resource module."""
+"""
+ Copyright 2021 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 typing import Any, Dict
+from onapsdk.sdc.vsp import Vsp # type: ignore
+from onapsdk.sdc.sdc_resource import SdcResource # type: ignore
+from onapsdk.sdc.properties import Property # type: ignore
+
+
+class XnfResource(ABC):
+ """Xnf resource class.
+
+ Network function base class.
+ """
+
+ def __init__(self) -> None:
+ """Initialize xnf resource."""
+ self._xnf: SdcResource = None
+
+ def onboard_resource_with_properties(self, data: Dict[str, Any]) -> None:
+ """Set properties provided and instantiate SDC resource.
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+
+ """
+ if (vsp_name := data.get("vsp")) is not None:
+ self._xnf.vsp = Vsp(vsp_name)
+ self._xnf.create()
+ if (artifact_data := data.get("deployment_artifact")) is not None:
+ self._xnf.add_deployment_artifact(
+ artifact_type=data["deployment_artifact"]["artifact_type"],
+ artifact_name=data["deployment_artifact"]["artifact_name"],
+ artifact_label=data["deployment_artifact"]["artifact_label"],
+ artifact=data["deployment_artifact"]["artifact_file_name"],
+ )
+ for property_data in data.get("properties", []):
+ self._xnf.add_property(
+ Property(
+ name=property_data["name"],
+ property_type=property_data["type"],
+ value=property_data.get("value"),
+ )
+ )
+ self._xnf.onboard()