aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBharath Thiruveedula <bharath.thiruveedula@verizon.com>2019-03-13 20:37:34 +0530
committerBharath Thiruveedula <bharath.thiruveedula@verizon.com>2019-03-13 22:29:55 +0530
commit1efbbf8a1ed35996766d3aed5b69f03e4dbe4d1a (patch)
tree8cb1b0afce60f7187c0322aa0c2dd6add0dffca8
parentfcba1c612c515d78fb3f8ff5eb7add34968ea3ff (diff)
Add fetch artifacts API
Add SOL 005 Fetch Artifacts API Issue-ID: VFC-1220 Change-Id: I25752ad11ea7179ca14ef6ce3d5042874e443330 Signed-off-by: Bharath Thiruveedula <bharath.thiruveedula@verizon.com>
-rw-r--r--.gitignore1
-rw-r--r--catalog/packages/biz/vnf_pkg_artifacts.py39
-rw-r--r--catalog/packages/tests/test_vnf_package.py40
-rwxr-xr-xcatalog/packages/urls.py2
-rw-r--r--catalog/packages/views/vnf_package_artifact_views.py77
-rw-r--r--catalog/pub/exceptions.py4
-rw-r--r--catalog/pub/utils/fileutil.py15
-rw-r--r--static/catalog/resource_test.csarbin0 -> 227 bytes
8 files changed, 177 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 54a7acb3..e6ae5450 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,5 +5,4 @@ logs/*.log
target
htmlcov
.coverage
-static/*/*
test-reports/*
diff --git a/catalog/packages/biz/vnf_pkg_artifacts.py b/catalog/packages/biz/vnf_pkg_artifacts.py
new file mode 100644
index 00000000..1077228a
--- /dev/null
+++ b/catalog/packages/biz/vnf_pkg_artifacts.py
@@ -0,0 +1,39 @@
+# Copyright (C) 2019 Verizon. All Rights Reserved
+#
+# 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 catalog.pub.database.models import VnfPackageModel
+from catalog.pub.exceptions import ResourceNotFoundException, ArtifactNotFoundException
+from catalog.pub.utils import fileutil
+
+logger = logging.getLogger(__name__)
+
+
+class FetchVnfPkgArtifact(object):
+ def fetch(self, vnfPkgId, artifactPath):
+ logger.debug("FetchVnfPkgArtifact--get--single--artifact--biz::>"
+ "ID: %s path: %s" % (vnfPkgId, artifactPath))
+ vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnfPkgId).get()
+ if not vnf_pkg:
+ err_msg = "NF Package (%s) doesn't exists." % vnfPkgId
+ return ResourceNotFoundException(err_msg)
+ local_path = vnf_pkg.localFilePath
+ if local_path.endswith(".csar") or local_path.endswith(".zip"):
+ vnf_extract_path = fileutil.unzip_csar_to_tmp(local_path)
+ artifact_path = fileutil.get_artifact_path(vnf_extract_path, artifactPath)
+ if not artifact_path:
+ raise ArtifactNotFoundException("Couldn't artifact %s" % artifactPath)
+ file_content = open(artifact_path, 'rb').read()
+ return file_content
diff --git a/catalog/packages/tests/test_vnf_package.py b/catalog/packages/tests/test_vnf_package.py
index 701a22ed..135c9838 100644
--- a/catalog/packages/tests/test_vnf_package.py
+++ b/catalog/packages/tests/test_vnf_package.py
@@ -321,3 +321,43 @@ class TestVnfPackage(TestCase):
mock_download.side_effect = TypeError("integer type")
response = self.client.get("/api/vnfpkgm/v1/vnf_packages/222/package_content")
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ @mock.patch.object(toscaparser, 'parse_vnfd')
+ def test_fetch_vnf_artifact(self, mock_parse_vnfd):
+ data = {'file': open(os.path.join(CATALOG_ROOT_PATH, "resource_test.csar"), "rb")}
+ VnfPackageModel.objects.create(
+ vnfPackageId="222",
+ onboardingState="CREATED"
+ )
+ mock_parse_vnfd.return_value = json.JSONEncoder().encode(vnfd_data)
+ response = self.client.put("/api/vnfpkgm/v1/vnf_packages/222/package_content", data=data)
+ self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
+ response = self.client.get("/api/vnfpkgm/v1/vnf_packages/222/artifacts/image")
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.getvalue(), "ubuntu_16.04\n")
+
+ @mock.patch.object(toscaparser, 'parse_vnfd')
+ def test_fetch_vnf_artifact_not_exists(self, mock_parse_vnfd):
+ data = {'file': open(os.path.join(CATALOG_ROOT_PATH, "resource_test.csar"), "rb")}
+ VnfPackageModel.objects.create(
+ vnfPackageId="222",
+ onboardingState="CREATED"
+ )
+ mock_parse_vnfd.return_value = json.JSONEncoder().encode(vnfd_data)
+ response = self.client.put("/api/vnfpkgm/v1/vnf_packages/222/package_content", data=data)
+ self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
+ response = self.client.get("/api/vnfpkgm/v1/vnf_packages/2224/artifacts/image")
+ self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
+
+ @mock.patch.object(toscaparser, 'parse_vnfd')
+ def test_fetch_vnf_artifact_vnf_not_exists(self, mock_parse_vnfd):
+ data = {'file': open(os.path.join(CATALOG_ROOT_PATH, "resource_test.csar"), "rb")}
+ VnfPackageModel.objects.create(
+ vnfPackageId="222",
+ onboardingState="CREATED"
+ )
+ mock_parse_vnfd.return_value = json.JSONEncoder().encode(vnfd_data)
+ response = self.client.put("/api/vnfpkgm/v1/vnf_packages/222/package_content", data=data)
+ self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
+ response = self.client.get("/api/vnfpkgm/v1/vnf_packages/222/artifacts/image1")
+ self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
diff --git a/catalog/packages/urls.py b/catalog/packages/urls.py
index a6fb6003..dfd13261 100755
--- a/catalog/packages/urls.py
+++ b/catalog/packages/urls.py
@@ -16,6 +16,7 @@ from django.conf.urls import url
from catalog.packages.views import vnf_package_views
from catalog.packages.views.vnf_package_subscription_views import CreateQuerySubscriptionView, QueryTerminateSubscriptionView
+from catalog.packages.views.vnf_package_artifact_views import FetchVnfPkgmArtifactsView
from catalog.packages.views import catalog_views, ns_descriptor_views, pnf_descriptor_views, nsdm_subscription_views
@@ -53,6 +54,7 @@ urlpatterns = [
# ETSI SOL 005 VNF Package Management Subscription APIs
url(r'^api/vnfpkgm/v1/subscriptions$', CreateQuerySubscriptionView.as_view(), name='subscriptions_create_query'),
url(r'^api/vnfpkgm/v1/subscriptions/(?P<subscriptionId>[0-9a-zA-Z\-\_]+)$', QueryTerminateSubscriptionView.as_view(), name='subscriptions_query_terminate'),
+ url(r'^api/vnfpkgm/v1/vnf_packages/(?P<vnfPkgId>[0-9a-zA-Z\-\_]+)/artifacts/(?P<artifactPath>[0-9a-zA-Z\-\_]+)$', FetchVnfPkgmArtifactsView.as_view(), name="fetch_vnf_artifacts"),
# url(r'^api/vnfpkgm/v1/subscriptions/(?P<vnfPkgId>[0-9a-zA-Z\-\_]+)$', vnf_package_subscription_views.vnf_package_subscriptions_rc, name='subscriptions_rc'),
# url(r'^api/vnfpkgm/v1/vnf_packages/(?P<vnfPkgId>[0-9a-zA-Z\-\_]+)/vnfd$', vnfd.as_view(), name='vnfd_r'),# url(r'^api/vnfpkgm/v1/vnf_packages/(?P<vnfPkgId>[0-9a-zA-Z\-\_]+)/artifacts/artifactPath$', artifacts.as_view(), name='artifacts_r'),
diff --git a/catalog/packages/views/vnf_package_artifact_views.py b/catalog/packages/views/vnf_package_artifact_views.py
new file mode 100644
index 00000000..c321ccaa
--- /dev/null
+++ b/catalog/packages/views/vnf_package_artifact_views.py
@@ -0,0 +1,77 @@
+# Copyright (C) 2019 Verizon. All Rights Reserved
+#
+# 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 traceback
+import logging
+
+from drf_yasg.utils import swagger_auto_schema
+from rest_framework import status
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from django.http import FileResponse
+
+from catalog.packages.serializers.response import ProblemDetailsSerializer
+from catalog.packages.biz.vnf_pkg_artifacts import FetchVnfPkgArtifact
+from catalog.pub.exceptions import ResourceNotFoundException, ArtifactNotFoundException
+
+logger = logging.getLogger(__name__)
+VALID_FILTERS = ["callbackUri", "notificationTypes", "vnfdId", "vnfPkgId", "operationalState", "usageState"]
+
+
+def get_problem_details_serializer(status_code, error_message):
+ problem_details = {
+ "status": status_code,
+ "detail": error_message
+ }
+ problem_details_serializer = ProblemDetailsSerializer(data=problem_details)
+ problem_details_serializer.is_valid()
+ return problem_details_serializer
+
+
+class FetchVnfPkgmArtifactsView(APIView):
+
+ @swagger_auto_schema(
+ responses={
+ status.HTTP_200_OK: None,
+ status.HTTP_404_NOT_FOUND: ProblemDetailsSerializer(),
+ status.HTTP_500_INTERNAL_SERVER_ERROR: ProblemDetailsSerializer()
+ }
+ )
+ def get(self, request, vnfPkgId, artifactPath):
+ logger.debug("FetchVnfPkgmArtifactsView--get::> ")
+ try:
+
+ resp_data = FetchVnfPkgArtifact().fetch(vnfPkgId, artifactPath)
+ response = FileResponse(resp_data)
+
+ return response
+ except ResourceNotFoundException as e:
+ logger.error(e.message)
+ logger.error(traceback.format_exc())
+ problem_details_serializer = get_problem_details_serializer(status.HTTP_404_NOT_FOUND,
+ traceback.format_exc())
+ return Response(data=problem_details_serializer.data, status=status.HTTP_404_NOT_FOUND)
+ except ArtifactNotFoundException as e:
+ logger.error(e.message)
+ logger.error(traceback.format_exc())
+ problem_details_serializer = get_problem_details_serializer(status.HTTP_404_NOT_FOUND,
+ traceback.format_exc())
+ return Response(data=problem_details_serializer.data, status=status.HTTP_404_NOT_FOUND)
+ except Exception as e:
+ logger.error(e.message)
+ logger.error(traceback.format_exc())
+ problem_details_serializer = get_problem_details_serializer(status.HTTP_404_NOT_FOUND,
+ traceback.format_exc())
+ return Response(data=problem_details_serializer.data, status=status.HTTP_404_NOT_FOUND)
diff --git a/catalog/pub/exceptions.py b/catalog/pub/exceptions.py
index 96c2fd95..afe45d16 100644
--- a/catalog/pub/exceptions.py
+++ b/catalog/pub/exceptions.py
@@ -39,3 +39,7 @@ class NsdmBadRequestException(CatalogException):
class NsdmDuplicateSubscriptionException(CatalogException):
pass
+
+
+class ArtifactNotFoundException(CatalogException):
+ pass
diff --git a/catalog/pub/utils/fileutil.py b/catalog/pub/utils/fileutil.py
index 48b64cb7..d7811b8f 100644
--- a/catalog/pub/utils/fileutil.py
+++ b/catalog/pub/utils/fileutil.py
@@ -14,6 +14,7 @@
import os
import shutil
import logging
+import tempfile
import traceback
import urllib2
import zipfile
@@ -62,3 +63,17 @@ def unzip_file(zip_src, dst_dir, csar_path):
return os.path.join(dst_dir, csar_path)
else:
return ""
+
+
+def unzip_csar_to_tmp(zip_src):
+ dirpath = tempfile.mkdtemp()
+ zip_ref = zipfile.ZipFile(zip_src, 'r')
+ zip_ref.extractall(dirpath)
+ return dirpath
+
+
+def get_artifact_path(vnf_path, artifact_file):
+ for root, dirs, files in os.walk(vnf_path):
+ if artifact_file in files:
+ return os.path.join(root, artifact_file)
+ return None
diff --git a/static/catalog/resource_test.csar b/static/catalog/resource_test.csar
new file mode 100644
index 00000000..1cf038d7
--- /dev/null
+++ b/static/catalog/resource_test.csar
Binary files differ