1 # Copyright 2019 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 from mock import MagicMock
19 from django.test import TestCase
20 from rest_framework import status
21 from rest_framework.test import APIClient
22 from lcm.ns.biz.ns_instant import BuildInWorkflowThread
23 from lcm.ns.biz.ns_instant import InstantNSService
24 from lcm.pub.database.models import NSInstModel
25 from lcm.pub.utils import restcall
26 from lcm.pub.config import config
28 nsd_model = json.dumps({
59 "descriptor_id": "zte_ran_du_0001",
60 "descriptor_invariant_id": "1111",
63 "function_description": "RAN DU Function",
90 "basepath": "c:\\users\\10030173\\appdata\\local\\temp\\tmpvg5vto",
95 "key_name": "ran_ext_net",
99 "key_name": "ran_flat_net",
100 "vl_id": "vl_flat_net"
105 "key_name": "ran_ext_net",
106 "vl_id": "vl_ext_net"
109 "key_name": "ran_flat_net",
110 "vl_id": "vl_flat_net"
116 "descriptor_id": "zte_ran_cucp_0001",
117 "flavour_description": "default",
118 "software_version": "1.0.1",
120 "descriptor_version": "1.0",
122 "id": "zte_ran_cucp_0001",
132 "key_name": "ran_ext_net",
133 "vl_id": "vl_ext_net"
136 "key_name": "ran_flat_net",
137 "vl_id": "vl_flat_net"
142 "key_name": "ran_ext_net",
143 "vl_id": "vl_ext_net"
146 "key_name": "ran_flat_net",
147 "vl_id": "vl_flat_net"
153 "descriptor_id": "zte_ran_cuup_0001",
154 "flavour_description": "default",
155 "software_version": "1.0.1",
157 "descriptor_version": "1.0",
159 "id": "zte_ran_cuup_0001",
171 "vl_id": "vl_ext_net",
174 "connectivity_type": {
175 "layer_protocol": "ipv4"
178 "cidr": "10.0.0.0/24",
179 "max_bit_rate_requirements": {
183 "networkName": "ran_ext_net",
184 "min_bit_rate_requirements": {
194 "vl_id": "vl_flat_net",
197 "connectivity_type": {
198 "layer_protocol": "ipv4"
201 "cidr": "10.1.0.0/24",
202 "max_bit_rate_requirements": {
206 "networkName": "ran_flat_net",
207 "min_bit_rate_requirements": {
220 "template_name": "RAN-NS",
221 "template_version": "1.0",
222 "template_author": "ZTE"
225 vnfminfo = {"vnfmId": "1"}
228 class TestInstantiateNsApi(TestCase):
231 self.client = APIClient()
232 NSInstModel.objects.filter().delete()
233 self.url = "/api/nslcm/v1/ns_instances/%s/instantiate"
235 "additionalParamForNs": {
238 "nsFlavourId": 'default',
239 "localizationLanguage": [{
240 "vnfProfileId": "vnfd1",
241 "locationConstraints": {
242 "countryCode": "countryCode",
244 "civicAddressElement": [
252 self.nsd_model = nsd_model
253 self.updated_nsd_model = {
273 self.vnfms = json.dumps({
278 self.vnfm = json.dumps({
282 "certificate-url": "http://127.0.0.0/ztevnfm/v1/auth",
283 "esr-system-info-list": {
284 "esr-system-info": [{
288 "service-url": "http://127.0.0.0/ztevnfm/v1",
289 "user-name": "admin",
290 "password": "admin123"
294 self.nsInstanceId = str(uuid.uuid4())
295 NSInstModel(id=self.nsInstanceId, nspackage_id="7", nsd_id="2", status="active").save()
300 @mock.patch.object(restcall, 'call_req')
301 @mock.patch('lcm.pub.msapi.sdc_run_catalog.parse_nsd', MagicMock(return_value=nsd_model))
302 @mock.patch.object(BuildInWorkflowThread, 'run')
303 def test_ns_instantiate_when_succeed_to_enter_workflow(self, mock_run, mock_call_req):
304 config.WORKFLOW_OPTION = "buildin"
305 mock_call_req.side_effect = [
306 [0, self.nsd_model, '200'],
307 [0, self.vnfms, '200'],
308 [0, self.vnfm, '200']
310 response = self.client.post(self.url % self.nsInstanceId, data=self.req_data, format='json')
311 self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code)
312 self.assertIsNotNone(response['Location'])
313 response = self.client.get(response['Location'], format='json')
314 self.assertEqual(response.status_code, status.HTTP_200_OK)
316 @mock.patch.object(InstantNSService, 'do_biz')
317 def test_ns_instantiate_normal(self, mock_do_biz):
318 mock_do_biz.return_value = {'occ_id': "1"}
319 response = self.client.post(self.url % self.nsInstanceId, data=self.req_data, format='json')
320 self.failUnlessEqual(status.HTTP_202_ACCEPTED, response.status_code)
322 @mock.patch.object(restcall, 'call_req')
323 def test_ns_instantiate_when_fail_to_parse_nsd(self, mock_call_req):
324 mock_call_req.return_value = [1, "Failed to parse nsd", '500']
325 resp = self.client.post(self.url % self.nsInstanceId, data=self.req_data, format='json')
326 self.assertEqual(resp.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
328 @mock.patch('lcm.ns.biz.ns_instantiate_flow.post_deal')
329 @mock.patch.object(restcall, 'call_req')
330 @mock.patch('lcm.ns.biz.ns_instantiate_flow.update_job')
331 @mock.patch('lcm.pub.msapi.sdc_run_catalog.parse_nsd', MagicMock(return_value=nsd))
332 @mock.patch('lcm.pub.msapi.extsys.select_vnfm', MagicMock(return_value=vnfminfo))
333 def test_ns_instantiate_with_pnf(self, mock_updata_job, mock_call_req, mock_post_deal):
334 config.WORKFLOW_OPTION = "grapflow"
335 nsInstanceId = str(uuid.uuid4())
336 NSInstModel(id=nsInstanceId, name="test_ns", nspackage_id="1", status="created").save()
337 ret = [0, json.JSONEncoder().encode({'jobId': "1", "responseDescriptor": {"progress": 100}}), '200']
338 mock_call_req.side_effect = [ret for i in range(1, 20)]
340 "nsFlavourId": 'default',
341 "additionalParamForNs": {
342 "sdnControllerId": "2"
344 "additionalParamsForVnf": [
346 "vnfProfileId": "zte_ran_cucp_0001",
347 "additionalParams": {"vimId": "3"}
350 "vnfProfileId": "zte_ran_cuup_0001",
351 "additionalParams": {"vimId": "3"}
356 "pnfName": "test_pnf",
357 "pnfdId": "zte_ran_du_0001",
361 response = self.client.post(self.url % nsInstanceId, data=data, format='json')
362 self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
363 self.assertIsNotNone(response['Location'])
364 response = self.client.get(response['Location'], format='json')
365 self.assertEqual(response.status_code, status.HTTP_200_OK)
367 def test_method_not_allowed(self):
368 response = self.client.put(self.url % self.nsInstanceId, data=self.req_data, format='json')
369 self.failUnlessEqual(status.HTTP_405_METHOD_NOT_ALLOWED, response.status_code)
370 response = self.client.patch(self.url % self.nsInstanceId, data=self.req_data, format='json')
371 self.failUnlessEqual(status.HTTP_405_METHOD_NOT_ALLOWED, response.status_code)
372 response = self.client.delete(self.url % self.nsInstanceId, data=self.req_data, format='json')
373 self.failUnlessEqual(status.HTTP_405_METHOD_NOT_ALLOWED, response.status_code)
374 response = self.client.get(self.url % self.nsInstanceId, data=self.req_data, format='json')
375 self.failUnlessEqual(status.HTTP_405_METHOD_NOT_ALLOWED, response.status_code)
377 @mock.patch.object(restcall, 'call_req')
378 @mock.patch('lcm.pub.msapi.sdc_run_catalog.parse_nsd', MagicMock(return_value=nsd_model))
379 @mock.patch.object(BuildInWorkflowThread, 'run')
380 def test_ns_instantiate_vcpe(self, mock_run, mock_call_req):
381 config.WORKFLOW_OPTION = "buildin"
382 vcpe_nsd_model = json.dumps({
383 "model": json.dumps({
385 "vnf_id": "b1bb0ce7-2222-4fa7-95ed-4840d70a1101",
395 "vnf_id": "0408f076-e6c0-4c82-9940-272fddbb82de",
405 "vnf_id": "b1bb0ce7-2222-4fa7-95ed-4840d70a1100",
415 "vnf_id": "b1bb0ce7-2222-4fa7-95ed-4840d70a1102",
425 "vnf_id": "3fca3543-07f5-492f-812c-ed462e4f94f4",
441 mock_call_req.side_effect = [
442 [0, vcpe_nsd_model, '200'],
443 [0, self.vnfms, '200'],
444 [0, self.vnfm, '200']
447 "nsFlavourId": 'default',
448 "aditionalParamsForNs": {
451 "multi_stage_design": "false",
452 "availability_zone_max_count": "1",
454 "nsd0_providing_service_invariant_uuid": "12204a12-7da2-4ddf-8c2f-992a1a1acebf",
455 "nsd0_providing_service_uuid": "5791dbeb-19d4-43e8-bf44-5b327ccf6bca"
457 "additionalParamsForVnf": [
459 "vnfProfileId": "b1bb0ce7-2222-4fa7-95ed-4840d70a1101",
460 "additionalParams": {
461 "vimId": "CloudOwner_regionOne"
465 "vnfProfileId": "0408f076-e6c0-4c82-9940-272fddbb82de",
466 "additionalParams": {
467 "vimId": "CloudOwner_regionOne"
471 "vnfProfileId": "b1bb0ce7-2222-4fa7-95ed-4840d70a1100",
472 "additionalParams": {
473 "vimId": "CloudOwner_regionOne"
477 "vnfProfileId": "b1bb0ce7-2222-4fa7-95ed-4840d70a1102",
478 "additionalParams": {
479 "vimId": "CloudOwner_regionOne"
483 "vnfProfileId": "3fca3543-07f5-492f-812c-ed462e4f94f4",
484 "additionalParams": {
485 "vimId": "CloudOwner_regionOne"
490 response = self.client.post(self.url % self.nsInstanceId, data=req_data, format='json')
491 self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code)
492 self.assertIsNotNone(response['Location'])
493 response = self.client.get(response['Location'], format='json')
494 self.assertEqual(response.status_code, status.HTTP_200_OK)