aboutsummaryrefslogtreecommitdiffstats
path: root/onap-client/onap_client/sdc
diff options
context:
space:
mode:
authorstark, steven <steven.stark@att.com>2020-03-11 14:30:58 -0700
committerstark, steven <steven.stark@att.com>2020-03-12 14:41:09 -0700
commitc02d3ed39e53d4ce56406a43089fc4a336c43f17 (patch)
tree8354fe71b2b4d379f36042b76c0e29775692f03e /onap-client/onap_client/sdc
parentd7d8722ce27e308defb6764d8d76f85ce7d63927 (diff)
[VVP] Adding onap-client intial commit.
This is supplementary tooling to interact with various ONAP applications. It will be used by the OVP VNF Testcase, it's not deployed with the ONAP platform. Issue-ID: VVP-381 Change-Id: I2ff3952ba8f4b9448acb5a24717ccc3b1f0a92fe Signed-off-by: stark, steven <steven.stark@att.com>
Diffstat (limited to 'onap-client/onap_client/sdc')
-rw-r--r--onap-client/onap_client/sdc/__init__.py40
-rw-r--r--onap-client/onap_client/sdc/catalog/__init__.py37
-rw-r--r--onap-client/onap_client/sdc/catalog/license_model_catalog.py318
-rw-r--r--onap-client/onap_client/sdc/catalog/service_catalog.py426
-rw-r--r--onap-client/onap_client/sdc/catalog/vnf_catalog.py410
-rw-r--r--onap-client/onap_client/sdc/catalog/vsp_catalog.py286
-rw-r--r--onap-client/onap_client/sdc/client.py81
-rw-r--r--onap-client/onap_client/sdc/license_model.py218
-rw-r--r--onap-client/onap_client/sdc/service.py426
-rw-r--r--onap-client/onap_client/sdc/tests/__init__.py0
-rw-r--r--onap-client/onap_client/sdc/tests/test.zipbin0 -> 428 bytes
-rw-r--r--onap-client/onap_client/sdc/tests/test_license_model.py125
-rw-r--r--onap-client/onap_client/sdc/tests/test_sdc_client.py68
-rw-r--r--onap-client/onap_client/sdc/tests/test_vnf.py172
-rw-r--r--onap-client/onap_client/sdc/tests/test_vsp.py118
-rw-r--r--onap-client/onap_client/sdc/vnf.py507
-rw-r--r--onap-client/onap_client/sdc/vsp.py213
17 files changed, 3445 insertions, 0 deletions
diff --git a/onap-client/onap_client/sdc/__init__.py b/onap-client/onap_client/sdc/__init__.py
new file mode 100644
index 0000000..d8028f6
--- /dev/null
+++ b/onap-client/onap_client/sdc/__init__.py
@@ -0,0 +1,40 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+from onap_client.config import APP_CONFIG
+
+SDC_PROPERTIES = APP_CONFIG.sdc
diff --git a/onap-client/onap_client/sdc/catalog/__init__.py b/onap-client/onap_client/sdc/catalog/__init__.py
new file mode 100644
index 0000000..d35e96a
--- /dev/null
+++ b/onap-client/onap_client/sdc/catalog/__init__.py
@@ -0,0 +1,37 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
diff --git a/onap-client/onap_client/sdc/catalog/license_model_catalog.py b/onap-client/onap_client/sdc/catalog/license_model_catalog.py
new file mode 100644
index 0000000..278645d
--- /dev/null
+++ b/onap-client/onap_client/sdc/catalog/license_model_catalog.py
@@ -0,0 +1,318 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import uuid
+from functools import partial
+
+from onap_client import sdc
+from onap_client import config
+from onap_client.sdc.client import SDCClient
+
+PAYLOADS_DIR = config.PAYLOADS_DIR
+sdc_properties = sdc.SDC_PROPERTIES
+application_id = config.APPLICATION_ID
+
+
+class LicenseModelClient(SDCClient):
+ @property
+ def catalog_resources(self):
+ return CATALOG_RESOURCES
+
+ @property
+ def namespace(self):
+ return "license_model"
+
+
+CATALOG_RESOURCES = {
+ "ADD_LICENSE_MODEL": {
+ "verb": "POST",
+ "description": "creates a license model in the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "payload": "{}/license_model.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["vendor_name"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {
+ "license_model_id": ("itemId",),
+ "license_model_version_id": ("version", "id"),
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_KEY_GROUP": {
+ "verb": "POST",
+ "description": "Adds a key group to a license model",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions/{license_model_version_id}/license-key-groups".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "uri-parameters": ["license_model_id", "license_model_version_id"],
+ "payload": "{}/key_group.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "license_start_date",
+ "license_end_date",
+ "key_group_name",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"key_group_id": ("value",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_ENTITLEMENT_POOL": {
+ "verb": "POST",
+ "description": "Adds an entitlement pool to a license model",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions/{license_model_version_id}/entitlement-pools".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "uri-parameters": ["license_model_id", "license_model_version_id"],
+ "payload": "{}/entitlement_pool.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "license_start_date",
+ "license_end_date",
+ "entitlement_pool_name",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"entitlement_pool_id": ("value",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_FEATURE_GROUP": {
+ "verb": "POST",
+ "description": "Adds an feature group to a license model",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions/{license_model_version_id}/feature-groups".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "uri-parameters": ["license_model_id", "license_model_version_id"],
+ "payload": "{}/feature_group.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "feature_group_name",
+ "key_group_id",
+ "entitlement_pool_id",
+ "manufacturer_reference_number",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"feature_group_id": ("value",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_LICENSE_AGREEMENT": {
+ "verb": "POST",
+ "description": "Adds an license agreement to a license model",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions/{license_model_version_id}/license-agreements".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "uri-parameters": ["license_model_id", "license_model_version_id"],
+ "payload": "{}/license_agreement.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["feature_group_id", "license_agreement_name"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"license_agreement_id": ("value",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "SUBMIT_LICENSE_MODEL": {
+ "verb": "PUT",
+ "description": "Submits a license model",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions/{license_model_version_id}/actions".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "uri-parameters": ["license_model_id", "license_model_version_id"],
+ "payload": "{}/action.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["action"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_LICENSE_MODEL": {
+ "verb": "GET",
+ "description": "Returns a license model",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions/{license_model_version_id}".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "uri-parameters": ["license_model_id", "license_model_version_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {
+ "vendor_name": ("vendorName",),
+ "license_model_id": ("id",),
+ "description": ("description",),
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_LICENSE_MODEL_VERSION_ATTRIBUTE": {
+ "verb": "GET",
+ "description": "Returns an attribute for a license model (license-agreements, features-groups, etc...)",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions/{license_model_version_id}/{attribute}".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_LICENSE_MODEL_PATH,
+ ),
+ "uri-parameters": ["license_model_id", "license_model_version_id", "attribute"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_LICENSE_MODEL_VERSIONS": {
+ "verb": "GET",
+ "description": "Returns the version list for a license model",
+ "uri": partial(
+ "{endpoint}{service_path}/{license_model_id}/versions".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_ITEMS_PATH,
+ ),
+ "uri-parameters": ["license_model_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_LICENSE_MODELS": {
+ "verb": "GET",
+ "description": "Returns the full list of license models from SDC",
+ "uri": partial(
+ "{endpoint}{service_path}?&itemType=vlm".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_ITEMS_PATH,
+ ),
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"results": ("results",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+}
diff --git a/onap-client/onap_client/sdc/catalog/service_catalog.py b/onap-client/onap_client/sdc/catalog/service_catalog.py
new file mode 100644
index 0000000..1d30725
--- /dev/null
+++ b/onap-client/onap_client/sdc/catalog/service_catalog.py
@@ -0,0 +1,426 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import uuid
+from functools import partial
+
+from onap_client import sdc
+from onap_client import config
+from onap_client.sdc.client import SDCClient
+
+PAYLOADS_DIR = config.PAYLOADS_DIR
+sdc_properties = sdc.SDC_PROPERTIES
+application_id = config.APPLICATION_ID
+
+
+class ServiceCatalog(SDCClient):
+ @property
+ def catalog_resources(self):
+ return CATALOG_RESOURCES
+
+ @property
+ def namespace(self):
+ return "service"
+
+
+CATALOG_RESOURCES = {
+ "ADD_CATALOG_SERVICE": {
+ "verb": "POST",
+ "description": "Creates a Service in the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "payload": "{}/catalog_service.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "service_name",
+ "instantiation_type",
+ "contact_id",
+ "category_name",
+ "category_id",
+ "category_name_lower",
+ "category_name_icon",
+ "tag",
+ "project_code",
+ "environment_context",
+ "ecomp_generated_naming",
+ "description",
+ "service_type",
+ "service_role",
+ "naming_policy",
+ ],
+ "success_code": 201,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_service_id": ("uniqueId",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_RESOURCE_INSTANCE": {
+ "verb": "POST",
+ "description": "Attaches a Resource to a Service",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/resourceInstance".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "payload": "{}/resource_instance.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "milli_timestamp",
+ "catalog_resource_id",
+ "catalog_resource_name",
+ "originType",
+ "posX",
+ "posY",
+ ],
+ "success_code": 201,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_resource_instance_id": ("uniqueId",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "CHECKIN_SERVICE": {
+ "verb": "POST",
+ "description": "Checks a service into the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/lifecycleState/checkin".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "payload": "{}/user_remarks.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["user_remarks"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "REQUEST_SERVICE_CERTIFICATION": {
+ "verb": "POST",
+ "description": "Requests certification of a service into the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/lifecycleState/certificationRequest".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "payload": "{}/user_remarks.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["user_remarks"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "START_SERVICE_CERTIFICATION": {
+ "verb": "POST",
+ "description": "Starts certification of a service into the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/lifecycleState/startCertification".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "payload": "{}/user_remarks.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["user_remarks"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_TESTER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "FINISH_SERVICE_CERTIFICATION": {
+ "verb": "POST",
+ "description": "Finishes certification of a service from the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/lifecycleState/certify".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "payload": "{}/user_remarks.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["user_remarks"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_TESTER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_service_id": ("uniqueId",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "APPROVE_SERVICE_CERTIFICATION": {
+ "verb": "POST",
+ "description": "Approves a service from the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/distribution-state/approve".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "payload": "{}/user_remarks.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["user_remarks"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_GOVERNOR_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "DISTRIBUTE_SDC_SERVICE": {
+ "verb": "POST",
+ "description": "Distributes a service from the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/distribution/PROD/activate".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_OPS_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_SERVICE_PROPERTY": {
+ "verb": "POST",
+ "description": "Add a property value for a VF in a Service",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/resourceInstance/{catalog_resource_instance_id}/properties".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id", "catalog_resource_instance_id"],
+ "payload": "{}/catalog_service_property.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "unique_id",
+ "parent_unique_id",
+ "owner_id",
+ "input_name",
+ "input_value",
+ "schema_type",
+ "property_type",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_SERVICE_INPUT": {
+ "verb": "POST",
+ "description": "Add an input value for a VF in a Service",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}/resourceInstance/{catalog_resource_instance_id}/inputs".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id", "catalog_resource_instance_id"],
+ "payload": "{}/catalog_service_property.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "unique_id",
+ "parent_unique_id",
+ "owner_id",
+ "input_name",
+ "input_value",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_SDC_SERVICE": {
+ "verb": "GET",
+ "description": "Gets a service from the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_service_id}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["catalog_service_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_SERVICES": {
+ "verb": "GET",
+ "description": "Get all services in the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_SCREEN_PATH,
+ ),
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"services": ("services",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_SERVICE_DISTRIBUTION": {
+ "verb": "GET",
+ "description": "Gets the distribution for a service from the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{distribution_service_id}/distribution".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["distribution_service_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_SERVICE_DISTRIBUTION_DETAILS": {
+ "verb": "GET",
+ "description": "Gets the distribution details for a service from the SDC Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/distribution/{distribution_id}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_SERVICES_PATH,
+ ),
+ "uri-parameters": ["distribution_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+}
diff --git a/onap-client/onap_client/sdc/catalog/vnf_catalog.py b/onap-client/onap_client/sdc/catalog/vnf_catalog.py
new file mode 100644
index 0000000..c4fd3da
--- /dev/null
+++ b/onap-client/onap_client/sdc/catalog/vnf_catalog.py
@@ -0,0 +1,410 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import uuid
+from functools import partial
+
+from onap_client import sdc
+from onap_client import config
+from onap_client.sdc.client import SDCClient
+
+PAYLOADS_DIR = config.PAYLOADS_DIR
+sdc_properties = sdc.SDC_PROPERTIES
+application_id = config.APPLICATION_ID
+
+
+class VNFCatalog(SDCClient):
+ @property
+ def catalog_resources(self):
+ return CATALOG_RESOURCES
+
+ @property
+ def namespace(self):
+ return "vnf"
+
+
+CATALOG_RESOURCES = {
+ "ADD_CATALOG_RESOURCE": {
+ "verb": "POST",
+ "description": "Adds a VNF to the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "payload": "{}/catalog_resource.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "software_product_id",
+ "vnf_name",
+ "vendor_name",
+ "resource_type",
+ ],
+ "success_code": 201,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_resource_id": ("uniqueId",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "CERTIFY_CATALOG_RESOURCE": {
+ "verb": "POST",
+ "description": "Certifies a VNF in the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/lifecycleState/certify".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_resource_id"],
+ "payload": "{}/user_remarks.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["user_remarks"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_resource_id": ("uniqueId",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_RESOURCE_INPUT": {
+ "verb": "POST",
+ "description": "Adds an input value for a VNF",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/update/inputs".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "payload": "{}/catalog_vnf_input.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "input_default_value",
+ "input_name",
+ "input_parent_unique_id",
+ "input_unique_id",
+ "input_owner_id",
+ ],
+ "uri-parameters": ["catalog_resource_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_RESOURCE_PROPERTY": {
+ "verb": "POST",
+ "description": "Adds an property value for a VNF",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/resourceInstance/{catalog_resource_instance_id}/inputs".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "payload": "{}/catalog_vnf_property.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "unique_id",
+ "parent_unique_id",
+ "owner_id",
+ "property_name",
+ "property_default_value",
+ "schema_type",
+ "property_type",
+ ],
+ "uri-parameters": ["catalog_resource_id", "catalog_resource_instance_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_RESOURCE_POLICY": {
+ "verb": "POST",
+ "description": "Adds an policy resource to a VNF",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/policies/{catalog_policy_name}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_resource_id", "catalog_policy_name"],
+ "success_code": 201,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_resource_id": ("uniqueId",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_POLICY_PROPERTY": {
+ "verb": "PUT",
+ "description": "Adds a property to a policy for a VNF",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/policies/{catalog_policy_id}/properties".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_resource_id", "catalog_policy_id"],
+ "payload": "{}/catalog_vnf_policy_property.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "unique_id",
+ "property_name",
+ "property_default_value",
+ "description",
+ "property_type",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_RESOURCE_GROUP": {
+ "verb": "POST",
+ "description": "Adds an group resource to a VNF",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/groups/{catalog_group_name}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_resource_id", "catalog_group_name"],
+ "success_code": 201,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_resource_id": ("uniqueId",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_CATALOG_GROUP_PROPERTY": {
+ "verb": "PUT",
+ "description": "Adds a property to a group for a VNF",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/groups/{catalog_group_id}/properties".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_resource_id", "catalog_group_id"],
+ "payload": "{}/catalog_vnf_group_property.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "unique_id",
+ "property_name",
+ "property_default_value",
+ "description",
+ "property_type",
+ "owner_id",
+ "parent_unique_id",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_GROUP_TO_INSTANCE": {
+ "verb": "POST",
+ "description": "Associate a group with a Catalog Instance",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/groups/{catalog_group_id}/members".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "payload": "{}/catalog_vnf_group.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["instance_id"],
+ "uri-parameters": ["catalog_resource_id", "catalog_group_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_POLICY_TO_INSTANCE": {
+ "verb": "POST",
+ "description": "Associate a policy with a Catalog Instance",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/policies/{catalog_policy_id}/targets".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "payload": "{}/catalog_vnf_policy.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["instance_ids"],
+ "uri-parameters": ["catalog_resource_id", "catalog_policy_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_RESOURCE_INSTANCE": {
+ "verb": "POST",
+ "description": "Attaches a Resource to a VNF",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}/resourceInstance".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_resource_id"],
+ "payload": "{}/resource_instance_vnf.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "milli_timestamp",
+ "new_catalog_resource_id",
+ "new_catalog_resource_name",
+ "originType",
+ "posX",
+ "posY",
+ ],
+ "success_code": 201,
+ "return_data": {"catalog_resource_instance_id": ("uniqueId",)},
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_CATALOG_RESOURCE": {
+ "verb": "GET",
+ "description": "Gets a VNF in the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{catalog_resource_id}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_CATALOG_RESOURCES_PATH,
+ ),
+ "uri-parameters": ["catalog_resource_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"catalog_resource_name": ("name",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_RESOURCES": {
+ "verb": "GET",
+ "description": "Get all resources in the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}".format,
+ endpoint=sdc_properties.SDC_BE_ENDPOINT,
+ service_path=sdc_properties.SDC_SCREEN_PATH,
+ ),
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"resources": ("resources",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+}
diff --git a/onap-client/onap_client/sdc/catalog/vsp_catalog.py b/onap-client/onap_client/sdc/catalog/vsp_catalog.py
new file mode 100644
index 0000000..65781a6
--- /dev/null
+++ b/onap-client/onap_client/sdc/catalog/vsp_catalog.py
@@ -0,0 +1,286 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import uuid
+from functools import partial
+
+from onap_client import sdc
+from onap_client import config
+from onap_client.sdc.client import SDCClient
+
+PAYLOADS_DIR = config.PAYLOADS_DIR
+sdc_properties = sdc.SDC_PROPERTIES
+application_id = config.APPLICATION_ID
+
+
+class VSPCatalog(SDCClient):
+ @property
+ def catalog_resources(self):
+ return CATALOG_RESOURCES
+
+ @property
+ def namespace(self):
+ return "vsp"
+
+
+CATALOG_RESOURCES = {
+ "ADD_SOFTWARE_PRODUCT": {
+ "verb": "POST",
+ "description": "Creates a VSP in the SDC catalog",
+ "uri": partial(
+ "{endpoint}{service_path}".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_SOFTWARE_PRODUCT_PATH,
+ ),
+ "payload": "{}/software_product.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": [
+ "software_product_name",
+ "feature_group_id",
+ "license_agreement_id",
+ "vendor_name",
+ "license_model_id",
+ "license_model_version_id",
+ "description",
+ "category",
+ "sub_category",
+ ],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {
+ "software_product_id": ("itemId",),
+ "software_product_version_id": ("version", "id"),
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "UPLOAD_HEAT_PACKAGE": {
+ "verb": "POST",
+ "description": "Uploads a heat zip to a VSP",
+ "uri": partial(
+ "{endpoint}{service_path}/{software_product_id}/versions/{software_product_version_id}/orchestration-template-candidate".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_SOFTWARE_PRODUCT_PATH,
+ ),
+ "uri-parameters": ["software_product_id", "software_product_version_id"],
+ "files-parameters": ["file_path", "file_type"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "multipart/form-data",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "VALIDATE_SOFTWARE_PRODUCT": {
+ "verb": "PUT",
+ "description": "Validates VSP with Heat Zip",
+ "uri": partial(
+ "{endpoint}{service_path}/{software_product_id}/versions/{software_product_version_id}/orchestration-template-candidate/process".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_SOFTWARE_PRODUCT_PATH,
+ ),
+ "uri-parameters": ["software_product_id", "software_product_version_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "SUBMIT_SOFTWARE_PRODUCT": {
+ "verb": "PUT",
+ "description": "Submits Heat Zip to VSP",
+ "uri": partial(
+ "{endpoint}{service_path}/{software_product_id}/versions/{software_product_version_id}/actions".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_SOFTWARE_PRODUCT_PATH,
+ ),
+ "uri-parameters": ["software_product_id", "software_product_version_id"],
+ "payload": "{}/action.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["action"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "PACKAGE_SOFTWARE_PRODUCT": {
+ "verb": "PUT",
+ "description": "Packages VSP (description needs to be better??)",
+ "uri": partial(
+ "{endpoint}{service_path}/{software_product_id}/versions/{software_product_version_id}/actions".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_SOFTWARE_PRODUCT_PATH,
+ ),
+ "uri-parameters": ["software_product_id", "software_product_version_id"],
+ "payload": "{}/action.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["action"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_SOFTWARE_PRODUCT": {
+ "verb": "GET",
+ "description": "Gets VSP from Catalog",
+ "uri": partial(
+ "{endpoint}{service_path}/{software_product_id}/versions/{software_product_version_id}".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_SOFTWARE_PRODUCT_PATH,
+ ),
+ "uri-parameters": ["software_product_id", "software_product_version_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"name": ("name",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_SOFTWARE_PRODUCT_VERSIONS": {
+ "verb": "GET",
+ "description": "Returns a list of vsp versions",
+ "uri": partial(
+ "{endpoint}{service_path}/{software_product_id}/versions".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_ITEMS_PATH,
+ ),
+ "uri-parameters": ["software_product_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {
+ "software_product_version_id": ("id",),
+ "description": ("description",),
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "GET_SOFTWARE_PRODUCTS": {
+ "verb": "GET",
+ "description": "Returns a list of vsps",
+ "uri": partial(
+ "{endpoint}{service_path}?&itemType=vsp".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_ITEMS_PATH,
+ ),
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "return_data": {"results": ("results",)},
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+ "ADD_VSP_CONTRIBUTER": {
+ "verb": "PUT",
+ "description": "Adds a user to a VSP as a contributer",
+ "uri": partial(
+ "{endpoint}{service_path}/{software_product_id}/permissions/Contributor".format,
+ endpoint=sdc_properties.SDC_BE_ONBOARD_ENDPOINT,
+ service_path=sdc_properties.SDC_VENDOR_ITEMS_PATH,
+ ),
+ "uri-parameters": ["software_product_id"],
+ "payload": "{}/add_vsp_contributer.jinja".format(PAYLOADS_DIR),
+ "payload-parameters": ["user_id"],
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.GLOBAL_SDC_USERNAME,
+ sdc_properties.GLOBAL_SDC_PASSWORD,
+ ),
+ },
+}
diff --git a/onap-client/onap_client/sdc/client.py b/onap-client/onap_client/sdc/client.py
new file mode 100644
index 0000000..8863e07
--- /dev/null
+++ b/onap-client/onap_client/sdc/client.py
@@ -0,0 +1,81 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import uuid
+
+from functools import partial
+from onap_client import sdc
+from onap_client.client.clients import Client
+from onap_client import config
+
+sdc_properties = sdc.SDC_PROPERTIES
+application_id = config.APPLICATION_ID
+
+
+class SDCClient(Client):
+ @property
+ def namespace(self):
+ return "sdc"
+
+ @property
+ def catalog_resources(self):
+ return CATALOG_RESOURCES
+
+
+CATALOG_RESOURCES = {
+ "HEALTH_CHECK": {
+ "verb": "GET",
+ "description": "Queries SDC health check endpoint",
+ "uri": partial(
+ "{endpoint}{service_path}".format,
+ endpoint=sdc_properties.SDC_HC_ENDPOINT,
+ service_path=sdc_properties.SDC_HEALTH_CHECK_PATH,
+ ),
+ "success_code": 200,
+ "headers": {
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "USER_ID": sdc_properties.SDC_DESIGNER_USER_ID,
+ "X-TransactionId": str(uuid.uuid4()),
+ "X-FromAppId": application_id,
+ },
+ "auth": (
+ sdc_properties.SDC_DESIGNER_USER_ID,
+ sdc_properties.SDC_DESIGNER_PASSWORD,
+ ),
+ },
+}
diff --git a/onap-client/onap_client/sdc/license_model.py b/onap-client/onap_client/sdc/license_model.py
new file mode 100644
index 0000000..e5ae740
--- /dev/null
+++ b/onap-client/onap_client/sdc/license_model.py
@@ -0,0 +1,218 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+from onap_client.lib import generate_dummy_string, generate_dummy_date
+from onap_client.resource import Resource
+from onap_client.client.clients import Client as SDCClient
+
+license_model_client = SDCClient().sdc.license_model
+
+
+class LicenseModel(Resource):
+ resource_name = "LICENSE_MODEL"
+ spec = {
+ "vendor_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_vendor_"),
+ },
+ "mfr_ref_number": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("mfref"),
+ },
+ "entitlement_pool_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_kg_"),
+ },
+ "key_group_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_ep_"),
+ },
+ "feature_group_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_fg_"),
+ },
+ "license_agreement_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_la_"),
+ },
+ "license_start_date": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_date(days=1),
+ },
+ "license_end_date": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_date(days=365),
+ },
+ }
+
+ def __init__(
+ self,
+ vendor_name,
+ mfr_ref_number,
+ entitlement_pool_name,
+ key_group_name,
+ feature_group_name,
+ license_agreement_name,
+ license_start_date,
+ license_end_date,
+ ):
+
+ license_input = {}
+ license_input["vendor_name"] = vendor_name
+ license_input["manufacturer_reference_number"] = mfr_ref_number
+ license_input["entitlement_pool_name"] = entitlement_pool_name
+ license_input["key_group_name"] = key_group_name
+ license_input["feature_group_name"] = feature_group_name
+ license_input["license_agreement_name"] = license_agreement_name
+ license_input["license_start_date"] = license_start_date
+ license_input["license_end_date"] = license_end_date
+
+ super().__init__(license_input)
+
+ def _create(self, license_input):
+ """Creates a license model object in SDC"""
+ return create_license_model(license_input)
+
+ def _post_create(self):
+ pass
+
+ def _submit(self):
+ """Submits the license model in SDC"""
+
+ license_model_client.submit_license_model(**self.attributes, action="Submit")
+
+ license_model = license_model_client.get_license_model(**self.attributes)
+ self.attributes["tosca"] = license_model.response_data
+
+
+# TODO
+# Break this up into class funcs?
+def create_license_model(license_input):
+ """Creates a license model object in SDC
+
+ :license_input: dictionary with values to input for lm creation
+
+ :return: dictionary of updated values for created lm
+ """
+ kwargs = license_input
+ license_model = license_model_client.add_license_model(**kwargs)
+
+ kwargs["license_model_id"] = license_model.license_model_id
+ kwargs["license_model_version_id"] = license_model.license_model_version_id
+
+ key_group = license_model_client.add_key_group(**kwargs)
+ key_group_id = key_group.key_group_id
+
+ entitlement_pool = license_model_client.add_entitlement_pool(**kwargs)
+ entitlement_pool_id = entitlement_pool.entitlement_pool_id
+
+ kwargs["entitlement_pool_id"] = entitlement_pool_id
+ kwargs["key_group_id"] = key_group_id
+
+ feature_group = license_model_client.add_feature_group(**kwargs)
+ feature_group_id = feature_group.feature_group_id
+
+ kwargs["feature_group_id"] = feature_group_id
+
+ license_agreement = license_model_client.add_license_agreement(**kwargs)
+ kwargs["license_agreement_id"] = license_agreement.license_agreement_id
+
+ license_model = license_model_client.get_license_model(**kwargs)
+ kwargs["tosca"] = license_model.response_data
+
+ return kwargs
+
+
+def get_license_model_id(license_model_name):
+ """GETs license model UUID from SDC
+
+ :license_model_name: name of license model in SDC
+
+ :return: uuid of lm or None
+ """
+ response = license_model_client.get_license_models()
+ results = response.response_data.get("results")
+ for license_model in results:
+ if license_model.get("name") == license_model_name:
+ return license_model.get("id")
+ return None
+
+
+def get_license_model_version_id(license_model_id):
+ """GETs license model version UUID from SDC
+
+ :license_model_id: uuid of license model in SDC
+
+ :return: uuid of lm version id or None
+ """
+ license_model_version_id = None
+ creation_time = -1
+ response = license_model_client.get_license_model_versions(
+ license_model_id=license_model_id
+ )
+ results = response.response_data.get("results")
+ for version in results:
+ if version.get("creationTime", 0) > creation_time:
+ creation_time = version.get("creationTime")
+ license_model_version_id = version.get("id")
+
+ return license_model_version_id
+
+
+def get_license_model_attribute(license_model_id, license_model_version_id, attribute):
+ """GETs license model attribute from SDC
+
+ :license_model_id: uuid of license model in SDC
+ :license_model_version_id: uuid of license model version in SDC
+ :attribute: attribute to GET (license-agreements, feature-groups, entitlement-pools, license-key-groups)
+
+ :return: uuid of attribute of license-model
+ """
+ response = license_model_client.get_license_model_version_attribute(
+ license_model_id=license_model_id,
+ license_model_version_id=license_model_version_id,
+ attribute=attribute,
+ )
+ return response.response_data.get("results")[0]
diff --git a/onap-client/onap_client/sdc/service.py b/onap-client/onap_client/sdc/service.py
new file mode 100644
index 0000000..4e3dd03
--- /dev/null
+++ b/onap-client/onap_client/sdc/service.py
@@ -0,0 +1,426 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+from onap_client.lib import generate_dummy_string
+from onap_client.resource import Resource
+from onap_client import exceptions
+from onap_client.client.clients import Client as SDCClient
+from onap_client.sdc.vnf import get_vnf_id
+from onap_client import sdc
+from onap_client.sdc import SDC_PROPERTIES
+from onap_client.util import utility
+
+import time
+import json
+import random
+
+service_client = SDCClient().sdc.service
+sdc_properties = sdc.SDC_PROPERTIES
+
+
+def normalize_category_icon(category_name):
+ if category_name == "Network L1-3":
+ return "network_l_4"
+ elif category_name == "Mobility":
+ return "mobility"
+ elif category_name == "E2E Service":
+ return "network_l_1-3"
+ elif category_name == "Network L1-3":
+ return "network_l_1-3"
+ elif category_name == "Network Service":
+ return "network_l_1-3"
+ elif category_name == "Network 4+":
+ return "network_l_4"
+ elif category_name == "VoIP Call Control":
+ return "call_controll"
+ else:
+ return "network_l_1-3"
+
+
+class Service(Resource):
+ resource_name = "SERVICE"
+ spec = {
+ "instantiation_type": {
+ "type": str,
+ "required": False,
+ "default": "A-la-carte",
+ },
+ "service_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_service_"),
+ },
+ "contact_id": {"type": str, "required": False, "default": "cs0008"},
+ "category_name": {"type": str, "required": False, "default": "Network L1-3"},
+ "tag": {"type": str, "required": False, "default": "robot-ete"},
+ "project_code": {"type": str, "required": False, "default": "123456"},
+ "environment_context": {
+ "type": str,
+ "required": False,
+ "default": "General_Revenue-Bearing",
+ },
+ "ecomp_generated_naming": {"type": str, "required": False, "default": "true"},
+ "description": {
+ "type": str,
+ "required": False,
+ "default": "Brand New Service",
+ },
+ "service_type": {"type": str, "required": False, "default": ""},
+ "service_role": {"type": str, "required": False, "default": ""},
+ "naming_policy": {"type": str, "required": False, "default": ""},
+ "resources": {
+ "type": list,
+ "list_item": dict,
+ "required": False,
+ "default": [],
+ "nested": {
+ "resource_name": {"type": str, "required": True},
+ "resource_id": {"type": str, "required": False},
+ "catalog_resource_name": {"type": str, "required": False},
+ "origin_type": {"type": str, "required": False, "default": "VF"},
+ "properties": {"type": dict, "required": False, "default": {}},
+ },
+ },
+ "wait_for_distribution": {"type": bool, "required": False, "default": False},
+ }
+
+ def __init__(
+ self,
+ instantiation_type,
+ service_name,
+ contact_id,
+ category_name,
+ tag,
+ project_code,
+ environment_context,
+ ecomp_generated_naming,
+ description,
+ service_type,
+ service_role,
+ naming_policy,
+ resources=[],
+ wait_for_distribution=False,
+ ):
+ service_input = {}
+
+ category_name_lower = category_name.lower()
+ category_name_icon = normalize_category_icon(category_name)
+ category_id = "serviceNewCategory.{}".format(category_name_lower)
+
+ service_input["service_name"] = service_name
+ service_input["instantiation_type"] = instantiation_type
+ service_input["contact_id"] = contact_id
+ service_input["category_name"] = category_name
+ service_input["category_id"] = category_id
+ service_input["category_name_lower"] = category_name_lower
+ service_input["category_name_icon"] = category_name_icon
+ service_input["tag"] = tag
+ service_input["project_code"] = project_code
+ service_input["environment_context"] = environment_context
+ service_input["ecomp_generated_naming"] = ecomp_generated_naming
+ service_input["description"] = description
+ service_input["service_type"] = service_type
+ service_input["service_role"] = service_role
+ service_input["naming_policy"] = naming_policy
+ service_input["resources"] = resources
+ service_input["wait_for_distribution"] = wait_for_distribution
+
+ super().__init__(service_input)
+
+ def _create(self, service_input):
+ """Creates a service object in SDC"""
+ service = None
+
+ if get_service_id(service_input.get("service_name")) is None:
+ service = create_service(service_input)
+ else:
+ raise exceptions.ResourceAlreadyExistsException(
+ "Service resource {} already exists".format(
+ service_input.get("service_name")
+ )
+ )
+
+ return service
+
+ def _post_create(self):
+ resources = self.resources
+
+ for resource in resources:
+ resource_name = resource.get("resource_name")
+ catalog_resource_name = resource.get("catalog_resource_name")
+ resource_id = resource.get("resource_id")
+ resource_properties = resource.get("properties")
+ if not resource_id:
+ resource_id = get_vnf_id(catalog_resource_name)
+ if not resource_id:
+ raise exceptions.ResourceIDNotFoundException(
+ "resource ID was not passed, and resource lookup by name was not found {}".format(
+ resource_name
+ )
+ )
+ resource_origin = resource.get("origin_type")
+ self.add_resource(resource_id, resource_name, origin_type=resource_origin)
+ for k, v in resource_properties.items():
+ if isinstance(v, dict):
+ v = json.dumps(v).replace('"', '\\"')
+ self.add_property_value(resource_name, k, v)
+
+ def _submit(self):
+ """Submits the service in SDC and distributes the model"""
+ DISTRIBUTION_STEPS = sdc_properties.SERVICE_DISTRIBUTION or []
+
+ service_client.checkin_service(**self.attributes, user_remarks="checking in")
+
+ if (
+ not DISTRIBUTION_STEPS
+ or "request_service_certification" in DISTRIBUTION_STEPS
+ ):
+ service_client.request_service_certification(
+ **self.attributes, user_remarks="requesting certification"
+ )
+
+ if (
+ not DISTRIBUTION_STEPS
+ or "start_service_certification" in DISTRIBUTION_STEPS
+ ):
+ service_client.start_service_certification(
+ **self.attributes, user_remarks="certifying"
+ )
+
+ if (
+ not DISTRIBUTION_STEPS
+ or "finish_service_certification" in DISTRIBUTION_STEPS
+ ):
+ catalog_service = service_client.finish_service_certification(
+ **self.attributes, user_remarks="certified"
+ )
+ self.attributes["catalog_service_id"] = catalog_service.catalog_service_id
+
+ if (
+ not DISTRIBUTION_STEPS
+ or "approve_service_certification" in DISTRIBUTION_STEPS
+ ):
+ service_client.approve_service_certification(
+ **self.attributes, user_remarks="approved"
+ )
+
+ service_client.distribute_sdc_service(**self.attributes)
+
+ if self.wait_for_distribution:
+ poll_distribution(self.service_name)
+
+ self._refresh()
+
+ def add_resource(
+ self, catalog_resource_id, catalog_resource_name, origin_type="VF"
+ ):
+ """Attaches a resource to a Service in SDC
+
+ :catalog_resource_id: ID of a resource in the SDC catalog
+ :catalog_resource_name: name to give to the resource when attaching to service
+ :origin_type: specifies the origin of the attached resource
+
+ """
+ milli_timestamp = int(time.time() * 1000)
+
+ resource_instance = service_client.add_resource_instance(
+ **self.attributes,
+ posX=random.randrange(150, 550), # nosec
+ posY=random.randrange(150, 450), # nosec
+ milli_timestamp=milli_timestamp,
+ catalog_resource_id=catalog_resource_id,
+ catalog_resource_name=catalog_resource_name,
+ originType=origin_type,
+ )
+
+ response = {
+ "id": resource_instance.catalog_resource_instance_id,
+ "tosca": resource_instance.response_data,
+ }
+ self.attributes[catalog_resource_name] = response
+
+ self._refresh()
+
+ def add_property_value(self, resource_name, property_name, input_value):
+ """Updates an property value on a resource attached to a Service
+
+ :resource_name: Name of a resource attached to a service
+ :property_name: property name to update
+ :input_value: value to update property with
+
+ """
+ resource = self.attributes.get(resource_name)
+ if not resource:
+ raise exceptions.ResourceNotFoundException(
+ "Resource {} was not found on Service {}".format(
+ resource_name, self.service_name
+ )
+ )
+ resource_id = resource["id"]
+
+ instance_inputs = self.tosca.get("componentInstancesProperties", {}).get(
+ resource_id, []
+ )
+ for prop in instance_inputs:
+ if prop.get("name") == property_name:
+ unique_id = prop.get("uniqueId")
+ parent_unique_id = prop.get("parentUniqueId")
+ owner_id = prop.get("ownerId")
+ schemaType = prop.get("schemaType", "")
+ property_type = prop.get("type")
+ return service_client.add_catalog_service_property(
+ **self.attributes,
+ unique_id=unique_id,
+ parent_unique_id=parent_unique_id,
+ owner_id=owner_id,
+ catalog_resource_instance_id=resource_id,
+ input_name=property_name,
+ input_value=input_value,
+ schema_type=schemaType,
+ property_type=property_type,
+ )
+
+ raise exceptions.PropertyNotFoundException(
+ "Property {} was not found in VF Instance {}".format(
+ property_name, resource_id
+ )
+ )
+
+ def _refresh(self):
+ self.tosca = service_client.get_sdc_service(
+ catalog_service_id=self.catalog_service_id
+ ).response_data
+
+
+def create_service(service_input):
+ """Creates a service object in SDC
+
+ :service_input: dictionary with values to input for service creation
+
+ :return: dictionary of updated values for created service
+ """
+ kwargs = service_input
+
+ service = service_client.add_catalog_service(**kwargs)
+
+ kwargs["catalog_service_id"] = service.catalog_service_id
+ kwargs["tosca"] = service.response_data
+
+ return kwargs
+
+
+@utility
+def get_service(service_name):
+ """Queries SDC for the TOSCA model for a service"""
+ return service_client.get_sdc_service(
+ catalog_service_id=get_service_id(service_name)
+ ).response_data
+
+
+@utility
+def get_service_id(service_name):
+ """Queries SDC for the uniqueId of a service model"""
+ response = service_client.get_services()
+ results = response.response_data.get("services", [])
+ for service in results:
+ if service.get("name") == service_name:
+ return service["uniqueId"]
+ return None
+
+
+def get_service_uuid(service_name):
+ return get_service(service_name).get("uuid")
+
+
+def get_service_distribution(service_name):
+ distribution_id = get_distribution_id(service_name)
+
+ if distribution_id:
+ return service_client.get_service_distribution_details(
+ distribution_id=distribution_id
+ ).response_data
+
+ return None
+
+
+def get_distribution_id(service_name):
+ distribution = service_client.get_service_distribution(
+ distribution_service_id=get_service_uuid(service_name)
+ ).response_data
+ if distribution:
+ details = distribution.get("distributionStatusOfServiceList", [])
+ for entry in details:
+ return entry.get("distributionID")
+
+ return None
+
+
+@utility
+def poll_distribution(service_name):
+ """Polls a distributed service until distribution is complete"""
+ poll_interval = SDC_PROPERTIES.POLL_INTERVAL or 30
+ x = 0
+ while x < 30:
+ distribution = get_service_distribution(service_name)
+ if not distribution:
+ raise exceptions.DistributionNotFound(
+ "Could not determine distribution status for {}".format(service_name)
+ )
+ distribution_list = distribution.get("distributionStatusList")
+ for component in distribution_list:
+ status = component.get("status")
+ component_name = component.get("omfComponentID")
+ if status == "DISTRIBUTION_COMPLETE_ERROR":
+ raise exceptions.DistributionFailure(
+ "Distribution failure for service {}, component details {}".format(
+ service_name, component
+ )
+ )
+ elif status == "COMPONENT_DONE_ERROR" and component_name == "aai-ml":
+ raise exceptions.DistributionFailure(
+ "Distribution failure for service {}, component details {}".format(
+ service_name, component
+ )
+ )
+ elif status == "DISTRIBUTION_COMPLETE_OK":
+ return "Distribution Successful"
+ x += 1
+ time.sleep(poll_interval)
+
+ raise exceptions.DistributionTimeout(
+ "Distribution polling timed out waiting for {}".format(service_name)
+ )
diff --git a/onap-client/onap_client/sdc/tests/__init__.py b/onap-client/onap_client/sdc/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/onap-client/onap_client/sdc/tests/__init__.py
diff --git a/onap-client/onap_client/sdc/tests/test.zip b/onap-client/onap_client/sdc/tests/test.zip
new file mode 100644
index 0000000..37b2ed1
--- /dev/null
+++ b/onap-client/onap_client/sdc/tests/test.zip
Binary files differ
diff --git a/onap-client/onap_client/sdc/tests/test_license_model.py b/onap-client/onap_client/sdc/tests/test_license_model.py
new file mode 100644
index 0000000..459c2e0
--- /dev/null
+++ b/onap-client/onap_client/sdc/tests/test_license_model.py
@@ -0,0 +1,125 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import responses
+from onap_client.client.clients import Client
+from onap_client.sdc.license_model import LicenseModel
+from onap_client.tests.utils import mockup_client, mockup_catalog_item
+
+license_model_client = Client().sdc.license_model
+
+
+@responses.activate
+def test_license_model_create():
+ LICENSE_MODEL_ID = "license_model_id"
+ LICENSE_MODEL_VERSION_ID = "license_model_version_id"
+ FEATURE_GROUP_ID = "feature_group_id"
+ KEYGROUP_ID = "key_group_id"
+ ENTITLEMENT_POOL_ID = "entitlement_pool_id"
+ LICENSE_AGREEMENT_ID = "license_agreement_id"
+ VENDOR_NAME = "vendor_name"
+ ID = "id"
+ DESCRIPTION = "description"
+
+ mockup_catalog_item(
+ license_model_client.catalog_items["ADD_LICENSE_MODEL"],
+ override_return_data={
+ "itemId": LICENSE_MODEL_ID,
+ "version": {"id": LICENSE_MODEL_VERSION_ID},
+ },
+ )
+
+ mockup_catalog_item(
+ license_model_client.catalog_items["ADD_KEY_GROUP"],
+ override_return_data={"value": KEYGROUP_ID},
+ override_uri_params={
+ "license_model_id": LICENSE_MODEL_ID,
+ "license_model_version_id": LICENSE_MODEL_VERSION_ID,
+ },
+ )
+
+ mockup_catalog_item(
+ license_model_client.catalog_items["ADD_ENTITLEMENT_POOL"],
+ override_return_data={"value": ENTITLEMENT_POOL_ID},
+ override_uri_params={
+ "license_model_id": LICENSE_MODEL_ID,
+ "license_model_version_id": LICENSE_MODEL_VERSION_ID,
+ },
+ )
+
+ mockup_catalog_item(
+ license_model_client.catalog_items["ADD_FEATURE_GROUP"],
+ override_return_data={"value": FEATURE_GROUP_ID},
+ override_uri_params={
+ "license_model_id": LICENSE_MODEL_ID,
+ "license_model_version_id": LICENSE_MODEL_VERSION_ID,
+ },
+ )
+
+ mockup_catalog_item(
+ license_model_client.catalog_items["ADD_LICENSE_AGREEMENT"],
+ override_return_data={"value": LICENSE_AGREEMENT_ID},
+ override_uri_params={
+ "license_model_id": LICENSE_MODEL_ID,
+ "license_model_version_id": LICENSE_MODEL_VERSION_ID,
+ },
+ )
+
+ return_data = {"vendorName": VENDOR_NAME, "id": ID, "description": DESCRIPTION}
+ mockup_catalog_item(
+ license_model_client.catalog_items["GET_LICENSE_MODEL"],
+ override_return_data=return_data,
+ override_uri_params={
+ "license_model_id": LICENSE_MODEL_ID,
+ "license_model_version_id": LICENSE_MODEL_VERSION_ID,
+ },
+ )
+
+ mockup_client(license_model_client)
+
+ lm = LicenseModel(
+ VENDOR_NAME,
+ "abc123",
+ "entitlement_pool_name",
+ "key_group_name",
+ "feature_group_name",
+ "license_agreement_name",
+ "license_start_date",
+ "license_end_date",
+ )
+
+ assert lm.tosca == return_data
diff --git a/onap-client/onap_client/sdc/tests/test_sdc_client.py b/onap-client/onap_client/sdc/tests/test_sdc_client.py
new file mode 100644
index 0000000..c4188a9
--- /dev/null
+++ b/onap-client/onap_client/sdc/tests/test_sdc_client.py
@@ -0,0 +1,68 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+from onap_client.client.clients import Client
+
+
+def test_sdc_client():
+ c = Client()
+
+ assert hasattr(c, "sdc")
+
+
+def test_license_model_client():
+ c = Client().sdc
+
+ assert hasattr(c, "license_model")
+
+
+def test_vsp_client():
+ c = Client().sdc
+
+ assert hasattr(c, "vsp")
+
+
+def test_vnf_client():
+ c = Client().sdc
+
+ assert hasattr(c, "vnf")
+
+
+def test_service_client():
+ c = Client().sdc
+
+ assert hasattr(c, "service")
diff --git a/onap-client/onap_client/sdc/tests/test_vnf.py b/onap-client/onap_client/sdc/tests/test_vnf.py
new file mode 100644
index 0000000..025a2d8
--- /dev/null
+++ b/onap-client/onap_client/sdc/tests/test_vnf.py
@@ -0,0 +1,172 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import responses
+from onap_client.tests.utils import mockup_client, mockup_catalog_item
+from onap_client.client.clients import Client
+from onap_client.sdc.vnf import VNF
+from onap_client.sdc.vnf import (
+ instance_ids_for_property,
+ network_role_property_for_instance,
+)
+
+vnf_client = Client().sdc.vnf
+vsp_client = Client().sdc.vsp
+
+
+@responses.activate
+def test_vnf_create():
+ SOFTWARE_PRODUCT_NAME = "software_product_name"
+ SOFTWARE_PRODUCT_ID = "software_product_id"
+ SOFTWARE_PRODUCT_VERSION_ID = "software_product_version_id"
+ VNF_NAME = "vnf_name"
+ RESOURCE_TYPE = "VF"
+ CATALOG_RESOURCE_ID = "catalog_resource_id"
+
+ return_data = {
+ "uniqueId": CATALOG_RESOURCE_ID,
+ "componentInstancesInputs": {
+ "instance_id1": [
+ {"name": "vm_type_tag", "value": "red"},
+ {"name": "nf_role", "value": "dfankafd"},
+ ]
+ },
+ "name": VNF_NAME,
+ }
+ mockup_catalog_item(
+ vsp_client.catalog_items["GET_SOFTWARE_PRODUCTS"],
+ override_return_data={
+ "results": [{"name": SOFTWARE_PRODUCT_NAME, "id": SOFTWARE_PRODUCT_ID}]
+ },
+ )
+ mockup_catalog_item(
+ vsp_client.catalog_items["GET_SOFTWARE_PRODUCT_VERSIONS"],
+ override_return_data={
+ "results": [
+ {"name": SOFTWARE_PRODUCT_NAME, "id": SOFTWARE_PRODUCT_VERSION_ID}
+ ]
+ },
+ override_uri_params={"software_product_id": SOFTWARE_PRODUCT_ID},
+ )
+ mockup_catalog_item(
+ vsp_client.catalog_items["GET_SOFTWARE_PRODUCT"],
+ override_return_data={"vendorName": "vendor_name"},
+ override_uri_params={
+ "software_product_id": SOFTWARE_PRODUCT_ID,
+ "software_product_version_id": SOFTWARE_PRODUCT_VERSION_ID,
+ },
+ )
+ mockup_catalog_item(
+ vnf_client.catalog_items["GET_RESOURCES"],
+ override_return_data={"resources": []},
+ )
+ mockup_catalog_item(
+ vnf_client.catalog_items["ADD_CATALOG_RESOURCE"],
+ override_return_data=return_data,
+ )
+ mockup_catalog_item(
+ vnf_client.catalog_items["GET_CATALOG_RESOURCE"],
+ override_return_data=return_data,
+ override_uri_params={"catalog_resource_id": CATALOG_RESOURCE_ID},
+ )
+ mockup_catalog_item(
+ vnf_client.catalog_items["CERTIFY_CATALOG_RESOURCE"],
+ override_return_data=return_data,
+ override_uri_params={"catalog_resource_id": CATALOG_RESOURCE_ID},
+ )
+ mockup_catalog_item(
+ vnf_client.catalog_items["ADD_CATALOG_RESOURCE_PROPERTY"],
+ override_uri_params={
+ "catalog_resource_id": CATALOG_RESOURCE_ID,
+ "catalog_resource_instance_id": "instance_id1",
+ },
+ )
+
+ mockup_client(vnf_client)
+
+ vnf = VNF(
+ SOFTWARE_PRODUCT_NAME,
+ VNF_NAME,
+ RESOURCE_TYPE,
+ vm_types=[{"vm_type": "red", "properties": {"nf_role": "blue"}}],
+ )
+
+ vnf._submit()
+
+ assert "catalog_resource_name" in vnf.tosca
+
+
+def test_instance_ids_for_property():
+ vnf_model = {
+ "componentInstancesInputs": {
+ "item1id": [
+ {"name": "vm_type", "value": "db"},
+ {"name": "otherprop", "value": "otherval"},
+ ],
+ "item2id": [
+ {"name": "vm_type", "value": "db"},
+ {"name": "otherprop", "value": "otherval"},
+ ],
+ }
+ }
+
+ ids = instance_ids_for_property(vnf_model, "vm_type", "db")
+
+ assert "item1id" in ids and "item2id" in ids
+
+
+def test_network_role_property_for_instance():
+ vnf_model = {
+ "componentInstancesInputs": {
+ "item1id": [
+ {"name": "vm_type", "value": "db"},
+ {"name": "item1id.port123.oam.network_role_tag", "value": "oam"},
+ {
+ "name": "item1id.port123.oam.network_role",
+ "value": "ACTUALNETWORKROLE",
+ },
+ ],
+ "item2id": [
+ {"name": "vm_type", "value": "db"},
+ {"name": "otherprop", "value": "otherval"},
+ ],
+ }
+ }
+
+ prop = network_role_property_for_instance("oam", vnf_model, "item1id")
+
+ assert prop == "item1id.port123.oam.network_role"
diff --git a/onap-client/onap_client/sdc/tests/test_vsp.py b/onap-client/onap_client/sdc/tests/test_vsp.py
new file mode 100644
index 0000000..4d71a81
--- /dev/null
+++ b/onap-client/onap_client/sdc/tests/test_vsp.py
@@ -0,0 +1,118 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+import responses
+from onap_client.client.clients import Client
+from onap_client import sdc
+from onap_client.tests.utils import mockup_client, mockup_catalog_item
+from os.path import dirname, abspath
+
+THIS_DIR = dirname(abspath(__file__))
+
+license_model_client = Client().sdc.license_model
+vsp_client = Client().sdc.vsp
+
+
+@responses.activate
+def test_vsp_create():
+ LICENSE_MODEL_ID = "license_model_id"
+ LICENSE_MODEL_VERSION_ID = "license_model_version_id"
+ FEATURE_GROUP_ID = "feature_group_id"
+ LICENSE_AGREEMENT_ID = "license_agreement_id"
+ LICENSE_MODEL_NAME = "test"
+ VSP_MODEL_ID = "software_product_id"
+ VSP_MODEL_VERSION_ID = "software_product_version_id"
+ VSP_NAME = "software_product_name"
+
+ mockup_catalog_item(
+ license_model_client.catalog_items["GET_LICENSE_MODELS"],
+ override_return_data={
+ "results": [{"name": LICENSE_MODEL_NAME, "id": LICENSE_MODEL_ID}]
+ },
+ )
+ mockup_catalog_item(
+ license_model_client.catalog_items["GET_LICENSE_MODEL_VERSIONS"],
+ override_return_data={
+ "results": [{"name": LICENSE_MODEL_NAME, "id": LICENSE_MODEL_VERSION_ID}]
+ },
+ )
+ mockup_catalog_item(
+ license_model_client.catalog_items["GET_LICENSE_MODEL_VERSION_ATTRIBUTE"],
+ override_return_data={
+ "results": [{"name": LICENSE_MODEL_NAME, "id": FEATURE_GROUP_ID}]
+ },
+ override_uri_params={"attribute": "feature-groups"},
+ )
+ mockup_catalog_item(
+ license_model_client.catalog_items["GET_LICENSE_MODEL_VERSION_ATTRIBUTE"],
+ override_return_data={
+ "results": [{"name": LICENSE_MODEL_NAME, "id": LICENSE_AGREEMENT_ID}]
+ },
+ override_uri_params={"attribute": "license-agreements"},
+ )
+ mockup_client(license_model_client)
+
+ mockup_catalog_item(
+ vsp_client.catalog_items["GET_SOFTWARE_PRODUCTS"],
+ override_return_data={"results": []},
+ )
+ mockup_catalog_item(
+ vsp_client.catalog_items["ADD_SOFTWARE_PRODUCT"],
+ override_return_data={
+ "itemId": VSP_MODEL_ID,
+ "version": {"id": VSP_MODEL_VERSION_ID},
+ },
+ )
+ mockup_catalog_item(
+ vsp_client.catalog_items["GET_SOFTWARE_PRODUCT"],
+ override_return_data={"name": VSP_NAME},
+ )
+ mockup_client(vsp_client)
+
+ vsp = sdc.vsp.VSP(
+ "vendor_name",
+ LICENSE_MODEL_NAME,
+ "{}/test.zip".format(THIS_DIR),
+ "application/zip",
+ VSP_NAME,
+ "description",
+ "category",
+ "sub_category",
+ contributers=["test123"],
+ )
+
+ assert vsp.tosca == {"name": VSP_NAME}
diff --git a/onap-client/onap_client/sdc/vnf.py b/onap-client/onap_client/sdc/vnf.py
new file mode 100644
index 0000000..da8f213
--- /dev/null
+++ b/onap-client/onap_client/sdc/vnf.py
@@ -0,0 +1,507 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+from onap_client.lib import generate_dummy_string
+from onap_client.resource import Resource
+from onap_client import exceptions, sdc
+from onap_client.client.clients import Client as SDCClient
+from onap_client.sdc import vsp
+from onap_client.util import utility
+
+import time
+
+vnf_client = SDCClient().sdc.vnf
+
+
+class VNF(Resource):
+ resource_name = "VNF"
+ spec = {
+ "software_product_name": {"type": str, "required": True},
+ "vnf_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_vnf_"),
+ },
+ "resource_type": {"type": str, "required": False, "default": "VF"},
+ "inputs": {"type": dict, "required": False, "default": {}},
+ "vm_types": {
+ "type": list,
+ "list_item": dict,
+ "required": False,
+ "default": [],
+ "nested": {
+ "vm_type": {"type": str, "required": True},
+ "properties": {"type": dict, "required": True, "default": {}},
+ },
+ },
+ "network_roles": {
+ "type": list,
+ "list_item": dict,
+ "required": False,
+ "default": [],
+ "nested": {
+ "network_role_tag": {"type": str, "required": True},
+ "network_role": {"type": str, "required": True},
+ "related_networks": {
+ "type": list,
+ "list_item": str,
+ "required": False,
+ "default": [],
+ },
+ },
+ },
+ "policies": {
+ "type": list,
+ "list_item": dict,
+ "required": False,
+ "default": [],
+ "nested": {
+ "policy_name": {"type": str, "required": True},
+ "properties": {"type": dict, "required": False, "default": {}},
+ },
+ },
+ }
+
+ def __init__(
+ self,
+ software_product_name,
+ vnf_name,
+ resource_type,
+ inputs={},
+ vm_types=[],
+ network_roles=[],
+ policies=[],
+ ):
+
+ vnf_input = {}
+
+ software_product_id = vsp.get_vsp_id(software_product_name)
+ software_product_version_id = vsp.get_vsp_version_id(software_product_id)
+ vsp_model = vsp.get_vsp_model(software_product_id, software_product_version_id)
+ vsp_vendor = vsp_model.get("vendorName")
+
+ vnf_input["software_product_id"] = software_product_id
+ vnf_input["vendor_name"] = vsp_vendor
+ vnf_input["vnf_name"] = vnf_name
+ vnf_input["resource_type"] = resource_type
+ vnf_input["inputs"] = inputs
+ vnf_input["vm_types"] = vm_types
+ vnf_input["network_roles"] = network_roles
+ vnf_input["policies"] = policies
+
+ super().__init__(vnf_input)
+
+ def _create(self, vnf_input):
+ """Creates a vnf object in SDC"""
+ vnf = None
+
+ if get_vnf_id(vnf_input.get("vnf_name")) is None:
+ vnf = create_vnf(vnf_input)
+ else:
+ raise exceptions.ResourceAlreadyExistsException(
+ "VNF resource {} already exists".format(vnf_input.get("vnf_name"))
+ )
+
+ return vnf
+
+ def _post_create(self):
+ inputs = self.inputs
+ vm_types = self.vm_types
+ network_roles = self.network_roles
+ policies = self.policies
+ model = self.tosca
+ vm_type_instances = []
+
+ for vm_type in vm_types:
+ vm_type_tag = vm_type.get("vm_type")
+ properties = vm_type.get("properties")
+ instance_ids = instance_ids_for_property(model, "vm_type_tag", vm_type_tag)
+ for instance_id in instance_ids:
+ for k, v in properties.items():
+ # updating vm_type properties
+ self.add_instance_property(instance_id, k, v)
+ vm_type_instances.append(instance_id)
+ for network_role in network_roles:
+ # checking if abstract node has matching network role,
+ # and updating if found
+ nrt = network_role.get("network_role_tag")
+ nr = network_role.get("network_role")
+ related_networks = network_role.get("related_networks")
+ instance_property = network_role_property_for_instance(
+ nrt, model, instance_id
+ )
+ if instance_property:
+ self.add_instance_property(instance_id, instance_property, nr)
+ if related_networks:
+ property_val = [
+ {"related_network_role": related_network_role}
+ for related_network_role in related_networks
+ ]
+ rnr_instance_property = instance_property.replace(
+ "_network_role", "_related_networks"
+ )
+ self.add_instance_property(
+ instance_id,
+ rnr_instance_property,
+ str(property_val).replace("'", '\\"'),
+ )
+
+ for policy in policies:
+ policy_name = policy.get("policy_name")
+ policy_model = self.add_policy_resource(policy_name)
+ self.associate_policy(policy_model.catalog_resource_id, vm_type_instances)
+ for k, v in policy.get("properties", {}).items():
+ self.add_policy_property(policy_model.catalog_resource_id, k, v)
+
+ for k, v in inputs.items():
+ self.add_input_value(k, v)
+
+ def _submit(self):
+ """Submits the vnf in SDC"""
+ certification = vnf_client.certify_catalog_resource(
+ **self.attributes, user_remarks="Ready!"
+ )
+ self.attributes["catalog_resource_id"] = certification.catalog_resource_id
+
+ vnf = vnf_client.get_catalog_resource(**self.attributes)
+
+ self.attributes["catalog_resource_name"] = vnf.catalog_resource_name
+ self.attributes["tosca"] = vnf.response_data
+
+ def add_resource(
+ self, catalog_resource_id, catalog_resource_name, origin_type="VF"
+ ):
+ """Attaches a resource to a VNF in SDC
+
+ :catalog_resource_id: ID of a resource in the SDC catalog
+ :catalog_resource_name: name to give to the resource when attaching to vnf
+ :origin_type: specifies the origin of the attached resource
+
+ """
+ milli_timestamp = int(time.time() * 1000)
+
+ resource_instance = vnf_client.add_resource_instance(
+ **self.attributes,
+ posX=306,
+ posY=248,
+ milli_timestamp=milli_timestamp,
+ new_catalog_resource_id=catalog_resource_id,
+ new_catalog_resource_name=catalog_resource_name,
+ originType=origin_type,
+ )
+
+ response = {
+ "id": resource_instance.catalog_resource_instance_id,
+ "tosca": resource_instance.response_data,
+ }
+ self.attributes[catalog_resource_name] = response
+
+ def add_input_value(self, input_name, input_default_value):
+ """Updates an input value on a VNF
+
+ :input_name: input name to update
+ :property_value: value to update input with
+
+ """
+ self._refresh()
+
+ inputs = self.tosca.get("inputs", [])
+ for item in inputs:
+ if item["name"] == input_name:
+ unique_id = item["uniqueId"]
+ parent_unique_id = item["parentUniqueId"]
+ owner_id = item["ownerId"]
+ return vnf_client.add_catalog_resource_input(
+ **self.attributes,
+ input_default_value=input_default_value,
+ input_name=input_name,
+ input_parent_unique_id=parent_unique_id,
+ input_unique_id=unique_id,
+ input_owner_id=owner_id,
+ )
+
+ raise exceptions.InputNotFoundException(
+ "Input {} was not found in VF".format(input_name)
+ )
+
+ # TODO
+ # instance, policy, and group properties can probably be merged
+ # rn there is a lot of dup
+
+ def add_instance_property(self, instance_id, property_name, property_value):
+ """Updates an instance property on a abstract instance attached to a VNF
+
+ :instance_id: ID of a instance attached to a VNF
+ :property_name: property name to update
+ :property_value: value to update property with
+
+ """
+ self._refresh()
+
+ instance_inputs = self.tosca.get("componentInstancesInputs", {}).get(
+ instance_id, {}
+ )
+
+ for prop in instance_inputs:
+ if prop.get("name") == property_name:
+ unique_id = prop.get("uniqueId")
+ parent_unique_id = prop.get("parentUniqueId")
+ owner_id = prop.get("ownerId")
+ schemaType = prop.get("schemaType", "")
+ property_type = prop.get("type")
+ return vnf_client.add_catalog_resource_property(
+ **self.attributes,
+ unique_id=unique_id,
+ parent_unique_id=parent_unique_id,
+ owner_id=owner_id,
+ catalog_resource_instance_id=instance_id,
+ property_name=property_name,
+ property_default_value=property_value,
+ schema_type=schemaType,
+ property_type=property_type,
+ )
+
+ raise exceptions.PropertyNotFoundException(
+ "Property {} was not found in Instance {}".format(
+ property_name, instance_id
+ )
+ )
+
+ def add_policy_property(self, policy_id, property_name, property_value):
+ """Updates a policy property on a polic attached to a VNF
+
+ :policy_id: ID of a policy attached to a VNF
+ :property_name: property name to update
+ :property_value: value to update property with
+
+ """
+ self._refresh()
+
+ policies = (
+ self.tosca.get("policies", {}).get(policy_id, {}).get("properties", {})
+ )
+
+ for prop in policies:
+ if prop.get("name") == property_name:
+ unique_id = prop.get("uniqueId")
+ property_type = prop.get("type")
+ description = prop.get("description")
+ return vnf_client.add_catalog_policy_property(
+ **self.attributes,
+ unique_id=unique_id,
+ catalog_policy_id=policy_id,
+ property_name=property_name,
+ property_default_value=property_value,
+ description=description,
+ property_type=property_type,
+ )
+
+ raise exceptions.PropertyNotFoundException(
+ "Property {} was not found in policy {}".format(property_name, policy_id)
+ )
+
+ def add_group_property(self, group_id, property_name, property_value):
+ """Updates a group property on a group attached to a VNF
+
+ :group_id: ID of a group attached to a VNF
+ :property_name: property name to update
+ :property_value: value to update property with
+
+ """
+ self._refresh()
+
+ groups = self.tosca.get("groups", [])
+
+ for group in groups:
+ if group.get("uniqueId") == group_id:
+ properties = group.get("properties", [])
+ for prop in properties:
+ unique_id = prop.get("uniqueId")
+ property_type = prop.get("type")
+ description = prop.get("description")
+ parent_unique_id = prop.get("parentUniqueId")
+ owner_id = prop.get("ownerId")
+ return vnf_client.add_catalog_group_property(
+ **self.attributes,
+ unique_id=unique_id,
+ catalog_group_id=group_id,
+ property_name=property_name,
+ property_default_value=property_value,
+ description=description,
+ property_type=property_type,
+ parent_unique_id=parent_unique_id,
+ owner_id=owner_id,
+ )
+
+ raise exceptions.PropertyNotFoundException(
+ "Property {} was not found in group {}".format(property_name, group_id)
+ )
+
+ def add_group_resource(self, group_name):
+ """Adds an SDC group resource to a VNF
+
+ :group_name: name of the group, matching onap-client.conf
+
+ """
+ sdc_properties = sdc.SDC_PROPERTIES
+ group = sdc_properties.GROUPS.get(group_name)
+ if not group:
+ raise exceptions.UnknownGroupException(
+ "Group {} was not found in configuration file".format(group_name)
+ )
+
+ return vnf_client.add_catalog_resource_group(
+ **self.attributes, catalog_group_name=group
+ )
+
+ def add_policy_resource(self, policy_name):
+ """Adds an SDC policy resource to a VNF
+
+ :group_name: name of the policy, matching onap-client.conf
+
+ """
+ sdc_properties = sdc.SDC_PROPERTIES
+ policy = sdc_properties.POLICIES.get(policy_name)
+ if not policy:
+ raise exceptions.UnknownPolicyException(
+ "Policy {} was not found in configuration file".format(policy_name)
+ )
+
+ return vnf_client.add_catalog_resource_policy(
+ **self.attributes, catalog_policy_name=policy
+ )
+
+ def associate_policy(self, policy_id, instance_ids):
+ """associates an SDC policy resource to an VNF instance resource
+
+ :policy_id: ID of policy resource from catalog
+ :instance_ids: list of instance ids to associate policy with
+
+ """
+
+ return vnf_client.add_policy_to_instance(
+ **self.attributes, catalog_policy_id=policy_id, instance_ids=instance_ids
+ )
+
+ def associate_group(self, group_id, instance_id):
+ """associates an SDC group resource to an VNF instance resource"""
+ return vnf_client.add_group_to_instance(
+ **self.attributes, catalog_group_id=group_id, instance_id=instance_id
+ )
+
+ def _refresh(self):
+ """GETs the VNF model from SDC and updates the VNF object"""
+ vnf = vnf_client.get_catalog_resource(**self.attributes)
+ self.attributes["tosca"] = vnf.response_data
+
+
+def create_vnf(vnf_input):
+ """Creates a vnf object in SDC
+
+ :vnf_input: dictionary with values to input for vnf creation
+
+ :return: dictionary of updated values for created vnf
+ """
+ kwargs = vnf_input
+ vnf = vnf_client.add_catalog_resource(**kwargs)
+
+ kwargs["catalog_resource_id"] = vnf.catalog_resource_id
+ kwargs["tosca"] = vnf.response_data
+
+ return kwargs
+
+
+def instance_ids_for_property(vnf_model, property_name, property_value):
+ """Parses a VNF model dictionary for a property + property value, to find the
+ abstract node tosca uuid
+
+ :vnf_model: dictionary for a VNF tosca model
+ :property_name: name of a property to look for in the vnf model
+ :property_value: value of a property to look for in the vnf model
+
+ :return: matching [instance_ids] or []
+ """
+ instance_ids = []
+ instances = vnf_model.get("componentInstancesInputs", {})
+ for instance_id, properties in instances.items():
+ for prop in properties:
+ if (
+ prop.get("name") == property_name
+ and prop.get("value", "") == property_value
+ ):
+ instance_ids.append(instance_id)
+ break
+
+ return instance_ids
+
+
+def network_role_property_for_instance(network_role_tag, vnf_model, instance_id):
+ """Parses a VNF model dictionary for a network_role_tag property, to find the
+ corresponding network role property
+
+ :network_role_tag: the network role tag to search for
+ :vnf_model: dictionary for a VNF tosca model
+ :instance_id: unique ID for an abstract node to look for the network_tag_property
+
+ :return: network_role property ID or None
+ """
+ instance_inputs = vnf_model.get("componentInstancesInputs", {}).get(instance_id, {})
+ for prop in instance_inputs:
+ if prop.get("name").endswith(
+ "network_role_tag"
+ ) and network_role_tag == prop.get("value"):
+ network_role_property = prop.get("name").replace("_tag", "")
+ return network_role_property
+
+ return None
+
+
+@utility
+def get_vnf(vnf_name):
+ """Queries SDC for the TOSCA model for a VNF"""
+ return vnf_client.get_catalog_resource(
+ catalog_resource_id=get_vnf_id(vnf_name)
+ ).response_data
+
+
+def get_vnf_id(vnf_name):
+ response = vnf_client.get_resources()
+ results = response.response_data.get("resources", [])
+ for vnf in results:
+ if vnf.get("name") == vnf_name:
+ return vnf["uniqueId"]
+ return None
diff --git a/onap-client/onap_client/sdc/vsp.py b/onap-client/onap_client/sdc/vsp.py
new file mode 100644
index 0000000..fc9258b
--- /dev/null
+++ b/onap-client/onap_client/sdc/vsp.py
@@ -0,0 +1,213 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2020 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+from onap_client.lib import generate_dummy_string
+from onap_client.resource import Resource
+from onap_client.client.clients import Client as SDCClient
+from onap_client import sdc
+from onap_client.util import utility
+from onap_client.exceptions import ResourceAlreadyExistsException
+
+vsp_client = SDCClient().sdc.vsp
+
+
+class VSP(Resource):
+ resource_name = "VSP"
+ spec = {
+ "vendor_name": {"type": str, "required": True},
+ "license_model_name": {"type": str, "required": True},
+ "file_path": {"type": str, "required": True},
+ "file_type": {"type": str, "required": False, "default": "application/zip"},
+ "software_product_name": {
+ "type": str,
+ "required": False,
+ "default": generate_dummy_string("test_vsp_"),
+ },
+ "description": {
+ "type": str,
+ "required": False,
+ "default": "new software product",
+ },
+ "category": {"type": str, "required": False, "default": "generic"},
+ "sub_category": {"type": str, "required": False, "default": "abstract"},
+ "contributers": {
+ "type": list,
+ "list_item": str,
+ "required": False,
+ "default": [],
+ },
+ }
+
+ def __init__(
+ self,
+ vendor_name,
+ license_model_name,
+ file_path,
+ file_type,
+ software_product_name,
+ description,
+ category,
+ sub_category,
+ contributers=[],
+ ):
+
+ vsp_input = {}
+
+ license_model_id = sdc.license_model.get_license_model_id(license_model_name)
+ license_model_version_id = sdc.license_model.get_license_model_version_id(
+ license_model_id
+ )
+ feature_group = sdc.license_model.get_license_model_attribute(
+ license_model_id, license_model_version_id, "feature-groups"
+ )
+ license_agreement = sdc.license_model.get_license_model_attribute(
+ license_model_id, license_model_version_id, "license-agreements"
+ )
+
+ vsp_input["software_product_name"] = software_product_name
+ vsp_input["feature_group_id"] = feature_group["id"]
+ vsp_input["license_agreement_id"] = license_agreement["id"]
+ vsp_input["vendor_name"] = vendor_name
+ vsp_input["license_model_id"] = license_model_id
+ vsp_input["license_model_version_id"] = license_model_version_id
+ vsp_input["file_path"] = file_path
+ vsp_input["file_type"] = file_type
+ vsp_input["description"] = description
+ vsp_input["category"] = category.lower()
+ vsp_input["sub_category"] = sub_category.lower()
+ vsp_input["contributers"] = contributers
+
+ super().__init__(vsp_input)
+
+ def _create(self, kwargs):
+ """Creates a vsp object in SDC"""
+ vsp = None
+
+ if get_vsp_id(kwargs.get("software_product_name")) is None:
+ vsp = create_vsp(kwargs)
+ else:
+ raise ResourceAlreadyExistsException(
+ "VSP resource {} already exists".format(
+ kwargs.get("software_product_name")
+ )
+ )
+
+ return vsp
+
+ def _post_create(self):
+ for contributer in self.contributers:
+ vsp_client.add_vsp_contributer(
+ user_id=contributer, software_product_id=self.software_product_id
+ )
+
+ def _submit(self):
+ """Submits the vsp in SDC"""
+ vsp_client.submit_software_product(**self.attributes, action="Submit")
+ vsp_client.package_software_product(**self.attributes, action="Create_Package")
+
+ vsp = vsp_client.get_software_product(**self.attributes)
+ self.attributes["tosca"] = vsp.response_data
+
+
+def create_vsp(vsp_input):
+ """Creates a VSP object in SDC
+
+ :vsp_input: dictionary with values to input for vsp creation
+
+ :return: dictionary of updated values for created vsp
+ """
+ kwargs = vsp_input
+ vsp = vsp_client.add_software_product(**kwargs)
+
+ kwargs["software_product_id"] = vsp.software_product_id
+ kwargs["software_product_version_id"] = vsp.software_product_version_id
+
+ vsp_client.upload_heat_package(**kwargs)
+ vsp_client.validate_software_product(**kwargs)
+
+ vsp = vsp_client.get_software_product(**kwargs)
+ kwargs["tosca"] = vsp.response_data
+
+ return kwargs
+
+
+def get_vsp_id(vsp_name):
+ """GETs vsp model ID from SDC
+
+ :vsp_name: name of vsp model in SDC
+
+ :return: id of vsp or None
+ """
+ response = vsp_client.get_software_products()
+ results = response.response_data.get("results", {})
+ for vsp in results:
+ if vsp.get("name") == vsp_name:
+ return vsp["id"]
+ return None
+
+
+def get_vsp_version_id(vsp_id):
+ """GETs vsp model version UUID from SDC
+
+ :vsp_id: uuid of vsp model in SDC
+
+ :return: uuid of vsp version id or None
+ """
+ vsp_version_id = None
+ creation_time = -1
+ response = vsp_client.get_software_product_versions(software_product_id=vsp_id)
+ results = response.response_data.get("results")
+ for version in results:
+ if version.get("creationTime", 0) > creation_time:
+ creation_time = version.get("creationTime")
+ vsp_version_id = version.get("id")
+
+ return vsp_version_id
+
+
+def get_vsp_model(vsp_id, vsp_version_id):
+ return vsp_client.get_software_product(
+ software_product_id=vsp_id, software_product_version_id=vsp_version_id,
+ ).response_data
+
+
+@utility
+def get_vsp(vsp_name):
+ """Queries SDC for the tosca model for a VSP"""
+ vsp_id = get_vsp_id(vsp_name)
+ vsp_version_id = get_vsp_version_id(vsp_id)
+ return get_vsp_model(vsp_id, vsp_version_id)