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
36 class TestGetVnfViews(TestCase):
38 self.client = Client()
39 self.nf_inst_id = str(uuid.uuid4())
40 NfInstModel(nfinstid=self.nf_inst_id, nf_name='vnf1', vnfm_inst_id='1', vnf_id='vnf_id1',
41 status=VNF_STATUS.ACTIVE, create_time=now_time(), lastuptime=now_time()).save()
44 NfInstModel.objects.all().delete()
46 def test_get_vnf(self):
47 response = self.client.get("/api/nslcm/v1/ns/vnfs/%s" % self.nf_inst_id)
48 self.failUnlessEqual(status.HTTP_200_OK, response.status_code)
49 context = json.loads(response.content)
50 self.failUnlessEqual(self.nf_inst_id, context['vnfInstId'])
53 class TestCreateVnfViews(TestCase):
55 self.ns_inst_id = str(uuid.uuid4())
56 self.job_id = str(uuid.uuid4())
58 'nsInstanceId': self.ns_inst_id,
59 'additionalParamForNs': {"inputs": json.dumps({})},
60 'additionalParamForVnf': [{
61 'vnfprofileid': 'VBras',
63 'inputs': json.dumps({'vnf_param1': '11', 'vnf_param2': '22'}),
64 'vnfminstanceid': "1"}}],
66 self.client = Client()
67 NfPackageModel(uuid=str(uuid.uuid4()), nfpackageid='package_id1', vnfdid='zte_vbras', vendor='zte',
68 vnfdversion='1.0.0', vnfversion='1.0.0', vnfdmodel=json.dumps(vnfd_model_dict)).save()
69 NSInstModel(id=self.ns_inst_id, name='ns', nspackage_id='1', nsd_id='nsd_id', description='description',
70 status='instantiating', nsd_model=json.dumps(nsd_model_dict), create_time=now_time(),
71 lastuptime=now_time()).save()
74 NfInstModel.objects.all().delete()
75 JobModel.objects.all().delete()
77 @mock.patch.object(CreateVnfs, 'run')
78 def test_create_vnf(self, mock_run):
79 response = self.client.post("/api/nslcm/v1/ns/vnfs", data=self.data)
80 self.failUnlessEqual(status.HTTP_202_ACCEPTED, response.status_code)
81 context = json.loads(response.content)
82 self.assertTrue(NfInstModel.objects.filter(nfinstid=context['vnfInstId']).exists())
84 @mock.patch.object(restcall, 'call_req')
85 def test_create_vnf_thread(self, mock_call_req):
87 "/api/ztevmanagerdriver/v1/1/vnfs":
88 [0, json.JSONEncoder().encode({"jobId": self.job_id, "vnfInstanceId": 3}), '200'],
89 "/api/aai-esr-server/v1/vnfms/1":
90 [0, json.JSONEncoder().encode({"name": 'vnfm1'}), '200'],
92 [0, json.JSONEncoder().encode({}), '200'],
93 "/api/resmgr/v1/vnfinfo":
94 [0, json.JSONEncoder().encode({}), '200'],
95 "/api/ztevmanagerdriver/v1/jobs/" + self.job_id + "&responseId=0":
96 [0, json.JSONEncoder().encode({"jobid": self.job_id,
97 "responsedescriptor": {"progress": "100",
98 "status": JOB_MODEL_STATUS.FINISHED,
100 "statusdescription": "creating",
102 "responsehistorylist": [
104 "status": JOB_MODEL_STATUS.PROCESSING,
106 "statusdescription": "creating",
107 "errorcode": "0"}]}}), '200']}
109 def side_effect(*args):
110 return mock_vals[args[4]]
111 mock_call_req.side_effect = side_effect
112 data = {'ns_instance_id': ignore_case_get(self.data, 'nsInstanceId'),
113 'additional_param_for_ns': ignore_case_get(self.data, 'additionalParamForNs'),
114 'additional_param_for_vnf': ignore_case_get(self.data, 'additionalParamForVnf'),
115 'vnf_index': ignore_case_get(self.data, 'vnfIndex')}
116 nf_inst_id, job_id = create_vnfs.prepare_create_params()
117 CreateVnfs(data, nf_inst_id, job_id).run()
118 self.assertTrue(NfInstModel.objects.get(nfinstid=nf_inst_id).status, VNF_STATUS.ACTIVE)
121 class TestTerminateVnfViews(TestCase):
123 self.client = Client()
124 self.ns_inst_id = str(uuid.uuid4())
125 self.nf_inst_id = '1'
126 self.vnffg_id = str(uuid.uuid4())
127 self.vim_id = str(uuid.uuid4())
128 self.job_id = str(uuid.uuid4())
130 self.tenant = "tenantname"
131 NSInstModel.objects.all().delete()
132 NfInstModel.objects.all().delete()
133 NSInstModel(id=self.ns_inst_id, name="ns_name").save()
134 NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1',
135 vnfm_inst_id='1', ns_inst_id='111,2-2-2',
136 max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10,
137 status='active', mnfinstid=self.nf_uuid, package_id='pkg1',
138 vnfd_model='{"metadata": {"vnfdId": "1","vnfdName": "PGW001",'
139 '"vnfProvider": "zte","vnfdVersion": "V00001","vnfVersion": "V5.10.20",'
140 '"productType": "CN","vnfType": "PGW",'
141 '"description": "PGW VNFD description",'
142 '"isShared":true,"vnfExtendType":"driver"}}')
145 NSInstModel.objects.all().delete()
146 NfInstModel.objects.all().delete()
148 @mock.patch.object(TerminateVnfs, 'run')
149 def test_terminate_vnf_url(self, mock_run):
151 "terminationType": "forceful",
152 "gracefulTerminationTimeout": "600"}
154 response = self.client.post("/api/nslcm/v1/ns/vnfs/%s" % self.nf_inst_id, data=req_data)
155 self.failUnlessEqual(status.HTTP_201_CREATED, response.status_code)
157 @mock.patch.object(restcall, "call_req")
158 def test_terminate_vnf(self, mock_call_req):
159 job_id = JobUtil.create_job("VNF", JOB_TYPE.TERMINATE_VNF, self.nf_inst_id)
161 nfinst = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
163 self.failUnlessEqual(1, 1)
165 self.failUnlessEqual(1, 0)
168 "/api/ztevmanagerdriver/v1/1/vnfs/111/terminate":
169 [0, json.JSONEncoder().encode({"jobId": job_id}), '200'],
170 "/api/aai-esr-server/v1/vnfms/1":
171 [0, json.JSONEncoder().encode({"name": 'vnfm1', "type": 'ztevmanagerdriver'}), '200'],
172 "/api/resmgr/v1/vnf/1":
173 [0, json.JSONEncoder().encode({"jobId": job_id}), '200'],
174 "/api/ztevmanagerdriver/v1/1/jobs/" + job_id + "?responseId=0":
175 [0, json.JSONEncoder().encode({"jobId": job_id,
176 "responsedescriptor": {"progress": "100",
177 "status": JOB_MODEL_STATUS.FINISHED,
179 "statusdescription": "creating",
181 "responsehistorylist": [
183 "status": JOB_MODEL_STATUS.PROCESSING,
185 "statusdescription": "creating",
186 "errorcode": "0"}]}}), '200']}
189 "terminationType": "forceful",
190 "gracefulTerminationTimeout": "600"}
192 def side_effect(*args):
193 return mock_vals[args[4]]
194 mock_call_req.side_effect = side_effect
196 TerminateVnfs(req_data, self.nf_inst_id, job_id).run()
197 nfinst = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
199 self.failUnlessEqual(1, 0)
201 self.failUnlessEqual(1, 1)
203 class TestScaleVnfViews(TestCase):
205 self.client = Client()
206 self.ns_inst_id = str(uuid.uuid4())
207 self.nf_inst_id = str(uuid.uuid4())
208 self.vnffg_id = str(uuid.uuid4())
209 self.vim_id = str(uuid.uuid4())
210 self.job_id = str(uuid.uuid4())
212 self.tenant = "tenantname"
213 NSInstModel(id=self.ns_inst_id, name="ns_name").save()
214 NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1',
215 vnfm_inst_id='1', ns_inst_id='111,2-2-2',
216 max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10,
217 status='active', mnfinstid=self.nf_uuid, package_id='pkg1',
218 vnfd_model='{"metadata": {"vnfdId": "1","vnfdName": "PGW001",'
219 '"vnfProvider": "zte","vnfdVersion": "V00001","vnfVersion": "V5.10.20",'
220 '"productType": "CN","vnfType": "PGW",'
221 '"description": "PGW VNFD description",'
222 '"isShared":true,"vnfExtendType":"driver"}}')
225 NSInstModel.objects.all().delete()
226 NfInstModel.objects.all().delete()
228 @mock.patch.object(restcall, "call_req")
229 def test_scale_vnf(self, mock_call_req):
230 job_id = JobUtil.create_job("VNF", JOB_TYPE.TERMINATE_VNF, self.nf_inst_id)
235 "flavour_id":"flavour1",
240 "instances_minimum_number": 1,
241 "instances_maximum_number": 4,
242 "local_affinity_antiaffinity_rule":[
244 "affinity_antiaffinity":"affinity",
253 "name": "demo_aspect",
254 "description": "demo_aspect",
255 "associated_group": "elementGroup1",
263 "group_id": "elementGroup1",
266 "name": "elementGroup1",
268 "members": ["gsu_vm","pfu_vm"],
277 "aspectId":"demo_aspect1",
279 "additionalParam":vnfd_info
283 "aspectId":"demo_aspect2",
285 "additionalParam":vnfd_info
292 "/api/ztevmanagerdriver/v1/1/vnfs/111/terminate":
293 [0, json.JSONEncoder().encode({"jobId": job_id}), '200'],
294 "/api/ztevmanagerdriver/v1/1/vnfs/111/terminate":
295 [0, json.JSONEncoder().encode({"jobId": job_id}), '200']
297 def side_effect(*args):
298 return mock_vals[args[4]]
299 mock_call_req.side_effect = side_effect
301 NFManualScaleService(self.nf_inst_id, req_data).run()
302 nsIns = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
304 self.failUnlessEqual(1, 1)
306 self.failUnlessEqual(1, 0)
309 class TestHealVnfViews(TestCase):
311 self.client = Client()
312 self.ns_inst_id = str(uuid.uuid4())
313 self.nf_inst_id = str(uuid.uuid4())
316 self.job_id = JobUtil.create_job("VNF", JOB_TYPE.HEAL_VNF, self.nf_inst_id)
318 NSInstModel(id=self.ns_inst_id, name="ns_name").save()
319 NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1',
320 vnfm_inst_id='1', ns_inst_id='111,2-2-2',
321 max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10,
322 status='active', mnfinstid=self.nf_uuid, package_id='pkg1',
323 vnfd_model='{"metadata": {"vnfdId": "1","vnfdName": "PGW001",'
324 '"vnfProvider": "zte","vnfdVersion": "V00001","vnfVersion": "V5.10.20",'
325 '"productType": "CN","vnfType": "PGW",'
326 '"description": "PGW VNFD description",'
327 '"isShared":true,"vnfExtendType":"driver"}}')
330 NSInstModel.objects.all().delete()
331 NfInstModel.objects.all().delete()
333 @mock.patch.object(restcall, "call_req")
334 def test_heal_vnf(self, mock_call_req):
338 "/api/ztevmanagerdriver/v1/1/vnfs/111/heal":
339 [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'],
340 "/api/aai-esr-server/v1/vnfms/1":
341 [0, json.JSONEncoder().encode({"name": 'vnfm1', "type": 'ztevmanagerdriver'}), '200'],
342 "/api/resmgr/v1/vnf/1":
343 [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'],
344 "/api/ztevmanagerdriver/v1/1/jobs/" + self.job_id + "?responseId=0":
345 [0, json.JSONEncoder().encode({"jobId": self.job_id,
346 "responsedescriptor": {"progress": "100",
347 "status": JOB_MODEL_STATUS.FINISHED,
349 "statusdescription": "creating",
351 "responsehistorylist": [
353 "status": JOB_MODEL_STATUS.PROCESSING,
355 "statusdescription": "creating",
356 "errorcode": "0"}]}}), '200']}
358 def side_effect(*args):
359 return mock_vals[args[4]]
361 mock_call_req.side_effect = side_effect
372 NFHealService(self.nf_inst_id, req_data).run()
374 self.assertEqual(NfInstModel.objects.get(nfinstid=self.nf_inst_id).status, VNF_STATUS.ACTIVE)
376 @mock.patch.object(NFHealService, "run")
377 def test_heal_vnf_non_existing_vnf(self, mock_biz):
378 mock_biz.side_effect = NSLCMException("VNF Not Found")
391 self.assertRaises(NSLCMException, NFHealService(nf_inst_id, req_data).run)
392 self.assertEqual(len(NfInstModel.objects.filter(nfinstid=nf_inst_id)), 0)
395 'local_storages': [],
398 'volumn_storages': [],
402 'local_storages': [],
403 'vdu_id': u'vdu_omm.001',
404 'image_file': u'opencos_sss_omm_img_release_20150723-1-disk1',
410 'support_scaling': False,
413 'storage_policy': '',
416 'availability_zone': '',
421 'inject_data_list': [],
425 'local_affinity_antiaffinity_rule': {},
426 'template_id': u'omm.001',
427 'manual_scale_select_vim': False},
428 'description': u'singleommvm'},
430 'volumn_storages': [],
434 'local_storages': [],
436 'image_file': u'sss',
442 'support_scaling': False,
445 'storage_policy': '',
448 'availability_zone': '',
453 'inject_data_list': [],
457 'local_affinity_antiaffinity_rule': {},
459 'manual_scale_select_vim': False},
460 'description': u'ompvm'},
462 'volumn_storages': [],
466 'local_storages': [],
468 'image_file': u'sss',
474 'support_scaling': False,
477 'storage_policy': '',
480 'availability_zone': '',
485 'inject_data_list': [],
489 'local_affinity_antiaffinity_rule': {},
491 'manual_scale_select_vim': False},
492 'description': u'ompvm'},
494 'volumn_storages': [],
498 'local_storages': [],
500 'image_file': u'sss',
506 'support_scaling': False,
509 'storage_policy': '',
512 'availability_zone': '',
517 'inject_data_list': [],
521 'local_affinity_antiaffinity_rule': {},
523 'manual_scale_select_vim': False},
524 'description': u'ompvm'},
526 'volumn_storages': [],
530 'local_storages': [],
532 'image_file': u'sss',
538 'support_scaling': False,
541 'storage_policy': '',
544 'availability_zone': '',
549 'inject_data_list': [],
553 'local_affinity_antiaffinity_rule': {},
554 'template_id': u'10',
555 'manual_scale_select_vim': False},
556 'description': u'ppvm'},
558 'volumn_storages': [],
562 'local_storages': [],
564 'image_file': u'sss',
570 'support_scaling': False,
573 'storage_policy': '',
576 'availability_zone': '',
581 'inject_data_list': [],
585 'local_affinity_antiaffinity_rule': {},
586 'template_id': u'11',
587 'manual_scale_select_vim': False},
588 'description': u'ppvm'},
590 'volumn_storages': [],
594 'local_storages': [],
596 'image_file': u'sss',
602 'support_scaling': False,
605 'storage_policy': '',
608 'availability_zone': '',
613 'inject_data_list': [],
617 'local_affinity_antiaffinity_rule': {},
618 'template_id': u'12',
619 'manual_scale_select_vim': False},
620 'description': u'ppvm'}],
621 'volumn_storages': [],
625 'policy_id': u'policy_scale_sss-vnf-template',
627 'policy_file': '*-vnfd.zip/*-vnf-policy.xml'},
633 'name': u'opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
635 'disk_format': u'VMDK',
636 'file_url': u'./zte-cn-sss-main-image/OMM/opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
637 'container_type': 'vm',
639 'hypervisor_type': 'kvm'},
640 'image_file_id': u'opencos_sss_omm_img_release_20150723-1-disk1'},
646 'disk_format': u'VMDK',
647 'file_url': u'./zte-cn-sss-main-image/NE/sss.vmdk',
648 'container_type': 'vm',
650 'hypervisor_type': 'kvm'},
651 'image_file_id': u'sss'}],
658 'domain_type': u'CN',
659 'version': u'v4.14.10',
660 'vmnumber_overquota_alarm': False,
663 'vnfd_version': u'V00000001',
664 'id': u'sss-vnf-template',
665 'name': u'sss-vnf-template'}}
670 "externalDataNetworkName": {
682 "plugin_info": "vbrasplugin_1.0",
684 "is_shared": "False",
685 "request_reclassification": "False",
686 "vnfd_version": "1.0.0",
690 "externalDataNetworkName": {
691 "get_input": "externalDataNetworkName"},
702 "vl_id": "ext_mnet_network",
705 "network_type": "vlan",
706 "name": "externalMNetworkName",
707 "dhcp_enabled": False,
714 "end_ip": "190.168.100.100",
715 "gateway_ip": "190.168.100.1",
716 "start_ip": "190.168.100.2",
717 "cidr": "190.168.100.0/24",
719 "network_name": "sub_mnet",
724 "invariant_id": "vbras_ns",
725 "description": "vbras_ns",