summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordyh <dengyuanhong@chinamobile.com>2019-03-28 10:02:38 +0800
committerdyh <dengyuanhong@chinamobile.com>2019-03-28 10:02:50 +0800
commit9737bb0c33deae190beff671fb35132ab4934b12 (patch)
treed1030a5cd3965a088aace648fd88b34365a96059
parent50baae0e33075cd8751c0a15afa9342beec9ac85 (diff)
1.Implement parser RESTAPI. 2.Add UT cases.
Change-Id: I33cd9dc53a00d955d7be3e1cff510aa9dfa263a7 Issue-ID: VFC-1318 Signed-off-by: dyh <dengyuanhong@chinamobile.com>
-rw-r--r--catalog/packages/biz/sdc_service_package.py12
-rw-r--r--catalog/packages/biz/sdc_vnf_package.py2
-rw-r--r--catalog/packages/biz/service_descriptor.py9
-rw-r--r--catalog/packages/serializers/catalog_serializers.py1
-rw-r--r--catalog/packages/tests/test_service_descriptor.py90
-rw-r--r--catalog/packages/tests/test_servicepackage.py81
-rwxr-xr-xcatalog/packages/urls.py4
-rw-r--r--catalog/packages/views/catalog_views.py61
8 files changed, 243 insertions, 17 deletions
diff --git a/catalog/packages/biz/sdc_service_package.py b/catalog/packages/biz/sdc_service_package.py
index bae1f71d..713ab056 100644
--- a/catalog/packages/biz/sdc_service_package.py
+++ b/catalog/packages/biz/sdc_service_package.py
@@ -46,11 +46,7 @@ class ServicePackage(object):
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
-
+ fileutil.unzip_file(local_file_name, local_path, "")
data = {
'userDefinedData': {}
}
@@ -94,11 +90,13 @@ class ServicePackage(object):
csar_id,
csars[0].servicePackageUri)
else:
- raise PackageNotFoundException("Service package[%s] not Found." % csar_id)
+ error_message = "Service package[%s] not Found." % csar_id
+ logger.error(error_message)
+ raise PackageNotFoundException(error_message)
return {"csarId": csar_id, "packageInfo": package_info}
- def parse_serviced(csar_id, inputs):
+ def parse_serviced(self, 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)
diff --git a/catalog/packages/biz/sdc_vnf_package.py b/catalog/packages/biz/sdc_vnf_package.py
index 71eee499..d1ee4c7d 100644
--- a/catalog/packages/biz/sdc_vnf_package.py
+++ b/catalog/packages/biz/sdc_vnf_package.py
@@ -19,6 +19,7 @@ import sys
import threading
import traceback
+from catalog.packages.const import PKG_STATUS
from catalog.pub.config.config import CATALOG_ROOT_PATH, CATALOG_URL_PATH
from catalog.pub.config.config import REG_TO_MSB_REG_PARAM
from catalog.pub.database.models import VnfPackageModel
@@ -27,7 +28,6 @@ from catalog.pub.msapi import sdc
from catalog.pub.utils import fileutil
from catalog.pub.utils import toscaparser
from catalog.pub.utils.jobutil import JobUtil
-from catalog.packages.const import PKG_STATUS
logger = logging.getLogger(__name__)
diff --git a/catalog/packages/biz/service_descriptor.py b/catalog/packages/biz/service_descriptor.py
index 72a561ae..4b9a2aad 100644
--- a/catalog/packages/biz/service_descriptor.py
+++ b/catalog/packages/biz/service_descriptor.py
@@ -28,15 +28,18 @@ logger = logging.getLogger(__name__)
class ServiceDescriptor(object):
+ """
+ Action for Service Descriptor
+ """
def __init__(self):
pass
- def create(self, data, csar_id):
+ def create(self, data, csar_id=None):
logger.info('Start to create a ServiceD...')
user_defined_data = ignore_case_get(data, 'userDefinedData', {})
data = {
- 'id': id if id else str(uuid.uuid4()),
+ 'id': csar_id if csar_id else str(uuid.uuid4()),
'servicedOnboardingState': PKG_STATUS.CREATED,
'servicedOperationalState': PKG_STATUS.DISABLED,
'servicedUsageState': PKG_STATUS.NOT_IN_USE,
@@ -58,7 +61,7 @@ class ServiceDescriptor(object):
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
+ serviced_json = toscaparser.parse_nsd(local_file_name)
logger.debug("%s", serviced_json)
serviced = json.JSONDecoder().decode(serviced_json)
diff --git a/catalog/packages/serializers/catalog_serializers.py b/catalog/packages/serializers/catalog_serializers.py
index 0e830e5e..4007c34a 100644
--- a/catalog/packages/serializers/catalog_serializers.py
+++ b/catalog/packages/serializers/catalog_serializers.py
@@ -282,6 +282,7 @@ class PostJobResponseSerializer(serializers.Serializer):
class ParseModelRequestSerializer(serializers.Serializer):
csarId = serializers.CharField(help_text="CSAR ID", required=True)
+ packageType = serializers.CharField(help_text="Package type: VNF, PNF, NS, Service", required=False)
inputs = serializers.JSONField(help_text="Inputs", required=False)
diff --git a/catalog/packages/tests/test_service_descriptor.py b/catalog/packages/tests/test_service_descriptor.py
new file mode 100644
index 00000000..d0dc83fd
--- /dev/null
+++ b/catalog/packages/tests/test_service_descriptor.py
@@ -0,0 +1,90 @@
+# 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
+
+from django.test import TestCase
+
+from catalog.packages.biz.service_descriptor import ServiceDescriptor
+from catalog.packages.const import PKG_STATUS
+from catalog.pub.database.models import ServicePackageModel
+from catalog.pub.exceptions import PackageNotFoundException
+
+logger = logging.getLogger(__name__)
+
+
+class TestServiceDescription(TestCase):
+
+ def setUp(self):
+ self.user_defined_data = {
+ 'key1': 'value1',
+ 'key2': 'value2',
+ 'key3': 'value3',
+ }
+ self.data = {
+ 'userDefinedData': self.user_defined_data,
+ }
+ ServicePackageModel.objects.filter().delete()
+
+ def tearDown(self):
+ pass
+
+ def test_create(self):
+ result_data = ServiceDescriptor().create(self.data)
+ self.assertIsNotNone(result_data['id'])
+ service_package = ServicePackageModel.objects.filter(servicePackageId=result_data['id'])[0]
+ self.assertIsNotNone(service_package)
+ self.assertEqual(PKG_STATUS.DISABLED, service_package.operationalState)
+ self.assertEqual(PKG_STATUS.CREATED, service_package.onboardingState)
+ self.assertEqual(PKG_STATUS.NOT_IN_USE, service_package.usageState)
+
+ def test_create_with_csarid(self):
+ csar_id = '0b667470-e6b3-4ee8-8f08-186317a04dc2'
+ result_data = ServiceDescriptor().create(self.data, csar_id)
+ self.assertEqual(csar_id, result_data['id'])
+ service_package = ServicePackageModel.objects.filter(servicePackageId=csar_id)[0]
+ self.assertIsNotNone(service_package)
+ self.assertEqual(PKG_STATUS.DISABLED, service_package.operationalState)
+ self.assertEqual(PKG_STATUS.CREATED, service_package.onboardingState)
+ self.assertEqual(PKG_STATUS.NOT_IN_USE, service_package.usageState)
+
+ def test_parse_serviced_and_save(self):
+ try:
+ servcie_desc = ServiceDescriptor()
+ csar_id = '0b667470-e6b3-4ee8-8f08-186317a04dc2'
+ servcie_desc.create(self.data, csar_id)
+
+ local_file_name = "C:\\work\\onap\\api_test_data\\service\\service-Sotnvpninfraservice-csar.csar"
+ servcie_desc.parse_serviced_and_save(csar_id, local_file_name)
+
+ service_package = ServicePackageModel.objects.filter(servicePackageId=csar_id)[0]
+ self.assertIsNotNone(service_package)
+ except Exception as e:
+ logger.error(e.message)
+
+ def test_delete_single(self):
+ servcie_desc = ServiceDescriptor()
+ csar_id = '0b667470-e6b3-4ee8-8f08-186317a04dc2'
+ servcie_desc.create(self.data, csar_id)
+
+ servcie_desc.delete_single(csar_id)
+ self.assertTrue(len(ServicePackageModel.objects.filter(servicePackageId=csar_id)) == 0)
+ self.assertFalse(ServicePackageModel.objects.filter(servicePackageId=csar_id).exists())
+
+ def test_delete_single_not_exists(self):
+ csar_id = "8000"
+ try:
+ ServiceDescriptor().delete_single(csar_id)
+ except Exception as e:
+ self.assertTrue(isinstance(e, PackageNotFoundException))
+ self.assertEqual("Service package[8000] not Found.", e.message)
diff --git a/catalog/packages/tests/test_servicepackage.py b/catalog/packages/tests/test_servicepackage.py
index 86d513e0..9365c295 100644
--- a/catalog/packages/tests/test_servicepackage.py
+++ b/catalog/packages/tests/test_servicepackage.py
@@ -11,13 +11,19 @@
# 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
from django.test import TestCase, Client
+from mock import mock
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
+from catalog.pub.exceptions import PackageNotFoundException, PackageHasExistsException, CatalogException
+from catalog.pub.msapi import sdc
+from catalog.pub.utils import toscaparser
+
+PARSER_BASE_URL = "/api/parser/v1"
class TestServicePackage(TestCase):
@@ -40,14 +46,49 @@ class TestServicePackage(TestCase):
except PackageHasExistsException as e:
self.assertEqual("Service CSAR(1) already exists.", e.message)
+ @mock.patch.object(sdc, 'get_artifact')
+ def test_service_pkg_distribute_when_fail_get_artifacts(self, mock_get_artifact):
+ mock_get_artifact.side_effect = CatalogException("Failed to query artifact(services,1) from sdc.")
+ csar_id = 1
+ try:
+ ServicePackage().on_distribute(csar_id)
+ except Exception as e:
+ self.assertTrue(isinstance(e, CatalogException))
+ self.assertEqual("Failed to query artifact(services,1) from sdc.", e.message)
+
+ @mock.patch.object(sdc, 'get_artifact')
+ @mock.patch.object(sdc, 'download_artifacts')
+ def test_api_service_pkg_distribute_when_fail_download_artifacts(self, mock_get_artifact, mock_download_artifacts):
+ mock_get_artifact.return_value = {
+ "uuid": "1",
+ "invariantUUID": "63eaec39-ffbe-411c-a838-448f2c73f7eb",
+ "name": "underlayvpn",
+ "version": "2.0",
+ "toscaModelURL": "/sdc/v1/catalog/resources/c94490a0-f7ef-48be-b3f8-8d8662a37236/toscaModel",
+ "category": "Volte",
+ "subCategory": "VolteVNF",
+ "resourceType": "VF",
+ "lifecycleState": "CERTIFIED",
+ "distributionStatus": "DISTRIBUTION_APPROVED",
+ "lastUpdaterUserId": "jh0003"
+ }
+ mock_download_artifacts.side_effect = CatalogException("Failed to download 1 from sdc.")
+ csar_id = 1
+ try:
+ ServicePackage().on_distribute(csar_id)
+ except Exception as e:
+ self.assertTrue(isinstance(e, CatalogException))
+ self.assertEqual("Failed to download 1 from sdc.", 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')
+ PARSER_BASE_URL + "/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",
@@ -81,7 +122,7 @@ class TestServicePackage(TestCase):
servicedVersion="3",
servicePackageUri="14.csar",
servicedModel="").save()
- resp = self.client.get("/api/parser/v1/service_packages")
+ resp = self.client.get(PARSER_BASE_URL + "/service_packages")
self.assertEqual(resp.status_code, status.HTTP_200_OK)
###############################################################
@@ -111,11 +152,11 @@ class TestServicePackage(TestCase):
servicedVersion="4",
servicePackageUri="14.csar",
servicedModel="").save()
- resp = self.client.get("/api/parser/v1/service_packages/14")
+ resp = self.client.get(PARSER_BASE_URL + "/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")
+ resp = self.client.get(PARSER_BASE_URL + "/service_packages/22")
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(
{"errorMessage": "Service package[22] not Found.", 'error': 404},
@@ -139,5 +180,33 @@ class TestServicePackage(TestCase):
def test_api_service_pkg_normal_delete(self):
ServicePackageModel(servicePackageId="8", servicedId="2").save()
- resp = self.client.delete("/api/parser/v1/service_packages/8")
+ resp = self.client.delete(PARSER_BASE_URL + "/service_packages/8")
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
+
+ ###############################################################
+
+ @mock.patch.object(toscaparser, 'parse_nsd')
+ def test_service_pkg_parser(self, mock_parse_nsd):
+ ServicePackageModel(servicePackageId="8", servicedId="2").save()
+ mock_parse_nsd.return_value = json.JSONEncoder().encode({"a": "b"})
+
+ inputs = []
+ ret = ServicePackage().parse_serviced(8, inputs)
+ self.assertTrue({"model": '{"c": "d"}'}, ret)
+
+ def test_service_pkg_parser_not_found(self):
+ try:
+ csar_id = 8000
+ inputs = []
+ ServicePackage().parse_serviced(csar_id, inputs)
+ except PackageNotFoundException as e:
+ self.assertEqual("Service CSAR(8000) does not exist.", e.message)
+
+ def test_api_service_pkg_parser_not_found(self):
+ query_data = {
+ "csarId": "1",
+ "packageType": "Service",
+ "inputs": "string"
+ }
+ resp = self.client.post(PARSER_BASE_URL + "/parser", query_data, format='json')
+ self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
diff --git a/catalog/packages/urls.py b/catalog/packages/urls.py
index 3a3426e5..16301d30 100755
--- a/catalog/packages/urls.py
+++ b/catalog/packages/urls.py
@@ -31,6 +31,10 @@ urlpatterns = [
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/parser/v1/parser$', catalog_views.model_parser, name='modelparser_rc'),
+ url(r'^api/parser/v1/parsernsd$', catalog_views.ns_model_parser, name='nsmodelparser_rc'),
+ url(r'^api/parser/v1/parservnfd$', catalog_views.vnf_model_parser, name='vnfmodelparser_rc'),
+ url(r'^api/parser/v1/parserpnfd$', pnf_descriptor_views.pnf_model_parser, name='pnfmodelparser_rc'),
url(r'^api/catalog/v1/parsernsd$', catalog_views.ns_model_parser, name='nsmodelparser_rc'),
url(r'^api/catalog/v1/parservnfd$', catalog_views.vnf_model_parser, name='vnfmodelparser_rc'),
url(r'^api/catalog/v1/parserpnfd$', pnf_descriptor_views.pnf_model_parser, name='pnfmodelparser_rc'),
diff --git a/catalog/packages/views/catalog_views.py b/catalog/packages/views/catalog_views.py
index 5496c6e0..f9cc4803 100644
--- a/catalog/packages/views/catalog_views.py
+++ b/catalog/packages/views/catalog_views.py
@@ -21,6 +21,7 @@ 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.biz.pnf_descriptor import PnfDescriptor
from catalog.packages.biz.sdc_service_package import ServicePackage
from catalog.packages.serializers.catalog_serializers import InternalErrorRequestSerializer, \
ServicePackageDistributeRequestSerializer, ServicePackagesSerializer, ServicePackageSerializer
@@ -391,6 +392,66 @@ def nf_rd_csar(request, *args, **kwargs):
@swagger_auto_schema(
method='POST',
+ operation_description="Parse model(NS, Service, VNF, PNF)",
+ request_body=ParseModelRequestSerializer,
+ responses={
+ status.HTTP_202_ACCEPTED: ParseModelResponseSerializer,
+ status.HTTP_500_INTERNAL_SERVER_ERROR: InternalErrorRequestSerializer})
+@api_view(http_method_names=['POST'])
+def model_parser(request, *args, **kwargs):
+ csar_id = ignore_case_get(request.data, "csarId")
+ package_type = ignore_case_get(request.data, "packageType")
+ inputs = ignore_case_get(request.data, "inputs")
+ logger.debug(
+ "Enter %s, csar_id=%s, package_type=%s, inputs=%s",
+ fun_name(),
+ csar_id,
+ package_type,
+ inputs)
+
+ if package_type.lower().__eq__("service"):
+ try:
+ ret = ServicePackage().parse_serviced(csar_id, inputs)
+ response_serializer = ParseModelResponseSerializer(data=ret)
+ validation_error = handleValidatonError(
+ response_serializer, False)
+ if validation_error:
+ return validation_error
+ return Response(data=response_serializer.data, status=status.HTTP_202_ACCEPTED)
+ 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 package_type.lower().__eq__("ns"):
+ ret = sdc_ns_package.parse_nsd(csar_id, inputs)
+ elif package_type.lower().__eq__("vnf"):
+ ret = sdc_vnf_package.parse_vnfd(csar_id, inputs)
+ elif package_type.lower().__eq__("pnf"):
+ ret = PnfDescriptor().parse_pnfd(csar_id, inputs)
+ else:
+ error_status = status.HTTP_400_BAD_REQUEST
+ error_message = "Invalid package type, it should be one of [VNF, PNF, NS, Service]"
+ return Response(data=fmt_error_rsp(error_message, error_status), status=error_status)
+
+ if ret[0] != 0:
+ return Response(
+ data={
+ 'error': ret[1]},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ response_serializer = ParseModelResponseSerializer(data=ret[1])
+ validation_error = handleValidatonError(
+ response_serializer, False)
+ if validation_error:
+ return validation_error
+
+ return Response(data=response_serializer.data, status=status.HTTP_202_ACCEPTED)
+
+
+@swagger_auto_schema(
+ method='POST',
operation_description="Parse NS model",
request_body=ParseModelRequestSerializer,
responses={