1 # Copyright 2017 ZTE Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
18 import catalog.pub.utils.timeutil
19 from requests.auth import HTTPBasicAuth
21 from django.test import TestCase
22 from rest_framework import status
23 from rest_framework.test import APIClient
25 from catalog.packages.biz.sdc_vnf_package import NfDistributeThread, NfPkgDeleteThread
26 from catalog.pub.database.models import JobStatusModel, JobModel
27 from catalog.pub.database.models import VnfPackageModel
28 from catalog.pub.msapi import sdc
29 from catalog.pub.utils import restcall, toscaparser
30 from .const import vnfd_data
31 from catalog.pub.config.config import CATALOG_ROOT_PATH
32 from catalog.packages import const
33 from catalog.pub.config import config as pub_config
36 class TestNfPackage(TestCase):
38 self.client = APIClient()
39 VnfPackageModel.objects.filter().delete()
40 JobModel.objects.filter().delete()
41 JobStatusModel.objects.filter().delete()
42 self.vnfd_data = vnfd_data
47 def assert_job_result(self, job_id, job_progress, job_detail):
48 jobs = JobStatusModel.objects.filter(
50 progress=job_progress,
52 self.assertEqual(1, len(jobs))
54 @mock.patch.object(NfDistributeThread, 'run')
55 def test_nf_pkg_distribute_normal(self, mock_run):
56 resp = self.client.post(
57 "/api/catalog/v1/vnfpackages",
64 self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED)
66 def test_nf_pkg_distribute_when_csar_already_exist(self):
69 vnfdId="vcpe_vfw_zte_1_0"
77 self.assert_job_result("2", 255, "NF CSAR(1) already exists.")
79 @mock.patch.object(restcall, 'call_req')
80 @mock.patch.object(sdc, 'download_artifacts')
81 @mock.patch.object(toscaparser, 'parse_vnfd')
82 def test_nf_pkg_distribute_when_vnfd_already_exist(self,
84 mock_download_artifacts,
86 mock_parse_vnfd.return_value = json.JSONEncoder().encode(self.vnfd_data)
87 mock_download_artifacts.return_value = "/home/hss.csar"
88 mock_call_req.return_value = [0, json.JSONEncoder().encode([{
90 "toscaModelURL": "https://127.0.0.1:1234/sdc/v1/hss.csar"
92 VnfPackageModel(vnfPackageId="2", vnfdId="00342b18-a5c7-11e8-998c-bf1755941f12").save()
99 self.assert_job_result("2", 255, "VNF package(00342b18-a5c7-11e8-998c-bf1755941f12) already exists.")
101 @mock.patch.object(restcall, 'call_req')
102 @mock.patch.object(sdc, 'download_artifacts')
103 @mock.patch.object(toscaparser, 'parse_vnfd')
104 def test_nf_pkg_distribute_successfully(self,
106 mock_download_artifacts,
108 mock_parse_vnfd.return_value = json.JSONEncoder().encode(self.vnfd_data)
109 mock_download_artifacts.return_value = "/home/hss.csar"
110 mock_call_req.return_value = [0, json.JSONEncoder().encode([{
112 "toscaModelURL": "https://127.0.0.1:1234/sdc/v1/hss.csar"
120 self.assert_job_result("4", 100, "CSAR(1) distribute successfully.")
122 ###############################################################################################################
124 @mock.patch.object(NfPkgDeleteThread, 'run')
125 def test_nf_pkg_delete_normal(self, mock_run):
126 resp = self.client.delete("/api/catalog/v1/vnfpackages/1")
127 self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED)
129 def test_nf_pkg_normal_delete(self):
132 vnfdId="vcpe_vfw_zte_1_0"
138 self.assert_job_result("2", 100, "Delete CSAR(2) successfully.")
140 def test_nf_pkg_get_all(self):
146 vnfSoftwareVersion='',
155 vnfSoftwareVersion='',
159 resp = self.client.get("/api/catalog/v1/vnfpackages")
160 self.assertEqual(resp.status_code, status.HTTP_200_OK)
170 "downloadUrl": "http://127.0.0.1:8806/static/catalog/3/",
184 "downloadUrl": "http://127.0.0.1:8806/static/catalog/4/",
191 self.assertEqual(expect_data, resp.data)
193 def test_nf_pkg_get_one(self):
199 vnfSoftwareVersion='',
204 resp = self.client.get("/api/catalog/v1/vnfpackages/4")
205 self.assertEqual(resp.status_code, status.HTTP_200_OK)
214 "downloadUrl": "http://127.0.0.1:8806/static/catalog/4/",
220 self.assertEqual(expect_data, resp.data)
222 def test_nf_pkg_get_one_failed(self):
228 vnfSoftwareVersion='',
233 resp = self.client.get("/api/catalog/v1/vnfpackages/2")
234 self.assertEqual(resp.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
235 self.assertEqual({'error': 'Vnf package[2] not Found.'}, resp.data)
237 ###############################################################################################################
239 @mock.patch.object(toscaparser, 'parse_vnfd')
240 def test_vnfd_parse_normal(self, mock_parse_vnfd):
245 mock_parse_vnfd.return_value = json.JSONEncoder().encode({"c": "d"})
250 resp = self.client.post(
251 "/api/parser/v1/parservnfd",
255 self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED)
256 self.assertEqual({"model": '{"c": "d"}'}, resp.data)
258 def test_vnfd_parse_when_csar_not_exist(self):
259 req_data = {"csarId": "1", "inputs": []}
260 resp = self.client.post(
261 "/api/parser/v1/parservnfd",
265 self.assertEqual(resp.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
266 self.assertEqual(resp.data, {"error": "VNF CSAR(1) does not exist."})
268 @mock.patch("requests.post")
269 @mock.patch.object(sdc, 'download_artifacts')
270 @mock.patch.object(sdc, 'get_artifact')
271 @mock.patch("requests.get")
272 @mock.patch("uuid.uuid4")
273 @mock.patch.object(catalog.pub.utils.timeutil, "now_time")
274 def test_service_pkg_distribute_and_notify(self, mock_nowtime, mock_uuid, mock_requests_get, mock_get_artifact,
275 mock_download_artifacts, mock_requests_post):
276 mock_nowtime.return_value = "2019-02-16 14:41:16"
277 uuid_subscriptid = "99442b18-a5c7-11e8-998c-bf1755941f13"
279 mock_uuid.side_effect = [uuid_subscriptid, "1111", "2222"]
280 mock_requests_get.return_value.status_code = 204
281 vnf_subscription_data = {
283 "notificationTypes": [
284 "VnfPackageOnboardingNotification",
285 "VnfPackageChangeNotification"
287 "vnfPkgId": [uuid_csarid],
288 "operationalState": ["ENABLED", "DISABLED"]
290 "callbackUri": "https://so-vnfm-simulator.onap:9093/vnfpkgm/v1/notification",
297 "password": "password1$"
301 response = self.client.post(
302 "/api/vnfpkgm/v1/subscriptions",
303 data=vnf_subscription_data,
305 self.assertEqual(201, response.status_code)
306 mock_download_artifacts.return_value = os.path.join(CATALOG_ROOT_PATH, "Sol004VnfCSAR.csar")
307 mock_get_artifact.return_value = {
308 "uuid": "c94490a0-f7ef-48be-b3f8-8d8662a37236",
309 "invariantUUID": "63eaec39-ffbe-411c-a838-448f2c73f7eb",
310 "name": "Sol004VnfCSAR",
312 "toscaModelURL": "/sdc/v1/catalog/resources/c94490a0-f7ef-48be-b3f8-8d8662a37236/toscaModel",
314 "subCategory": "VolteVF",
315 "resourceType": "VF",
316 "lifecycleState": "CERTIFIED",
317 "lastUpdaterUserId": "jh0003"
319 NfDistributeThread(csar_id=uuid_csarid, vim_ids=["1"], lab_vim_id="", job_id="4").on_distribute()
320 print(VnfPackageModel.objects.all().values())
321 expect_onboarding_notification = {
323 'notificationType': const.PKG_NOTIFICATION_TYPE.ONBOARDING,
324 'timeStamp': "2019-02-16 14:41:16",
326 'vnfdId': "b1bb0ce7-2222-4fa7-95ed-4840d70a1177",
329 'href': '%s/%s/vnf_packages/%s' % (pub_config.MSB_BASE_URL, const.PKG_URL_PREFIX, uuid_csarid)},
331 'href': '%s/%s%s' % (pub_config.MSB_BASE_URL, const.VNFPKG_SUBSCRIPTION_ROOT_URI, uuid_subscriptid)}
334 "subscriptionId": uuid_subscriptid
336 mock_requests_post.return_value.status_code = 204
337 mock_requests_post.assert_called_with(vnf_subscription_data["callbackUri"],
338 data=json.dumps(expect_onboarding_notification),
339 headers={'Connection': 'close',
340 'content-type': 'application/json',
341 'accept': 'application/json'},
342 auth=HTTPBasicAuth("vnfm", "password1$"),
344 mock_requests_post.return_value.status_code = 204
345 expect_deleted_notification = {
347 'notificationType': const.PKG_NOTIFICATION_TYPE.CHANGE,
348 'timeStamp': "2019-02-16 14:41:16",
350 'vnfdId': "b1bb0ce7-2222-4fa7-95ed-4840d70a1177",
353 'href': '%s/%s/vnf_packages/%s' % (pub_config.MSB_BASE_URL, const.PKG_URL_PREFIX,
356 'href': '%s/%s%s' % (pub_config.MSB_BASE_URL, const.VNFPKG_SUBSCRIPTION_ROOT_URI,
360 'changeType': const.PKG_CHANGE_TYPE.PKG_DELETE,
361 'operationalState': None,
362 "subscriptionId": uuid_subscriptid
364 NfPkgDeleteThread(csar_id=uuid_csarid, job_id="5").delete_csar()
365 mock_requests_post.assert_called_with(vnf_subscription_data["callbackUri"],
366 data=json.dumps(expect_deleted_notification),
367 headers={'Connection': 'close',
368 'content-type': 'application/json',
369 'accept': 'application/json'},
370 auth=HTTPBasicAuth("vnfm", "password1$"),