1 # Copyright 2016-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 from django.test import TestCase, Client
19 from rest_framework import status
21 from lcm.ns.vnfs import create_vnfs
22 from lcm.ns.vnfs.const import VNF_STATUS
23 from lcm.ns.vnfs.create_vnfs import CreateVnfs
24 from lcm.pub.database.models import NfInstModel, JobModel, NfPackageModel, NSInstModel
25 from lcm.pub.utils import restcall
26 from lcm.pub.utils.jobutil import JOB_MODEL_STATUS
27 from lcm.pub.utils.timeutil import now_time
28 from lcm.pub.utils.values import ignore_case_get
29 from lcm.ns.vnfs.terminate_nfs import TerminateVnfs
30 from lcm.ns.vnfs.scale_vnfs import NFManualScaleService
31 from lcm.ns.vnfs.heal_vnfs import NFHealService
32 from lcm.pub.utils.jobutil import JobUtil, JOB_TYPE
33 from lcm.pub.exceptions import NSLCMException
35 vnfm_info = {"vnfm-id": "example-vnfm-id-val-97336",
36 "vim-id": "example-vim-id-val-35532",
37 "certificate-url": "example-certificate-url-val-18046",
38 "resource-version": "example-resource-version-val-42094",
39 "esr-system-info-list": {
42 "esr-system-info-id": "example-esr-system-info-id-val-7713",
43 "system-name": "example-system-name-val-19801",
44 "type": "example-type-val-24477",
45 "vendor": "example-vendor-val-50079",
46 "version": "example-version-val-93146",
47 "service-url": "example-service-url-val-68090",
48 "user-name": "example-user-name-val-14470",
49 "password": "example-password-val-84190",
50 "system-type": "example-system-type-val-42773",
51 "protocal": "example-protocal-val-85736",
52 "ssl-cacert": "example-ssl-cacert-val-33989",
54 "ip-address": "example-ip-address-val-99038",
55 "port": "example-port-val-27323",
56 "cloud-domain": "example-cloud-domain-val-55163",
57 "default-tenant": "example-default-tenant-val-99383",
58 "resource-version": "example-resource-version-val-15424"
64 class TestGetVnfViews(TestCase):
66 self.client = Client()
67 self.nf_inst_id = str(uuid.uuid4())
68 NfInstModel(nfinstid=self.nf_inst_id, nf_name='vnf1', vnfm_inst_id='1', vnf_id='vnf_id1',
69 status=VNF_STATUS.ACTIVE, create_time=now_time(), lastuptime=now_time()).save()
72 NfInstModel.objects.all().delete()
74 def test_get_vnf(self):
75 response = self.client.get("/api/nslcm/v1/ns/vnfs/%s" % self.nf_inst_id)
76 self.failUnlessEqual(status.HTTP_200_OK, response.status_code)
77 context = json.loads(response.content)
78 self.failUnlessEqual(self.nf_inst_id, context['vnfInstId'])
81 class TestCreateVnfViews(TestCase):
83 self.ns_inst_id = str(uuid.uuid4())
84 self.job_id = str(uuid.uuid4())
86 'nsInstanceId': self.ns_inst_id,
87 'additionalParamForNs': {"inputs": json.dumps({})},
88 'additionalParamForVnf': [{
89 'vnfprofileid': 'VBras',
91 'inputs': json.dumps({'vnf_param1': '11', 'vnf_param2': '22'}),
92 'vnfminstanceid': "1"}}],
94 self.client = Client()
95 NfPackageModel(uuid=str(uuid.uuid4()), nfpackageid='package_id1', vnfdid='zte_vbras', vendor='zte',
96 vnfdversion='1.0.0', vnfversion='1.0.0', vnfdmodel=json.dumps(vnfd_model_dict)).save()
97 NSInstModel(id=self.ns_inst_id, name='ns', nspackage_id='1', nsd_id='nsd_id', description='description',
98 status='instantiating', nsd_model=json.dumps(nsd_model_dict), create_time=now_time(),
99 lastuptime=now_time()).save()
102 NfInstModel.objects.all().delete()
103 JobModel.objects.all().delete()
105 @mock.patch.object(CreateVnfs, 'run')
106 def test_create_vnf(self, mock_run):
107 response = self.client.post("/api/nslcm/v1/ns/vnfs", data=self.data)
108 self.failUnlessEqual(status.HTTP_202_ACCEPTED, response.status_code)
109 context = json.loads(response.content)
110 self.assertTrue(NfInstModel.objects.filter(nfinstid=context['vnfInstId']).exists())
112 @mock.patch.object(restcall, 'call_req')
113 def test_create_vnf_thread(self, mock_call_req):
115 "/api/ztevmanagerdriver/v1/1/vnfs":
116 [0, json.JSONEncoder().encode({"jobId": self.job_id, "vnfInstanceId": 3}), '200'],
117 "/external-system/esr-vnfm-list/esr-vnfm/1":
118 [0, json.JSONEncoder().encode(vnfm_info), '200'],
119 "/api/resmgr/v1/vnf":
120 [0, json.JSONEncoder().encode({}), '200'],
121 "/api/resmgr/v1/vnfinfo":
122 [0, json.JSONEncoder().encode({}), '200'],
123 "/api/ztevmanagerdriver/v1/jobs/" + self.job_id + "&responseId=0":
124 [0, json.JSONEncoder().encode({"jobid": self.job_id,
125 "responsedescriptor": {"progress": "100",
126 "status": JOB_MODEL_STATUS.FINISHED,
128 "statusdescription": "creating",
130 "responsehistorylist": [
132 "status": JOB_MODEL_STATUS.PROCESSING,
134 "statusdescription": "creating",
135 "errorcode": "0"}]}}), '200']}
137 def side_effect(*args):
138 return mock_vals[args[4]]
139 mock_call_req.side_effect = side_effect
140 data = {'ns_instance_id': ignore_case_get(self.data, 'nsInstanceId'),
141 'additional_param_for_ns': ignore_case_get(self.data, 'additionalParamForNs'),
142 'additional_param_for_vnf': ignore_case_get(self.data, 'additionalParamForVnf'),
143 'vnf_index': ignore_case_get(self.data, 'vnfIndex')}
144 nf_inst_id, job_id = create_vnfs.prepare_create_params()
145 CreateVnfs(data, nf_inst_id, job_id).run()
146 self.assertTrue(NfInstModel.objects.get(nfinstid=nf_inst_id).status, VNF_STATUS.ACTIVE)
149 class TestTerminateVnfViews(TestCase):
151 self.client = Client()
152 self.ns_inst_id = str(uuid.uuid4())
153 self.nf_inst_id = '1'
154 self.vnffg_id = str(uuid.uuid4())
155 self.vim_id = str(uuid.uuid4())
156 self.job_id = str(uuid.uuid4())
158 self.tenant = "tenantname"
159 NSInstModel.objects.all().delete()
160 NfInstModel.objects.all().delete()
161 NSInstModel(id=self.ns_inst_id, name="ns_name").save()
162 NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1',
163 vnfm_inst_id='1', ns_inst_id='111,2-2-2',
164 max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10,
165 status='active', mnfinstid=self.nf_uuid, package_id='pkg1',
166 vnfd_model='{"metadata": {"vnfdId": "1","vnfdName": "PGW001",'
167 '"vnfProvider": "zte","vnfdVersion": "V00001","vnfVersion": "V5.10.20",'
168 '"productType": "CN","vnfType": "PGW",'
169 '"description": "PGW VNFD description",'
170 '"isShared":true,"vnfExtendType":"driver"}}')
173 NSInstModel.objects.all().delete()
174 NfInstModel.objects.all().delete()
176 @mock.patch.object(TerminateVnfs, 'run')
177 def test_terminate_vnf_url(self, mock_run):
179 "terminationType": "forceful",
180 "gracefulTerminationTimeout": "600"}
182 response = self.client.post("/api/nslcm/v1/ns/vnfs/%s" % self.nf_inst_id, data=req_data)
183 self.failUnlessEqual(status.HTTP_201_CREATED, response.status_code)
185 # @mock.patch.object(restcall, "call_req")
186 # def test_terminate_vnf(self, mock_call_req):
187 # job_id = JobUtil.create_job("VNF", JOB_TYPE.TERMINATE_VNF, self.nf_inst_id)
189 # nfinst = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
191 # self.failUnlessEqual(1, 1)
193 # self.failUnlessEqual(1, 0)
196 # "/api/ztevmanagerdriver/v1/1/vnfs/111/terminate":
197 # [0, json.JSONEncoder().encode({"jobId": job_id}), '200'],
198 # "/external-system/esr-vnfm-list/esr-vnfm/1":
199 # [0, json.JSONEncoder().encode(vnfm_info), '200'],
200 # "/api/resmgr/v1/vnf/1":
201 # [0, json.JSONEncoder().encode({"jobId": job_id}), '200'],
202 # "/api/ztevmanagerdriver/v1/1/jobs/" + job_id + "?responseId=0":
203 # [0, json.JSONEncoder().encode({"jobId": job_id,
204 # "responsedescriptor": {"progress": "100",
205 # "status": JOB_MODEL_STATUS.FINISHED,
207 # "statusdescription": "creating",
209 # "responsehistorylist": [
211 # "status": JOB_MODEL_STATUS.PROCESSING,
213 # "statusdescription": "creating",
214 # "errorcode": "0"}]}}), '200']}
217 # "terminationType": "forceful",
218 # "gracefulTerminationTimeout": "600"}
220 # def side_effect(*args):
221 # return mock_vals[args[4]]
222 # mock_call_req.side_effect = side_effect
224 # TerminateVnfs(req_data, self.nf_inst_id, job_id).run()
225 # nfinst = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
227 # self.failUnlessEqual(1, 0)
229 # self.failUnlessEqual(1, 1)
231 class TestScaleVnfViews(TestCase):
233 self.client = Client()
234 self.ns_inst_id = str(uuid.uuid4())
235 self.nf_inst_id = str(uuid.uuid4())
236 self.vnffg_id = str(uuid.uuid4())
237 self.vim_id = str(uuid.uuid4())
238 self.job_id = str(uuid.uuid4())
240 self.tenant = "tenantname"
241 NSInstModel(id=self.ns_inst_id, name="ns_name").save()
242 NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1',
243 vnfm_inst_id='1', ns_inst_id='111,2-2-2',
244 max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10,
245 status='active', mnfinstid=self.nf_uuid, package_id='pkg1',
246 vnfd_model='{"metadata": {"vnfdId": "1","vnfdName": "PGW001",'
247 '"vnfProvider": "zte","vnfdVersion": "V00001","vnfVersion": "V5.10.20",'
248 '"productType": "CN","vnfType": "PGW",'
249 '"description": "PGW VNFD description",'
250 '"isShared":true,"vnfExtendType":"driver"}}')
253 NSInstModel.objects.all().delete()
254 NfInstModel.objects.all().delete()
256 @mock.patch.object(restcall, "call_req")
257 def test_scale_vnf(self, mock_call_req):
258 job_id = JobUtil.create_job("VNF", JOB_TYPE.TERMINATE_VNF, self.nf_inst_id)
263 "flavour_id":"flavour1",
268 "instances_minimum_number": 1,
269 "instances_maximum_number": 4,
270 "local_affinity_antiaffinity_rule":[
272 "affinity_antiaffinity":"affinity",
281 "name": "demo_aspect",
282 "description": "demo_aspect",
283 "associated_group": "elementGroup1",
291 "group_id": "elementGroup1",
294 "name": "elementGroup1",
296 "members": ["gsu_vm","pfu_vm"],
305 "aspectId":"demo_aspect1",
307 "additionalParam":vnfd_info
311 "aspectId":"demo_aspect2",
313 "additionalParam":vnfd_info
320 "/api/ztevmanagerdriver/v1/1/vnfs/111/terminate":
321 [0, json.JSONEncoder().encode({"jobId": job_id}), '200'],
322 "/api/ztevmanagerdriver/v1/1/vnfs/111/terminate":
323 [0, json.JSONEncoder().encode({"jobId": job_id}), '200']
325 def side_effect(*args):
326 return mock_vals[args[4]]
327 mock_call_req.side_effect = side_effect
329 NFManualScaleService(self.nf_inst_id, req_data).run()
330 nsIns = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
332 self.failUnlessEqual(1, 1)
334 self.failUnlessEqual(1, 0)
337 class TestHealVnfViews(TestCase):
339 self.client = Client()
340 self.ns_inst_id = str(uuid.uuid4())
341 self.nf_inst_id = str(uuid.uuid4())
344 self.job_id = JobUtil.create_job("VNF", JOB_TYPE.HEAL_VNF, self.nf_inst_id)
346 NSInstModel(id=self.ns_inst_id, name="ns_name").save()
347 NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1',
348 vnfm_inst_id='1', ns_inst_id='111,2-2-2',
349 max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10,
350 status='active', mnfinstid=self.nf_uuid, package_id='pkg1',
351 vnfd_model='{"metadata": {"vnfdId": "1","vnfdName": "PGW001",'
352 '"vnfProvider": "zte","vnfdVersion": "V00001","vnfVersion": "V5.10.20",'
353 '"productType": "CN","vnfType": "PGW",'
354 '"description": "PGW VNFD description",'
355 '"isShared":true,"vnfExtendType":"driver"}}')
358 NSInstModel.objects.all().delete()
359 NfInstModel.objects.all().delete()
361 @mock.patch.object(restcall, "call_req")
362 def test_heal_vnf(self, mock_call_req):
366 "/api/ztevmanagerdriver/v1/1/vnfs/111/heal":
367 [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'],
368 "/external-system/esr-vnfm-list/esr-vnfm/1":
369 [0, json.JSONEncoder().encode(vnfm_info), '200'],
370 "/api/resmgr/v1/vnf/1":
371 [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'],
372 "/api/ztevmanagerdriver/v1/1/jobs/" + self.job_id + "?responseId=0":
373 [0, json.JSONEncoder().encode({"jobId": self.job_id,
374 "responsedescriptor": {"progress": "100",
375 "status": JOB_MODEL_STATUS.FINISHED,
377 "statusdescription": "creating",
379 "responsehistorylist": [
381 "status": JOB_MODEL_STATUS.PROCESSING,
383 "statusdescription": "creating",
384 "errorcode": "0"}]}}), '200']}
386 def side_effect(*args):
387 return mock_vals[args[4]]
389 mock_call_req.side_effect = side_effect
400 NFHealService(self.nf_inst_id, req_data).run()
402 self.assertEqual(NfInstModel.objects.get(nfinstid=self.nf_inst_id).status, VNF_STATUS.ACTIVE)
404 @mock.patch.object(NFHealService, "run")
405 def test_heal_vnf_non_existing_vnf(self, mock_biz):
406 mock_biz.side_effect = NSLCMException("VNF Not Found")
419 self.assertRaises(NSLCMException, NFHealService(nf_inst_id, req_data).run)
420 self.assertEqual(len(NfInstModel.objects.filter(nfinstid=nf_inst_id)), 0)
423 'local_storages': [],
426 'volumn_storages': [],
430 'local_storages': [],
431 'vdu_id': u'vdu_omm.001',
432 'image_file': u'opencos_sss_omm_img_release_20150723-1-disk1',
438 'support_scaling': False,
441 'storage_policy': '',
444 'availability_zone': '',
449 'inject_data_list': [],
453 'local_affinity_antiaffinity_rule': {},
454 'template_id': u'omm.001',
455 'manual_scale_select_vim': False},
456 'description': u'singleommvm'},
458 'volumn_storages': [],
462 'local_storages': [],
464 'image_file': u'sss',
470 'support_scaling': False,
473 'storage_policy': '',
476 'availability_zone': '',
481 'inject_data_list': [],
485 'local_affinity_antiaffinity_rule': {},
487 'manual_scale_select_vim': False},
488 'description': u'ompvm'},
490 'volumn_storages': [],
494 'local_storages': [],
496 'image_file': u'sss',
502 'support_scaling': False,
505 'storage_policy': '',
508 'availability_zone': '',
513 'inject_data_list': [],
517 'local_affinity_antiaffinity_rule': {},
519 'manual_scale_select_vim': False},
520 'description': u'ompvm'},
522 'volumn_storages': [],
526 'local_storages': [],
528 'image_file': u'sss',
534 'support_scaling': False,
537 'storage_policy': '',
540 'availability_zone': '',
545 'inject_data_list': [],
549 'local_affinity_antiaffinity_rule': {},
551 'manual_scale_select_vim': False},
552 'description': u'ompvm'},
554 'volumn_storages': [],
558 'local_storages': [],
560 'image_file': u'sss',
566 'support_scaling': False,
569 'storage_policy': '',
572 'availability_zone': '',
577 'inject_data_list': [],
581 'local_affinity_antiaffinity_rule': {},
582 'template_id': u'10',
583 'manual_scale_select_vim': False},
584 'description': u'ppvm'},
586 'volumn_storages': [],
590 'local_storages': [],
592 'image_file': u'sss',
598 'support_scaling': False,
601 'storage_policy': '',
604 'availability_zone': '',
609 'inject_data_list': [],
613 'local_affinity_antiaffinity_rule': {},
614 'template_id': u'11',
615 'manual_scale_select_vim': False},
616 'description': u'ppvm'},
618 'volumn_storages': [],
622 'local_storages': [],
624 'image_file': u'sss',
630 'support_scaling': False,
633 'storage_policy': '',
636 'availability_zone': '',
641 'inject_data_list': [],
645 'local_affinity_antiaffinity_rule': {},
646 'template_id': u'12',
647 'manual_scale_select_vim': False},
648 'description': u'ppvm'}],
649 'volumn_storages': [],
653 'policy_id': u'policy_scale_sss-vnf-template',
655 'policy_file': '*-vnfd.zip/*-vnf-policy.xml'},
661 'name': u'opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
663 'disk_format': u'VMDK',
664 'file_url': u'./zte-cn-sss-main-image/OMM/opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
665 'container_type': 'vm',
667 'hypervisor_type': 'kvm'},
668 'image_file_id': u'opencos_sss_omm_img_release_20150723-1-disk1'},
674 'disk_format': u'VMDK',
675 'file_url': u'./zte-cn-sss-main-image/NE/sss.vmdk',
676 'container_type': 'vm',
678 'hypervisor_type': 'kvm'},
679 'image_file_id': u'sss'}],
686 'domain_type': u'CN',
687 'version': u'v4.14.10',
688 'vmnumber_overquota_alarm': False,
691 'vnfd_version': u'V00000001',
692 'id': u'sss-vnf-template',
693 'name': u'sss-vnf-template'}}
698 "externalDataNetworkName": {
710 "plugin_info": "vbrasplugin_1.0",
712 "is_shared": "False",
713 "request_reclassification": "False",
714 "vnfd_version": "1.0.0",
718 "externalDataNetworkName": {
719 "get_input": "externalDataNetworkName"},
730 "vl_id": "ext_mnet_network",
733 "network_type": "vlan",
734 "name": "externalMNetworkName",
735 "dhcp_enabled": False,
742 "end_ip": "190.168.100.100",
743 "gateway_ip": "190.168.100.1",
744 "start_ip": "190.168.100.2",
745 "cidr": "190.168.100.0/24",
747 "network_name": "sub_mnet",
752 "invariant_id": "vbras_ns",
753 "description": "vbras_ns",