diff options
Diffstat (limited to 'onap-client/onap_client/sdc')
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 Binary files differnew file mode 100644 index 0000000..37b2ed1 --- /dev/null +++ b/onap-client/onap_client/sdc/tests/test.zip 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) |