summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--catalog/packages/biz/vnf_package.py66
-rw-r--r--catalog/packages/serializers/vnf_pkg_infos.py2
-rw-r--r--catalog/packages/tests/test_vnf_package.py100
-rw-r--r--catalog/packages/views/vnf_package_views.py74
-rw-r--r--catalog/pub/utils/tests.py6
-rwxr-xr-xdocker/build_image.sh2
-rw-r--r--pom.xml4
-rw-r--r--version.properties2
8 files changed, 209 insertions, 47 deletions
diff --git a/catalog/packages/biz/vnf_package.py b/catalog/packages/biz/vnf_package.py
index d63df9ae..d3f1f587 100644
--- a/catalog/packages/biz/vnf_package.py
+++ b/catalog/packages/biz/vnf_package.py
@@ -21,6 +21,8 @@ import traceback
import urllib2
import uuid
+from rest_framework import status
+from django.http import FileResponse, StreamingHttpResponse
from catalog.pub.config.config import CATALOG_ROOT_PATH
from catalog.pub.database.models import VnfPackageModel
from catalog.pub.exceptions import CatalogException
@@ -58,30 +60,16 @@ def query_multiple():
if not nf_pkgs.exists():
raise CatalogException('VNF packages do not exist.')
for nf_pkg in nf_pkgs:
- ret = query_single(nf_pkg.vnfPackageId)
+ ret = fill_response_data(nf_pkg)
pkgs_info.append(ret)
return pkgs_info
def query_single(vnf_pkg_id):
- pkg_info = {}
nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
if not nf_pkg.exists():
raise CatalogException('VNF package(%s) does not exist.' % vnf_pkg_id)
- pkg_info["id"] = nf_pkg[0].vnfPackageId
- pkg_info["vnfdId"] = nf_pkg[0].vnfdId
- pkg_info["vnfProductName"] = nf_pkg[0].vnfdProductName
- pkg_info["vnfSoftwareVersion"] = nf_pkg[0].vnfSoftwareVersion
- pkg_info["vnfdVersion"] = nf_pkg[0].vnfdVersion
- pkg_info["checksum"] = json.JSONDecoder().decode(nf_pkg[0].checksum)
- pkg_info["softwareImages"] = None # TODO
- pkg_info["additionalArtifacts"] = None # TODO
- pkg_info["onboardingState"] = nf_pkg[0].onboardingState
- pkg_info["operationalState"] = nf_pkg[0].operationalState
- pkg_info["usageState"] = nf_pkg[0].usageState
- pkg_info["userDefinedData"] = json.JSONDecoder().decode(nf_pkg[0].userDefinedData)
- pkg_info["_links"] = None # TODO
- return pkg_info
+ return fill_response_data(nf_pkg[0])
def delete_vnf_pkg(vnf_pkg_id):
@@ -160,3 +148,49 @@ class VnfPkgUploadThread(threading.Thread):
save_file.write(req.read())
save_file.close()
req.close()
+
+
+def fill_response_data(nf_pkg):
+ pkg_info = {}
+ pkg_info["id"] = nf_pkg.vnfPackageId
+ pkg_info["vnfdId"] = nf_pkg.vnfdId
+ pkg_info["vnfProductName"] = nf_pkg.vnfdProductName
+ pkg_info["vnfSoftwareVersion"] = nf_pkg.vnfSoftwareVersion
+ pkg_info["vnfdVersion"] = nf_pkg.vnfdVersion
+ if nf_pkg.checksum:
+ pkg_info["checksum"] = json.JSONDecoder().decode(nf_pkg.checksum)
+ pkg_info["softwareImages"] = None # TODO
+ pkg_info["additionalArtifacts"] = None # TODO
+ pkg_info["onboardingState"] = nf_pkg.onboardingState
+ pkg_info["operationalState"] = nf_pkg.operationalState
+ pkg_info["usageState"] = nf_pkg.usageState
+ if nf_pkg.userDefinedData:
+ pkg_info["userDefinedData"] = json.JSONDecoder().decode(nf_pkg.userDefinedData)
+ pkg_info["_links"] = None # TODO
+ return pkg_info
+
+
+def fetch_vnf_pkg(request, vnf_pkg_id):
+ nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
+ if not nf_pkg.exists():
+ raise CatalogException("VNF package (%s) does not exist" % vnf_pkg_id)
+ if nf_pkg[0].onboardingState != "ONBOARDED":
+ raise CatalogException("VNF package (%s) is not on-boarded" % vnf_pkg_id)
+ file_path = nf_pkg[0].localFilePath
+ file_name = file_path.split('/')[-1]
+ file_name = file_name.split('\\')[-1]
+ file_range = request.META.get('RANGE')
+ if file_range:
+ start_end = file_range.split('-')
+ start = int(start_end[0])
+ end = int(start_end[1])
+ f = open(file_path, "rb")
+ f.seek(start, 0)
+ fs = f.read(end - start + 1)
+ response = StreamingHttpResponse(fs, status=status.HTTP_200_OK)
+ response['Content-Type'] = 'application/octet-stream'
+ response['Content-Range'] = file_range
+ else:
+ response = FileResponse(open(file_path, 'rb'), status=status.HTTP_200_OK)
+ response['Content-Disposition'] = 'attachment; filename=%s' % file_name.encode('utf-8')
+ return response
diff --git a/catalog/packages/serializers/vnf_pkg_infos.py b/catalog/packages/serializers/vnf_pkg_infos.py
index 592ed071..d4cbc655 100644
--- a/catalog/packages/serializers/vnf_pkg_infos.py
+++ b/catalog/packages/serializers/vnf_pkg_infos.py
@@ -16,5 +16,5 @@ from rest_framework import serializers
from vnf_pkg_info import VnfPkgInfoSerializer
-class VnfPkgInfosSerializer(serializers.Serializer):
+class VnfPkgInfosSerializer(serializers.ListSerializer):
child = VnfPkgInfoSerializer()
diff --git a/catalog/packages/tests/test_vnf_package.py b/catalog/packages/tests/test_vnf_package.py
index cf49b89d..efde444d 100644
--- a/catalog/packages/tests/test_vnf_package.py
+++ b/catalog/packages/tests/test_vnf_package.py
@@ -328,3 +328,103 @@ class TestVnfPackage(TestCase):
}
self.assertEqual(response.data, expect_data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ def test_query_multiple_vnf(self):
+ VnfPackageModel.objects.create(
+ vnfPackageId="111",
+ vnfdId="zte-hss-1.0",
+ vnfVendor="zte",
+ vnfdProductName="hss",
+ vnfSoftwareVersion="1.0.0",
+ vnfdVersion="1.0.0",
+ checksum='{"algorithm":"111", "hash": "11"}',
+ onboardingState="CREATED",
+ operationalState="DISABLED",
+ usageState="NOT_IN_USE",
+ userDefinedData='{"a": "A"}'
+ )
+ VnfPackageModel.objects.create(
+ vnfPackageId="222",
+ vnfdId="zte-hss-1.0",
+ vnfVendor="zte",
+ vnfdProductName="hss",
+ vnfSoftwareVersion="1.0.0",
+ vnfdVersion="1.0.0",
+ checksum='{"algorithm":"111", "hash": "11"}',
+ onboardingState="CREATED",
+ operationalState="DISABLED",
+ usageState="NOT_IN_USE",
+ userDefinedData='{"a": "A"}'
+ )
+ response = self.client.get("/api/vnfpkgm/v1/vnf_packages")
+ expect_data = [
+ {
+ "id": "111",
+ "vnfdId": "zte-hss-1.0",
+ "vnfProductName": "hss",
+ "vnfSoftwareVersion": "1.0.0",
+ "vnfdVersion": "1.0.0",
+ "checksum": {"algorithm": "111", "hash": "11"},
+ "softwareImages": None,
+ "additionalArtifacts": None,
+ "onboardingState": "CREATED",
+ "operationalState": "DISABLED",
+ "usageState": "NOT_IN_USE",
+ "userDefinedData": {"a": "A"},
+ "_links": None
+ },
+ {
+ "id": "222",
+ "vnfdId": "zte-hss-1.0",
+ "vnfProductName": "hss",
+ "vnfSoftwareVersion": "1.0.0",
+ "vnfdVersion": "1.0.0",
+ "checksum": {"algorithm": "111", "hash": "11"},
+ "softwareImages": None,
+ "additionalArtifacts": None,
+ "onboardingState": "CREATED",
+ "operationalState": "DISABLED",
+ "usageState": "NOT_IN_USE",
+ "userDefinedData": {"a": "A"},
+ "_links": None
+ }
+ ]
+ self.assertEqual(response.data, expect_data)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ def test_delete_single_vnf_pkg(self):
+ VnfPackageModel.objects.create(
+ vnfPackageId="222",
+ vnfdId="zte-hss-1.0",
+ vnfVendor="zte",
+ vnfdProductName="hss",
+ vnfSoftwareVersion="1.0.0",
+ vnfdVersion="1.0.0",
+ checksum='{"algorithm":"111", "hash": "11"}',
+ onboardingState="CREATED",
+ operationalState="DISABLED",
+ usageState="NOT_IN_USE",
+ userDefinedData='{"a": "A"}'
+ )
+ response = self.client.delete("/api/vnfpkgm/v1/vnf_packages/222")
+ self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
+ self.assertEqual(response.data, None)
+
+ def test_fetch_vnf_pkg(self):
+ pass
+
+ def test_fetch_partical_vnf_pkg(self):
+ with open("vnfPackage.csar", "wb") as fp:
+ fp.writelines("AAAABBBBCCCCDDDD")
+ VnfPackageModel.objects.create(
+ vnfPackageId="222",
+ onboardingState="ONBOARDED",
+ localFilePath="vnfPackage.csar"
+ )
+ response = self.client.get("/api/vnfpkgm/v1/vnf_packages/222/package_content", RANGE="4-7")
+ partial_file_content = ''
+ for data in response.streaming_content:
+ partial_file_content = partial_file_content + data
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual('BBBB', partial_file_content)
+ os.remove("vnfPackage.csar")
diff --git a/catalog/packages/views/vnf_package_views.py b/catalog/packages/views/vnf_package_views.py
index 7defc347..2bdd3eb8 100644
--- a/catalog/packages/views/vnf_package_views.py
+++ b/catalog/packages/views/vnf_package_views.py
@@ -27,7 +27,7 @@ from catalog.packages.serializers.create_vnf_pkg_info_req import CreateVnfPkgInf
from catalog.packages.serializers.vnf_pkg_info import VnfPkgInfoSerializer
from catalog.packages.serializers.vnf_pkg_infos import VnfPkgInfosSerializer
from catalog.packages.biz.vnf_package import create_vnf_pkg, query_multiple, VnfPkgUploadThread, \
- query_single, delete_vnf_pkg, parse_vnfd_and_save
+ query_single, delete_vnf_pkg, parse_vnfd_and_save, fetch_vnf_pkg
from catalog.pub.database.models import VnfPackageModel
logger = logging.getLogger(__name__)
@@ -98,32 +98,56 @@ def vnf_packages_rc(request):
status.HTTP_500_INTERNAL_SERVER_ERROR: "Internal error"
}
)
-@api_view(http_method_names=['PUT'])
+@swagger_auto_schema(
+ method="GET",
+ operation_description="Fetch VNF package content",
+ request_body=no_body,
+ responses={
+ status.HTTP_200_OK: VnfPkgInfosSerializer(),
+ status.HTTP_500_INTERNAL_SERVER_ERROR: "Internal error"
+ }
+)
+@api_view(http_method_names=["PUT", "GET"])
def upload_vnf_pkg_content(request, vnfPkgId):
- logger.debug("Upload VNF package %s" % vnfPkgId)
- try:
- vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnfPkgId)
- if vnf_pkg[0].onboardingState != "CREATED":
- raise CatalogException("VNF package (%s) is not created" % vnfPkgId)
- file_object = request.FILES.get('file')
- upload_path = os.path.join(CATALOG_ROOT_PATH, vnfPkgId)
- if not os.path.exists(upload_path):
- os.makedirs(upload_path, 0o777)
-
- upload_file_name = os.path.join(upload_path, file_object.name)
- with open(upload_file_name, 'wb+') as dest_file:
- for chunk in file_object.chunks():
- dest_file.write(chunk)
-
- parse_vnfd_and_save(vnfPkgId, upload_file_name)
- return Response(None, status=status.HTTP_202_ACCEPTED)
- except CatalogException:
+ if request.method == "PUT":
+ logger.debug("Upload VNF package %s" % vnfPkgId)
+ try:
+ vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnfPkgId)
+ if vnf_pkg[0].onboardingState != "CREATED":
+ raise CatalogException("VNF package (%s) is not created" % vnfPkgId)
+ file_object = request.FILES.get('file')
+ upload_path = os.path.join(CATALOG_ROOT_PATH, vnfPkgId)
+ if not os.path.exists(upload_path):
+ os.makedirs(upload_path, 0o777)
+
+ upload_file_name = os.path.join(upload_path, file_object.name)
+ with open(upload_file_name, 'wb+') as dest_file:
+ for chunk in file_object.chunks():
+ dest_file.write(chunk)
+
+ parse_vnfd_and_save(vnfPkgId, upload_file_name)
+ return Response(None, status=status.HTTP_202_ACCEPTED)
+ except CatalogException:
+ logger.error(traceback.format_exc())
+ return Response(data={'error': 'Upload VNF package failed.'},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ except Exception as e:
+ logger.error(e.message)
logger.error(traceback.format_exc())
- return Response(data={'error': 'Upload VNF package failed.'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
- except Exception as e:
- logger.error(e.message)
- logger.error(traceback.format_exc())
- return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ if request.method == "GET":
+ try:
+ response = fetch_vnf_pkg(request, vnfPkgId)
+ return response
+ except CatalogException:
+ logger.error(traceback.format_exc())
+ return Response(data={'error': 'Fetch VNF package failed.'},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ except Exception as e:
+ logger.error(e.message)
+ logger.error(traceback.format_exc())
+ return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@swagger_auto_schema(
diff --git a/catalog/pub/utils/tests.py b/catalog/pub/utils/tests.py
index 0fe8310d..73029fa6 100644
--- a/catalog/pub/utils/tests.py
+++ b/catalog/pub/utils/tests.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import platform
import unittest
import mock
import fileutil
@@ -51,7 +52,10 @@ class UtilsTest(unittest.TestCase):
fileutil.delete_dirs("abc")
is_ok, f_name = fileutil.download_file_from_http("1", "abc", "1.txt")
self.assertTrue(is_ok)
- self.assertTrue(f_name.endswith("abc/1.txt"))
+ if 'Windows' in platform.system():
+ self.assertTrue(f_name.endswith("abc\\1.txt"))
+ else:
+ self.assertTrue(f_name.endswith("abc/1.txt"))
fileutil.delete_dirs("abc")
def test_query_job_status(self):
diff --git a/docker/build_image.sh b/docker/build_image.sh
index b42369f1..57fa076f 100755
--- a/docker/build_image.sh
+++ b/docker/build_image.sh
@@ -6,7 +6,7 @@ cd ${DOCKER_BUILD_DIR}
BUILD_ARGS="--no-cache"
ORG="onap"
-VERSION="1.1.0"
+VERSION="1.2.0"
PROJECT="vfc"
IMAGE="catalog"
DOCKER_REPOSITORY="nexus3.onap.org:10003"
diff --git a/pom.xml b/pom.xml
index 54b03c6b..98a69e59 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,12 +18,12 @@
<parent>
<groupId>org.onap.oparent</groupId>
<artifactId>oparent</artifactId>
- <version>1.1.0</version>
+ <version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.vfc.nfvo.catalog</groupId>
<artifactId>vfc-nfvo-catalog</artifactId>
- <version>1.1.0-SNAPSHOT</version>
+ <version>1.2.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>vfc-nfvo-catalog</name>
<description>vfc nfvo catalog</description>
diff --git a/version.properties b/version.properties
index e1751011..ad491ae4 100644
--- a/version.properties
+++ b/version.properties
@@ -17,7 +17,7 @@
# because they are used in Jenkins, whose plug-in doesn't support
major=1
-minor=1
+minor=2
patch=0
base_version=${major}.${minor}.${patch}