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/extsys/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/extsys/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 NFManualScaleService(self.nf_inst_id, req_data).run()
298 nsIns = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
300 self.failUnlessEqual(1, 1)
302 self.failUnlessEqual(1, 0)
305 class TestHealVnfViews(TestCase):
307 self.client = Client()
308 self.ns_inst_id = str(uuid.uuid4())
309 self.nf_inst_id = str(uuid.uuid4())
312 self.job_id = JobUtil.create_job("VNF", JOB_TYPE.HEAL_VNF, self.nf_inst_id)
314 NSInstModel(id=self.ns_inst_id, name="ns_name").save()
315 NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1',
316 vnfm_inst_id='1', ns_inst_id='111,2-2-2',
317 max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10,
318 status='active', mnfinstid=self.nf_uuid, package_id='pkg1',
319 vnfd_model='{"metadata": {"vnfdId": "1","vnfdName": "PGW001",'
320 '"vnfProvider": "zte","vnfdVersion": "V00001","vnfVersion": "V5.10.20",'
321 '"productType": "CN","vnfType": "PGW",'
322 '"description": "PGW VNFD description",'
323 '"isShared":true,"vnfExtendType":"driver"}}')
326 NSInstModel.objects.all().delete()
327 NfInstModel.objects.all().delete()
329 @mock.patch.object(restcall, "call_req")
330 def test_heal_vnf(self, mock_call_req):
334 "/api/ztevmanagerdriver/v1/1/vnfs/111/heal":
335 [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'],
336 "/api/extsys/v1/vnfms/1":
337 [0, json.JSONEncoder().encode({"name": 'vnfm1', "type": 'ztevmanagerdriver'}), '200'],
338 "/api/resmgr/v1/vnf/1":
339 [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'],
340 "/api/ztevmanagerdriver/v1/1/jobs/" + self.job_id + "?responseId=0":
341 [0, json.JSONEncoder().encode({"jobId": self.job_id,
342 "responsedescriptor": {"progress": "100",
343 "status": JOB_MODEL_STATUS.FINISHED,
345 "statusdescription": "creating",
347 "responsehistorylist": [
349 "status": JOB_MODEL_STATUS.PROCESSING,
351 "statusdescription": "creating",
352 "errorcode": "0"}]}}), '200']}
354 def side_effect(*args):
355 return mock_vals[args[4]]
357 mock_call_req.side_effect = side_effect
368 NFHealService(self.nf_inst_id, req_data).run()
370 self.assertEqual(NfInstModel.objects.get(nfinstid=self.nf_inst_id).status, VNF_STATUS.ACTIVE)
372 @mock.patch.object(NFHealService, "run")
373 def test_heal_vnf_non_existing_vnf(self, mock_biz):
374 mock_biz.side_effect = NSLCMException("VNF Not Found")
387 self.assertRaises(NSLCMException, NFHealService(nf_inst_id, req_data).run)
388 self.assertEqual(len(NfInstModel.objects.filter(nfinstid=nf_inst_id)), 0)
391 'local_storages': [],
394 'volumn_storages': [],
398 'local_storages': [],
399 'vdu_id': u'vdu_omm.001',
400 'image_file': u'opencos_sss_omm_img_release_20150723-1-disk1',
406 'support_scaling': False,
409 'storage_policy': '',
412 'availability_zone': '',
417 'inject_data_list': [],
421 'local_affinity_antiaffinity_rule': {},
422 'template_id': u'omm.001',
423 'manual_scale_select_vim': False},
424 'description': u'singleommvm'},
426 'volumn_storages': [],
430 'local_storages': [],
432 'image_file': u'sss',
438 'support_scaling': False,
441 'storage_policy': '',
444 'availability_zone': '',
449 'inject_data_list': [],
453 'local_affinity_antiaffinity_rule': {},
455 'manual_scale_select_vim': False},
456 'description': u'ompvm'},
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': {},
550 'template_id': u'10',
551 'manual_scale_select_vim': False},
552 'description': u'ppvm'},
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'11',
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'12',
615 'manual_scale_select_vim': False},
616 'description': u'ppvm'}],
617 'volumn_storages': [],
621 'policy_id': u'policy_scale_sss-vnf-template',
623 'policy_file': '*-vnfd.zip/*-vnf-policy.xml'},
629 'name': u'opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
631 'disk_format': u'VMDK',
632 'file_url': u'./zte-cn-sss-main-image/OMM/opencos_sss_omm_img_release_20150723-1-disk1.vmdk',
633 'container_type': 'vm',
635 'hypervisor_type': 'kvm'},
636 'image_file_id': u'opencos_sss_omm_img_release_20150723-1-disk1'},
642 'disk_format': u'VMDK',
643 'file_url': u'./zte-cn-sss-main-image/NE/sss.vmdk',
644 'container_type': 'vm',
646 'hypervisor_type': 'kvm'},
647 'image_file_id': u'sss'}],
654 'domain_type': u'CN',
655 'version': u'v4.14.10',
656 'vmnumber_overquota_alarm': False,
659 'vnfd_version': u'V00000001',
660 'id': u'sss-vnf-template',
661 'name': u'sss-vnf-template'}}
666 "externalDataNetworkName": {
678 "plugin_info": "vbrasplugin_1.0",
680 "is_shared": "False",
681 "request_reclassification": "False",
682 "vnfd_version": "1.0.0",
686 "externalDataNetworkName": {
687 "get_input": "externalDataNetworkName"},
698 "vl_id": "ext_mnet_network",
701 "network_type": "vlan",
702 "name": "externalMNetworkName",
703 "dhcp_enabled": False,
710 "end_ip": "190.168.100.100",
711 "gateway_ip": "190.168.100.1",
712 "start_ip": "190.168.100.2",
713 "cidr": "190.168.100.0/24",
715 "network_name": "sub_mnet",
720 "invariant_id": "vbras_ns",
721 "description": "vbras_ns",