diff options
author | dyh <dengyuanhong@chinamobile.com> | 2019-03-21 11:39:41 +0800 |
---|---|---|
committer | deng yuanhong <dengyuanhong@chinamobile.com> | 2019-03-22 06:21:47 +0000 |
commit | 363bc9d6d9f3803c6d80198865307c797d4809e2 (patch) | |
tree | 73f66918f67fc01dbc8968c9e651aa30ccad507b | |
parent | 3aed8eb825b0064d6e0c11091a751e29915a73d1 (diff) |
Implement Service package management RESTAPIs
Change-Id: Iee7a3c94cb6091baddf7a44ef92b70e64f8045dd
Issue-ID: VFC-1308
Signed-off-by: dyh <dengyuanhong@chinamobile.com>
-rw-r--r-- | catalog/packages/biz/sdc_service_package.py | 116 | ||||
-rw-r--r-- | catalog/packages/biz/service_descriptor.py | 127 | ||||
-rw-r--r-- | catalog/packages/serializers/catalog_serializers.py | 64 | ||||
-rw-r--r-- | catalog/packages/tests/test_servicepackage.py | 143 | ||||
-rwxr-xr-x | catalog/packages/urls.py | 2 | ||||
-rw-r--r-- | catalog/packages/views/catalog_views.py | 117 | ||||
-rw-r--r-- | catalog/packages/views/common.py | 4 | ||||
-rw-r--r-- | catalog/pub/database/models.py | 23 | ||||
-rw-r--r-- | catalog/pub/exceptions.py | 8 |
9 files changed, 603 insertions, 1 deletions
diff --git a/catalog/packages/biz/sdc_service_package.py b/catalog/packages/biz/sdc_service_package.py new file mode 100644 index 00000000..bae1f71d --- /dev/null +++ b/catalog/packages/biz/sdc_service_package.py @@ -0,0 +1,116 @@ +# Copyright (c) 2019, CMCC Technologies. Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import traceback + +from coverage.xmlreport import os + +from catalog.packages.biz.service_descriptor import ServiceDescriptor +from catalog.pub.config.config import CATALOG_ROOT_PATH, REG_TO_MSB_REG_PARAM, CATALOG_URL_PATH +from catalog.pub.database.models import ServicePackageModel +from catalog.pub.exceptions import CatalogException, PackageNotFoundException, \ + PackageHasExistsException +from catalog.pub.msapi import sdc +from catalog.pub.utils import fileutil, toscaparser + +logger = logging.getLogger(__name__) + + +class ServicePackage(object): + """ + Actions for sdc service package. + """ + + def __init__(self): + pass + + def on_distribute(self, csar_id): + if ServicePackageModel.objects.filter(servicePackageId=csar_id): + raise PackageHasExistsException("Service CSAR(%s) already exists." % csar_id) + + try: + artifact = sdc.get_artifact(sdc.ASSETTYPE_SERVICES, csar_id) + local_path = os.path.join(CATALOG_ROOT_PATH, csar_id) + csar_name = "%s.csar" % artifact.get("name", csar_id) + local_file_name = sdc.download_artifacts(artifact["toscaModelURL"], local_path, csar_name) + if local_file_name.endswith(".csar") or local_file_name.endswith(".zip"): + artifact_vnf_file = fileutil.unzip_file(local_file_name, local_path, + "Artifacts/Deployment/OTHER/ns.csar") + if os.path.exists(artifact_vnf_file): + local_file_name = artifact_vnf_file + + data = { + 'userDefinedData': {} + } + serviced = ServiceDescriptor() + serviced.create(data, csar_id) + serviced.parse_serviced_and_save(csar_id, local_file_name) + + except Exception as e: + logger.error(traceback.format_exc()) + if ServicePackageModel.objects.filter(servicePackageId=csar_id): + ServicePackage().delete_csar(csar_id) + raise e + + def delete_csar(self, csar_id): + serviced = ServiceDescriptor() + serviced.delete_single(csar_id) + + def get_csars(self): + csars = [] + packages = ServicePackageModel.objects.filter() + for package in packages: + csar = self.get_csar(package.servicePackageId) + csars.append(csar) + return csars + + def get_csar(self, csar_id): + package_info = {} + csars = ServicePackageModel.objects.filter(servicePackageId=csar_id) + if csars: + package_info["servicedId"] = csars[0].servicedId + package_info["servicePackageId"] = csars[0].servicePackageId + package_info["servicedProvider"] = csars[0].servicedDesigner + package_info["servicedVersion"] = csars[0].servicedVersion + package_info["csarName"] = csars[0].servicePackageUri + package_info["servicedModel"] = csars[0].servicedModel + package_info["servicedInvariantId"] = csars[0].invariantId + package_info["downloadUrl"] = "http://%s:%s/%s/%s/%s" % ( + REG_TO_MSB_REG_PARAM[0]["nodes"][0]["ip"], + REG_TO_MSB_REG_PARAM[0]["nodes"][0]["port"], + CATALOG_URL_PATH, + csar_id, + csars[0].servicePackageUri) + else: + raise PackageNotFoundException("Service package[%s] not Found." % csar_id) + + return {"csarId": csar_id, "packageInfo": package_info} + + def parse_serviced(csar_id, inputs): + service_pkg = ServicePackageModel.objects.filter(servicePackageId=csar_id) + if not service_pkg: + raise PackageNotFoundException("Service CSAR(%s) does not exist." % csar_id) + + try: + csar_path = service_pkg[0].localFilePath + ret = {"model": toscaparser.parse_nsd(csar_path, inputs)} + return ret + except CatalogException as e: + logger.error(e.message) + raise e + except Exception as e: + logger.error(e.message) + logger.error(traceback.format_exc()) + raise e diff --git a/catalog/packages/biz/service_descriptor.py b/catalog/packages/biz/service_descriptor.py new file mode 100644 index 00000000..72a561ae --- /dev/null +++ b/catalog/packages/biz/service_descriptor.py @@ -0,0 +1,127 @@ +# Copyright (c) 2019, CMCC Technologies. Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging +import os +import uuid + +from catalog.packages.const import PKG_STATUS +from catalog.pub.config.config import CATALOG_ROOT_PATH +from catalog.pub.database.models import ServicePackageModel +from catalog.pub.exceptions import CatalogException, PackageNotFoundException +from catalog.pub.utils import toscaparser, fileutil +from catalog.pub.utils.values import ignore_case_get + +logger = logging.getLogger(__name__) + + +class ServiceDescriptor(object): + + def __init__(self): + pass + + def create(self, data, csar_id): + logger.info('Start to create a ServiceD...') + user_defined_data = ignore_case_get(data, 'userDefinedData', {}) + data = { + 'id': id if id else str(uuid.uuid4()), + 'servicedOnboardingState': PKG_STATUS.CREATED, + 'servicedOperationalState': PKG_STATUS.DISABLED, + 'servicedUsageState': PKG_STATUS.NOT_IN_USE, + 'userDefinedData': user_defined_data, + '_links': None # TODO + } + ServicePackageModel.objects.create( + servicePackageId=data['id'], + onboardingState=data['servicedOnboardingState'], + operationalState=data['servicedOperationalState'], + usageState=data['servicedUsageState'], + userDefinedData=json.dumps(user_defined_data) + ) + logger.info('A ServiceD(%s) has been created.' % data['id']) + return data + + def parse_serviced_and_save(self, serviced_info_id, local_file_name): + logger.info('Start to process ServiceD(%s)...' % serviced_info_id) + service_pkgs = ServicePackageModel.objects.filter(servicePackageId=serviced_info_id) + service_pkgs.update(onboardingState=PKG_STATUS.PROCESSING) + + serviced_json = toscaparser.parse_nsd(local_file_name) # TODO + logger.debug("%s", serviced_json) + serviced = json.JSONDecoder().decode(serviced_json) + + serviced_id = serviced.get("ns", {}).get("properties", {}).get("descriptor_id", "") + serviced_name = serviced.get("ns", {}).get("properties", {}).get("name", "") + serviced_version = serviced.get("ns", {}).get("properties", {}).get("version", "") + serviced_designer = serviced.get("ns", {}).get("properties", {}).get("designer", "") + invariant_id = serviced.get("ns", {}).get("properties", {}).get("invariant_id", "") + if serviced_id == "": + raise CatalogException("serviced_id(%s) does not exist in metadata." % serviced_id) + other_nspkg = ServicePackageModel.objects.filter(nsdId=serviced_id) + if other_nspkg and other_nspkg[0].servicePackageId != serviced_info_id: + logger.warn("ServiceD(%s,%s) already exists.", serviced_id, other_nspkg[0].servicePackageId) + raise CatalogException("ServiceD(%s) already exists." % serviced_id) + + for vnf in serviced["vnfs"]: + vnfd_id = vnf["properties"].get("descriptor_id", "undefined") + if vnfd_id == "undefined": + vnfd_id = vnf["properties"].get("id", "undefined") + pkg = ServicePackageModel.objects.filter(vnfdId=vnfd_id) + if not pkg: + pkg = ServicePackageModel.objects.filter(vnfPackageId=vnfd_id) + if not pkg: + vnfd_name = vnf.get("vnf_id", "undefined") + logger.error("[%s] is not distributed.", vnfd_name) + raise CatalogException("VNF package(%s) is not distributed." % vnfd_id) + + for pnf in serviced["pnfs"]: + pnfd_id = pnf["properties"].get("descriptor_id", "undefined") + if pnfd_id == "undefined": + pnfd_id = pnf["properties"].get("id", "undefined") + pkg = ServicePackageModel.objects.filter(pnfdId=pnfd_id) + if not pkg: + pkg = ServicePackageModel.objects.filter(pnfPackageId=pnfd_id) + if not pkg: + pnfd_name = pnf.get("pnf_id", "undefined") + logger.error("[%s] is not distributed.", pnfd_name) + raise CatalogException("PNF package(%s) is not distributed." % pnfd_name) + + service_pkgs.update( + servicedId=serviced_id, + servicedName=serviced_name, + servicedDesginer=serviced_designer, + servicedDescription=serviced.get("description", ""), + servicedVersion=serviced_version, + invariantId=invariant_id, + onboardingState=PKG_STATUS.ONBOARDED, + operationalState=PKG_STATUS.ENABLED, + usageState=PKG_STATUS.NOT_IN_USE, + servicePackageUri=local_file_name, + sdcCsarId=serviced_info_id, + localFilePath=local_file_name, + servicedModel=serviced_json + ) + logger.info('ServiceD(%s) has been processed.' % serviced_info_id) + + def delete_single(self, serviced_info_id): + logger.info('Start to delete ServiceD(%s)...' % serviced_info_id) + service_pkgs = ServicePackageModel.objects.filter(servicePackageId=serviced_info_id) + if not service_pkgs.exists(): + logger.warn('ServiceD(%s) not found.' % serviced_info_id) + raise PackageNotFoundException("Service package[%s] not Found." % serviced_info_id) + service_pkgs.delete() + service_pkg_path = os.path.join(CATALOG_ROOT_PATH, serviced_info_id) + fileutil.delete_dirs(service_pkg_path) + logger.info('ServiceD(%s) has been deleted.' % serviced_info_id) diff --git a/catalog/packages/serializers/catalog_serializers.py b/catalog/packages/serializers/catalog_serializers.py index 90006c92..0e830e5e 100644 --- a/catalog/packages/serializers/catalog_serializers.py +++ b/catalog/packages/serializers/catalog_serializers.py @@ -132,6 +132,70 @@ class NsPackagesSerializer(serializers.ListSerializer): child = NsPackageSerializer() +class ServicePackageDistributeRequestSerializer(serializers.Serializer): + csarId = serializers.CharField(help_text="csarId", required=True) + + +class ServicePackageInfoSerializer(serializers.Serializer): + servicedId = serializers.CharField( + help_text="ServiceD ID", + required=False, + allow_null=True + ) + servicePackageId = serializers.CharField( + help_text="Service Package ID", + allow_blank=True, + required=False, + allow_null=True + ) + servicedProvider = serializers.CharField( + help_text="ServiceD Provider", + allow_blank=True, + required=False, + allow_null=True + ) + servicedVersion = serializers.CharField( + help_text="ServiceD Version", + allow_blank=True, + required=False, + allow_null=True + ) + csarName = serializers.CharField( + help_text="CSAR name", + allow_blank=True, + required=False, + allow_null=True + ) + servicedModel = serializers.CharField( + help_text="ServiceD Model", + allow_blank=True, + required=False, + allow_null=True + ) + downloadUrl = serializers.CharField( + help_text="URL to download ServiceD Model", + required=False, + allow_null=True + ) + + +class ServicePackageSerializer(serializers.Serializer): + csarId = serializers.CharField( + help_text="CSAR ID", + required=False, + allow_null=True + ) + packageInfo = ServicePackageInfoSerializer( + help_text="Service Package Info", + required=False, + allow_null=True + ) + + +class ServicePackagesSerializer(serializers.ListSerializer): + child = ServicePackageSerializer() + + class NfPackageDistributeRequestSerializer(serializers.Serializer): csarId = serializers.CharField(help_text="CSAR ID", required=True) vimIds = serializers.ListField( diff --git a/catalog/packages/tests/test_servicepackage.py b/catalog/packages/tests/test_servicepackage.py new file mode 100644 index 00000000..86d513e0 --- /dev/null +++ b/catalog/packages/tests/test_servicepackage.py @@ -0,0 +1,143 @@ +# Copyright (c) 2019, CMCC Technologies. Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.test import TestCase, Client +from rest_framework import status + +from catalog.packages.biz.sdc_service_package import ServicePackage +from catalog.pub.database.models import ServicePackageModel +from catalog.pub.exceptions import PackageNotFoundException, PackageHasExistsException + + +class TestServicePackage(TestCase): + """ Test case for Service Package operations""" + + def setUp(self): + self.client = Client() + ServicePackageModel.objects.filter().delete() + + def tearDown(self): + pass + + ############################################################### + + def test_service_pkg_distribute_when_pkg_exists(self): + ServicePackageModel(servicePackageId="1", servicedId="2").save() + csar_id = 1 + try: + ServicePackage().on_distribute(csar_id) + except PackageHasExistsException as e: + self.assertEqual("Service CSAR(1) already exists.", e.message) + + def test_api_service_pkg_distribute_when_pkg_exists(self): + ServicePackageModel(servicePackageId="1", servicedId="2").save() + resp = self.client.post( + "/api/parser/v1/service_packages", {"csarId": "1"}, format='json') + self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual("Service CSAR(1) already exists.", resp.data["errorMessage"]) + + ############################################################### + def test_service_pkg_get_all(self): + ServicePackageModel( + servicePackageId="13", + servicedId="2", + servicedDesigner="2", + servicedVersion="2", + servicePackageUri="13.csar", + servicedModel="").save() + ServicePackageModel( + servicePackageId="14", + servicedId="3", + servicedDesigner="3", + servicedVersion="3", + servicePackageUri="14.csar", + servicedModel="").save() + csars = ServicePackage().get_csars() + self.assertEqual(2, len(csars)) + + def test_api_service_pkg_get_all(self): + ServicePackageModel( + servicePackageId="13", + servicedId="2", + servicedDesigner="2", + servicedVersion="2", + servicePackageUri="13.csar", + servicedModel="").save() + ServicePackageModel( + servicePackageId="14", + servicedId="3", + servicedDesigner="3", + servicedVersion="3", + servicePackageUri="14.csar", + servicedModel="").save() + resp = self.client.get("/api/parser/v1/service_packages") + self.assertEqual(resp.status_code, status.HTTP_200_OK) + + ############################################################### + + def test_service_pkg_get_one(self): + ServicePackageModel( + servicePackageId="14", + servicedId="2", + servicedDesigner="3", + servicedVersion="4", + servicePackageUri="14.csar", + servicedModel="").save() + csar = ServicePackage().get_csar(14) + self.assertEqual(14, csar['csarId']) + + def test_service_pkg_get_one_not_found(self): + try: + ServicePackage().get_csar(1000) + except PackageNotFoundException as e: + self.assertEqual("Service package[1000] not Found.", e.message) + + def test_api_service_pkg_get_one(self): + ServicePackageModel( + servicePackageId="14", + servicedId="2", + servicedDesigner="3", + servicedVersion="4", + servicePackageUri="14.csar", + servicedModel="").save() + resp = self.client.get("/api/parser/v1/service_packages/14") + self.assertEqual(resp.status_code, status.HTTP_200_OK) + + def test_api_service_pkg_get_one_not_found(self): + resp = self.client.get("/api/parser/v1/service_packages/22") + self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND) + self.assertEqual( + {"errorMessage": "Service package[22] not Found.", 'error': 404}, + resp.data) + + ############################################################### + + def test_service_pkg_normal_delete(self): + ServicePackageModel(servicePackageId="8", servicedId="2").save() + sp = ServicePackageModel.objects.filter(servicePackageId=8) + self.assertEqual(1, len(sp)) + ServicePackage().delete_csar("8") + sp = ServicePackageModel.objects.filter(servicePackageId=8) + self.assertEqual(0, len(sp)) + + def test_service_pkg_normal_delete_not_found(self): + try: + ServicePackage().delete_csar("8000") + except PackageNotFoundException as e: + self.assertEqual("Service package[8000] not Found.", e.message) + + def test_api_service_pkg_normal_delete(self): + ServicePackageModel(servicePackageId="8", servicedId="2").save() + resp = self.client.delete("/api/parser/v1/service_packages/8") + self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT) diff --git a/catalog/packages/urls.py b/catalog/packages/urls.py index dfd13261..3a3426e5 100755 --- a/catalog/packages/urls.py +++ b/catalog/packages/urls.py @@ -27,6 +27,8 @@ urlpatterns = [ url(r'^api/catalog/v1/nspackages/(?P<csarId>[0-9a-zA-Z\-\_]+)$', catalog_views.ns_rd_csar, name='nspackage_rd'), url(r'^api/catalog/v1/vnfpackages$', catalog_views.nfpackages_rc, name='nfpackages_rc'), url(r'^api/catalog/v1/vnfpackages/(?P<csarId>[0-9a-zA-Z\-\_]+)$', catalog_views.nf_rd_csar, name='nfpackage_rd'), + url(r'^api/parser/v1/service_packages$', catalog_views.servicepackages_rc, name='servicepackages_rc'), + url(r'^api/parser/v1/service_packages/(?P<csarId>[0-9a-zA-Z\-\_]+)$', catalog_views.service_rd_csar, name='servicepackage_rd'), # NFV Model Parser url(r'^api/catalog/v1/parsernsd$', catalog_views.ns_model_parser, name='nsmodelparser_rc'), diff --git a/catalog/packages/views/catalog_views.py b/catalog/packages/views/catalog_views.py index fd7f5d43..5496c6e0 100644 --- a/catalog/packages/views/catalog_views.py +++ b/catalog/packages/views/catalog_views.py @@ -21,7 +21,9 @@ from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from catalog.packages.biz import sdc_vnf_package, sdc_ns_package -from catalog.packages.serializers.catalog_serializers import InternalErrorRequestSerializer +from catalog.packages.biz.sdc_service_package import ServicePackage +from catalog.packages.serializers.catalog_serializers import InternalErrorRequestSerializer, \ + ServicePackageDistributeRequestSerializer, ServicePackagesSerializer, ServicePackageSerializer from catalog.packages.serializers.catalog_serializers import NfPackageDistributeRequestSerializer from catalog.packages.serializers.catalog_serializers import NfPackageSerializer from catalog.packages.serializers.catalog_serializers import NfPackagesSerializer @@ -32,6 +34,8 @@ from catalog.packages.serializers.catalog_serializers import NsPackagesSerialize from catalog.packages.serializers.catalog_serializers import ParseModelRequestSerializer from catalog.packages.serializers.catalog_serializers import ParseModelResponseSerializer from catalog.packages.serializers.catalog_serializers import PostJobResponseSerializer +from catalog.packages.views.common import fmt_error_rsp +from catalog.pub.exceptions import PackageNotFoundException, PackageHasExistsException from catalog.pub.utils.syscomm import fun_name from catalog.pub.utils.values import ignore_case_get @@ -209,6 +213,117 @@ def ns_rd_csar(request, *args, **kwargs): @swagger_auto_schema( + method='POST', + operation_description="On distribute Service package", + request_body=ServicePackageDistributeRequestSerializer, + responses={ + status.HTTP_202_ACCEPTED: "", + status.HTTP_400_BAD_REQUEST: InternalErrorRequestSerializer, + status.HTTP_500_INTERNAL_SERVER_ERROR: InternalErrorRequestSerializer}) +@swagger_auto_schema( + method='GET', + operation_description="Query Service packages", + request_body=no_body, + responses={ + status.HTTP_200_OK: ServicePackagesSerializer, + status.HTTP_500_INTERNAL_SERVER_ERROR: InternalErrorRequestSerializer}) +@api_view(http_method_names=['POST', 'GET']) +def servicepackages_rc(request, *args, **kwargs): + logger.debug("Enter %s, method is %s", fun_name(), request.method) + + if request.method == 'GET': + # Gets service package list + try: + csar_list = ServicePackage().get_csars() + response_serializer = ServicePackagesSerializer(data=csar_list) + validation_error = handleValidatonError(response_serializer, False) + if validation_error: + return validation_error + return Response(data=csar_list, status=status.HTTP_200_OK) + except Exception as e: + error_status = status.HTTP_500_INTERNAL_SERVER_ERROR + return Response(data=fmt_error_rsp(e.message, error_status), status=error_status) + elif request.method == 'POST': + # Distributes the package according to the given csarId + request_serializer = ServicePackageDistributeRequestSerializer(data=request.data) + validation_error = handleValidatonError(request_serializer, True) + if validation_error: + return validation_error + + csar_id = ignore_case_get(request.data, "csarId") + logger.debug("csar_id is %s", csar_id) + try: + ServicePackage().on_distribute(csar_id) + return Response(status=status.HTTP_202_ACCEPTED) + except PackageHasExistsException as e: + error_status = status.HTTP_400_BAD_REQUEST + return Response(data=fmt_error_rsp(e.message, error_status), status=error_status) + except Exception as e: + error_status = status.HTTP_500_INTERNAL_SERVER_ERROR + return Response(data=fmt_error_rsp(e.message, error_status), status=error_status) + + +@swagger_auto_schema( + method='DELETE', + operation_description="Delete one Service package", + request_body=no_body, + manual_parameters=[ + openapi.Parameter( + 'csarId', + openapi.IN_QUERY, + "csarId", + type=openapi.TYPE_STRING)], + responses={ + status.HTTP_204_NO_CONTENT: "", + status.HTTP_404_NOT_FOUND: InternalErrorRequestSerializer, + status.HTTP_500_INTERNAL_SERVER_ERROR: InternalErrorRequestSerializer}) +@swagger_auto_schema( + method='GET', + operation_description="Query one Service package", + request_body=no_body, + manual_parameters=[ + openapi.Parameter( + 'csarId', + openapi.IN_QUERY, + "csarId", + type=openapi.TYPE_STRING)], + responses={ + status.HTTP_200_OK: ServicePackageSerializer, + status.HTTP_404_NOT_FOUND: InternalErrorRequestSerializer, + status.HTTP_500_INTERNAL_SERVER_ERROR: InternalErrorRequestSerializer}) +@api_view(http_method_names=['DELETE', 'GET']) +def service_rd_csar(request, *args, **kwargs): + csar_id = ignore_case_get(kwargs, "csarId") + logger.info("Enter %s, method is %s, csar_id is %s", fun_name(), request.method, csar_id) + + if request.method == 'GET': + try: + ret = ServicePackage().get_csar(csar_id) + response_serializer = ServicePackageSerializer(data=ret) + validation_error = handleValidatonError(response_serializer, False) + if validation_error: + return validation_error + return Response(data=ret, status=status.HTTP_200_OK) + except PackageNotFoundException as e: + error_status = status.HTTP_404_NOT_FOUND + return Response(data=fmt_error_rsp(e.message, error_status), status=error_status) + except Exception as e: + error_status = status.HTTP_500_INTERNAL_SERVER_ERROR + return Response(data=fmt_error_rsp(e.message, error_status), status=error_status) + + elif request.method == 'DELETE': + try: + ServicePackage().delete_csar(csar_id) + return Response(status=status.HTTP_204_NO_CONTENT) + except PackageNotFoundException as e: + error_status = status.HTTP_404_NOT_FOUND + return Response(data=fmt_error_rsp(e.message, error_status), status=error_status) + except Exception as e: + error_status = status.HTTP_500_INTERNAL_SERVER_ERROR + return Response(data=fmt_error_rsp(e.message, error_status), status=error_status) + + +@swagger_auto_schema( method='DELETE', operation_description="Delete one Nf package", request_body=no_body, diff --git a/catalog/packages/views/common.py b/catalog/packages/views/common.py index 5dacb771..94566ebc 100644 --- a/catalog/packages/views/common.py +++ b/catalog/packages/views/common.py @@ -25,3 +25,7 @@ def validate_data(data, serializer): logger.error('Data validation failed.') raise CatalogException(serialized_data.errors) return serialized_data + + +def fmt_error_rsp(error_message, status): + return {"errorMessage": error_message, "error": status} diff --git a/catalog/pub/database/models.py b/catalog/pub/database/models.py index ef95dea9..9f0b4985 100644 --- a/catalog/pub/database/models.py +++ b/catalog/pub/database/models.py @@ -38,6 +38,29 @@ class NSPackageModel(models.Model): db_table = 'CATALOG_NSPACKAGE' +class ServicePackageModel(models.Model): + servicePackageId = models.CharField(db_column='SERVICEPACKAGEID', primary_key=True, max_length=50) + servicePackageUri = models.CharField(db_column='SERVICEPACKAGEURI', max_length=300, null=True, blank=True) + checksum = models.CharField(db_column='CHECKSUM', max_length=50, null=True, blank=True) # checksum + sdcCsarId = models.CharField(db_column='SDCCSARID', max_length=50, null=True, blank=True) # SdcCSARUri + onboardingState = models.CharField(db_column='ONBOARDINGSTATE', max_length=20, blank=True, null=True) + operationalState = models.CharField(db_column='OPERATIONALSTATE', max_length=20, blank=True, null=True) # operationalState + usageState = models.CharField(db_column='USAGESTATE', max_length=20, blank=True, null=True) # usageState + deletionPending = models.CharField(db_column='DELETIONPENDING', max_length=20, blank=True, null=True) # deletionPending + servicedId = models.CharField(db_column='SERVICEDID', max_length=50, blank=True, null=True) + invariantId = models.CharField(db_column='INVARIANTID', max_length=50, blank=True, null=True) # servicedInvariantId + servicedName = models.CharField(db_column='SERVICEDNAME', max_length=50, blank=True, null=True) + servicedDesigner = models.CharField(db_column='SERVICEDDESIGNER', max_length=50, null=True, blank=True) + servicedDescription = models.CharField(db_column='SERVICEDDESCRIPTION', max_length=100, null=True, blank=True) + servicedVersion = models.CharField(db_column='SERVICEDVERSION', max_length=20, null=True, blank=True) + userDefinedData = models.TextField(db_column='USERDEFINEDDATA', max_length=1024, blank=True, null=True) # userDefinedData + localFilePath = models.CharField(db_column='LOCALFILEPATH', max_length=300, null=True, blank=True) + servicedModel = models.TextField(db_column='SERVICEDMODEL', max_length=65535, null=True, blank=True) + + class Meta: + db_table = 'CATALOG_SERVICEPACKAGE' + + class VnfPackageModel(models.Model): # uuid = models.CharField(db_column='UUID', primary_key=True, max_length=255) vnfPackageId = models.CharField(db_column='VNFPACKAGEID', primary_key=True, max_length=50) # onboardedVnfPkgInfoId diff --git a/catalog/pub/exceptions.py b/catalog/pub/exceptions.py index afe45d16..a9354204 100644 --- a/catalog/pub/exceptions.py +++ b/catalog/pub/exceptions.py @@ -21,6 +21,14 @@ class ResourceNotFoundException(CatalogException): pass +class PackageNotFoundException(CatalogException): + pass + + +class PackageHasExistsException(CatalogException): + pass + + class VnfPkgSubscriptionException(CatalogException): pass |