fix but for ETSI Catalog Manager needs to trigger a notification after storing ETSI...
[modeling/etsicatalog.git] / catalog / packages / tests / test_vnfpackage.py
1 # Copyright 2017 ZTE Corporation.
2 #
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
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 import json
16 import mock
17 import os
18 import catalog.pub.utils.timeutil
19 from requests.auth import HTTPBasicAuth
20
21 from django.test import TestCase
22 from rest_framework import status
23 from rest_framework.test import APIClient
24
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
34
35
36 class TestNfPackage(TestCase):
37     def setUp(self):
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
43
44     def tearDown(self):
45         pass
46
47     def assert_job_result(self, job_id, job_progress, job_detail):
48         jobs = JobStatusModel.objects.filter(
49             jobid=job_id,
50             progress=job_progress,
51             descp=job_detail)
52         self.assertEqual(1, len(jobs))
53
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",
58             {
59                 "csarId": "1",
60                 "vimIds": ["1"]
61             },
62             format='json'
63         )
64         self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED)
65
66     def test_nf_pkg_distribute_when_csar_already_exist(self):
67         VnfPackageModel(
68             vnfPackageId="1",
69             vnfdId="vcpe_vfw_zte_1_0"
70         ).save()
71         NfDistributeThread(
72             csar_id="1",
73             vim_ids=["1"],
74             lab_vim_id="",
75             job_id="2"
76         ).run()
77         self.assert_job_result("2", 255, "NF CSAR(1) already exists.")
78
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,
83                                                        mock_parse_vnfd,
84                                                        mock_download_artifacts,
85                                                        mock_call_req):
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([{
89             "uuid": "1",
90             "toscaModelURL": "https://127.0.0.1:1234/sdc/v1/hss.csar"
91         }]), '200']
92         VnfPackageModel(vnfPackageId="2", vnfdId="00342b18-a5c7-11e8-998c-bf1755941f12").save()
93         NfDistributeThread(
94             csar_id="1",
95             vim_ids=["1"],
96             lab_vim_id="",
97             job_id="2"
98         ).run()
99         self.assert_job_result("2", 255, "VNF package(00342b18-a5c7-11e8-998c-bf1755941f12) already exists.")
100
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,
105                                             mock_parse_vnfd,
106                                             mock_download_artifacts,
107                                             mock_call_req):
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([{
111             "uuid": "1",
112             "toscaModelURL": "https://127.0.0.1:1234/sdc/v1/hss.csar"
113         }]), '200']
114         NfDistributeThread(
115             csar_id="1",
116             vim_ids=["1"],
117             lab_vim_id="",
118             job_id="4"
119         ).run()
120         self.assert_job_result("4", 100, "CSAR(1) distribute successfully.")
121
122     ###############################################################################################################
123
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)
128
129     def test_nf_pkg_normal_delete(self):
130         VnfPackageModel(
131             vnfPackageId="2",
132             vnfdId="vcpe_vfw_zte_1_0"
133         ).save()
134         NfPkgDeleteThread(
135             csar_id="2",
136             job_id="2"
137         ).run()
138         self.assert_job_result("2", 100, "Delete CSAR(2) successfully.")
139
140     def test_nf_pkg_get_all(self):
141         VnfPackageModel(
142             vnfPackageId="3",
143             vnfdId="3",
144             vnfVendor='3',
145             vnfdVersion='3',
146             vnfSoftwareVersion='',
147             vnfPackageUri='',
148             vnfdModel=''
149         ).save()
150         VnfPackageModel(
151             vnfPackageId="4",
152             vnfdId="4",
153             vnfVendor='4',
154             vnfdVersion='4',
155             vnfSoftwareVersion='',
156             vnfPackageUri='',
157             vnfdModel=''
158         ).save()
159         resp = self.client.get("/api/catalog/v1/vnfpackages")
160         self.assertEqual(resp.status_code, status.HTTP_200_OK)
161         expect_data = [
162             {
163                 "imageInfo": [],
164                 "csarId": "3",
165                 "packageInfo": {
166                     "csarName": "",
167                     "vnfdModel": "",
168                     "vnfdProvider": "3",
169                     "vnfdId": "3",
170                     "downloadUrl": "http://127.0.0.1:8806/static/catalog/3/",
171                     "vnfVersion": "",
172                     "vnfdVersion": "3",
173                     "vnfPackageId": "3"
174                 }
175             },
176             {
177                 "imageInfo": [],
178                 "csarId": "4",
179                 "packageInfo": {
180                     "csarName": "",
181                     "vnfdModel": "",
182                     "vnfdProvider": "4",
183                     "vnfdId": "4",
184                     "downloadUrl": "http://127.0.0.1:8806/static/catalog/4/",
185                     "vnfVersion": "",
186                     "vnfdVersion": "4",
187                     "vnfPackageId": "4"
188                 }
189             }
190         ]
191         self.assertEqual(expect_data, resp.data)
192
193     def test_nf_pkg_get_one(self):
194         VnfPackageModel(
195             vnfPackageId="4",
196             vnfdId="4",
197             vnfVendor='4',
198             vnfdVersion='4',
199             vnfSoftwareVersion='',
200             vnfPackageUri='',
201             vnfdModel=''
202         ).save()
203
204         resp = self.client.get("/api/catalog/v1/vnfpackages/4")
205         self.assertEqual(resp.status_code, status.HTTP_200_OK)
206         expect_data = {
207             "imageInfo": [],
208             "csarId": "4",
209             "packageInfo": {
210                 "csarName": "",
211                 "vnfdModel": "",
212                 "vnfdProvider": "4",
213                 "vnfdId": "4",
214                 "downloadUrl": "http://127.0.0.1:8806/static/catalog/4/",
215                 "vnfVersion": "",
216                 "vnfdVersion": "4",
217                 "vnfPackageId": "4"
218             }
219         }
220         self.assertEqual(expect_data, resp.data)
221
222     def test_nf_pkg_get_one_failed(self):
223         VnfPackageModel(
224             vnfPackageId="4",
225             vnfdId="4",
226             vnfVendor='4',
227             vnfdVersion='4',
228             vnfSoftwareVersion='',
229             vnfPackageUri='',
230             vnfdModel=''
231         ).save()
232
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)
236
237     ###############################################################################################################
238
239     @mock.patch.object(toscaparser, 'parse_vnfd')
240     def test_vnfd_parse_normal(self, mock_parse_vnfd):
241         VnfPackageModel(
242             vnfPackageId="8",
243             vnfdId="10"
244         ).save()
245         mock_parse_vnfd.return_value = json.JSONEncoder().encode({"c": "d"})
246         req_data = {
247             "csarId": "8",
248             "inputs": []
249         }
250         resp = self.client.post(
251             "/api/parser/v1/parservnfd",
252             req_data,
253             format='json'
254         )
255         self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED)
256         self.assertEqual({"model": '{"c": "d"}'}, resp.data)
257
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",
262             req_data,
263             format='json'
264         )
265         self.assertEqual(resp.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
266         self.assertEqual(resp.data, {"error": "VNF CSAR(1) does not exist."})
267
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"
278         uuid_csarid = "1234"
279         mock_uuid.side_effect = [uuid_subscriptid, "1111", "2222"]
280         mock_requests_get.return_value.status_code = 204
281         vnf_subscription_data = {
282             "filter": {
283                 "notificationTypes": [
284                     "VnfPackageOnboardingNotification",
285                     "VnfPackageChangeNotification"
286                 ],
287                 "vnfdId": [
288                     "b1bb0ce7-2222-4fa7-95ed-4840d70a1177"
289                 ],
290                 "operationalState": ["ENABLED", "DISABLED"]
291             },
292             "callbackUri": "https://so-vnfm-simulator.onap:9093/vnfpkgm/v1/notification",
293             "authentication": {
294                 "authType": [
295                     "BASIC"
296                 ],
297                 "paramsBasic": {
298                     "userName": "vnfm",
299                     "password": "password1$"
300                 }
301             }
302         }
303         response = self.client.post(
304             "/api/vnfpkgm/v1/subscriptions",
305             data=vnf_subscription_data,
306             format='json')
307         self.assertEqual(201, response.status_code)
308         mock_download_artifacts.return_value = os.path.join(CATALOG_ROOT_PATH, "Sol004VnfCSAR.csar")
309         mock_get_artifact.return_value = {
310             "uuid": "c94490a0-f7ef-48be-b3f8-8d8662a37236",
311             "invariantUUID": "63eaec39-ffbe-411c-a838-448f2c73f7eb",
312             "name": "Sol004VnfCSAR",
313             "version": "2.0",
314             "toscaModelURL": "/sdc/v1/catalog/resources/c94490a0-f7ef-48be-b3f8-8d8662a37236/toscaModel",
315             "category": "Volte",
316             "subCategory": "VolteVF",
317             "resourceType": "VF",
318             "lifecycleState": "CERTIFIED",
319             "lastUpdaterUserId": "jh0003"
320         }
321         NfDistributeThread(csar_id=uuid_csarid, vim_ids=["1"], lab_vim_id="", job_id="4").on_distribute()
322         print(VnfPackageModel.objects.all().values())
323         expect_onboarding_notification = {
324             'id': "1111",
325             'notificationType': const.PKG_NOTIFICATION_TYPE.ONBOARDING,
326             'timeStamp': "2019-02-16 14:41:16",
327             'vnfPkgId': "1234",
328             'vnfdId': "b1bb0ce7-2222-4fa7-95ed-4840d70a1177",
329             '_links': {
330                 'vnfPackage': {
331                     'href': 'http://%s:%s/%s/vnf_packages/%s' % (pub_config.MSB_SERVICE_IP,
332                                                                  pub_config.MSB_SERVICE_PORT,
333                                                                  const.PKG_URL_PREFIX,
334                                                                  uuid_csarid)},
335                     'subscription': {
336                         'href': 'http://%s:%s/%s%s' % (pub_config.MSB_SERVICE_IP,
337                                                        pub_config.MSB_SERVICE_PORT,
338                                                        const.VNFPKG_SUBSCRIPTION_ROOT_URI,
339                                                        uuid_subscriptid)}
340
341             },
342             "subscriptionId": uuid_subscriptid
343         }
344         mock_requests_post.return_value.status_code = 204
345         mock_requests_post.assert_called_with(vnf_subscription_data["callbackUri"], data=expect_onboarding_notification,
346                                               headers={'Connection': 'close',
347                                                        'content-type': 'application/json',
348                                                        'accept': 'application/json'},
349                                               auth=HTTPBasicAuth("vnfm", "password1$"),
350                                               verify=False)
351         mock_requests_post.return_value.status_code = 204
352         expect_deleted_notification = {
353             'id': "2222",
354             'notificationType': const.PKG_NOTIFICATION_TYPE.CHANGE,
355             'timeStamp': "2019-02-16 14:41:16",
356             'vnfPkgId': "1234",
357             'vnfdId': "b1bb0ce7-2222-4fa7-95ed-4840d70a1177",
358             'changeType': const.PKG_CHANGE_TYPE.PKG_DELETE,
359             'operationalState': None,
360             "subscriptionId": uuid_subscriptid,
361             '_links': {
362                 'subscription': {
363                     'href': 'http://%s:%s/%s%s' % (pub_config.MSB_SERVICE_IP,
364                                                    pub_config.MSB_SERVICE_PORT,
365                                                    const.VNFPKG_SUBSCRIPTION_ROOT_URI,
366                                                    uuid_subscriptid)},
367                 'vnfPackage': {
368                     'href': 'http://%s:%s/%s/vnf_packages/%s' % (pub_config.MSB_SERVICE_IP,
369                                                                  pub_config.MSB_SERVICE_PORT,
370                                                                  const.PKG_URL_PREFIX,
371                                                                  uuid_csarid)
372                 }
373             }
374         }
375         NfPkgDeleteThread(csar_id=uuid_csarid, job_id="5").delete_csar()
376         mock_requests_post.assert_called_with(vnf_subscription_data["callbackUri"], data=expect_deleted_notification,
377                                               headers={'Connection': 'close',
378                                                        'content-type': 'application/json',
379                                                        'accept': 'application/json'},
380                                               auth=HTTPBasicAuth("vnfm", "password1$"),
381                                               verify=False)