diff options
-rw-r--r-- | lcm/v2/grant_vnf.py | 101 | ||||
-rw-r--r-- | lcm/v2/handle_vnflcmooc_notification.py | 22 | ||||
-rw-r--r-- | lcm/v2/tests.py | 56 | ||||
-rw-r--r-- | lcm/v2/views.py | 1 |
4 files changed, 154 insertions, 26 deletions
diff --git a/lcm/v2/grant_vnf.py b/lcm/v2/grant_vnf.py index a3ba37f9..38b1fbc2 100644 --- a/lcm/v2/grant_vnf.py +++ b/lcm/v2/grant_vnf.py @@ -15,6 +15,11 @@ import json import logging import uuid +from lcm.pub.database.models import NfInstModel +from lcm.pub.exceptions import NSLCMException +from lcm.pub.msapi.sdc_run_catalog import query_vnfpackage_by_id +from lcm.pub.utils.values import ignore_case_get +from lcm.pub.msapi import resmgr logger = logging.getLogger(__name__) @@ -24,12 +29,104 @@ class GrantVnf(object): self.data = grant_data def exec_grant(self): + logger.debug("grant data from vnfm:%s", self.data) if isinstance(self.data, (unicode, str)): self.data = json.JSONDecoder().decode(self.data) + has_res_tpl = False + grant_type = None + vimConnections = [] + if ignore_case_get(self.data, "addResources"): + grant_type = "addResources" + elif ignore_case_get(self.data, "removeResources"): + grant_type = "removeResources" + else: + has_res_tpl = True + + for res in ignore_case_get(self.data, grant_type): + if "resourceTemplate" in res: + has_res_tpl = True + break + + if not has_res_tpl: + m_vnf_inst_id = ignore_case_get(self.data, "vnfInstanceId") + additional_param = ignore_case_get(self.data, "additionalparam") + vnfm_inst_id = ignore_case_get(additional_param, "vnfmid") + vim_id = ignore_case_get(additional_param, "vimid") + + vnfinsts = NfInstModel.objects.filter( + mnfinstid=m_vnf_inst_id, vnfm_inst_id=vnfm_inst_id) + if not vnfinsts: + raise NSLCMException("Vnfinst(%s) is not found in vnfm(%s)" % ( + m_vnf_inst_id, vnfm_inst_id)) + + vnf_pkg_id = vnfinsts[0].package_id + nfpackage_info = query_vnfpackage_by_id(vnf_pkg_id) + vnf_pkg = nfpackage_info["packageInfo"] + vnfd = json.JSONDecoder().decode(vnf_pkg["vnfdModel"]) + + req_param = { + "vnfInstanceId": m_vnf_inst_id, + "vimId": vim_id, + "additionalParam": additional_param, + grant_type: [] + } + for res in ignore_case_get(self.data, grant_type): + vdu_name = ignore_case_get(res, "vdu") + grant_res = { + "resourceDefinitionId": ignore_case_get(res, "resourceDefinitionId"), + "type": ignore_case_get(res, "type"), + "vdu": vdu_name + } + for vdu in vnfd["vdus"]: + if vdu_name in (vdu["vdu_id"], vdu["properties"].get("name", "")): + grant_res["resourceTemplate"] = self.get_res_tpl(vdu, vnfd) + break + req_param[grant_type].append(grant_res) + self.data = req_param + vimConnections.append(resmgr.grant_vnf(self.data)) grant_resp = { "id": str(uuid.uuid4()), - "vnfInstanceId": self.data.get("vnfInstanceId"), - "vnfLcmOpOccId": self.data.get("vnfLcmOpOccId") + "vnfInstanceId": ignore_case_get(self.data, 'vnfInstanceId'), + "vnfLcmOpOccId": ignore_case_get(self.data, "vnfLcmOpOccId"), + "vimConnections": vimConnections } logger.debug("grant_resp=%s", grant_resp) return grant_resp + + def get_res_tpl(self, vdu, vnfd): + storage_size = 0 + for storage_id in vdu["local_storages"]: + storage_size = storage_size + self.get_storage_size(storage_id, vnfd) + resourceTemplate = { + "virtualComputeDescriptor": { + "virtualCpu": { + "numVirtualCpu": int(vdu["virtual_compute"]["virtual_cpu"]["num_virtual_cpu"]) + }, + "virtualMemory": { + "virtualMemSize": parse_unit(vdu["virtual_compute"]["virtual_memory"]["virtual_mem_size"], "MB") + } + }, + "virtualStorageDescriptor": { + "typeOfStorage": "", + "sizeOfStorage": storage_size, + "swImageDescriptor": "" + } + } + return resourceTemplate + + def get_storage_size(self, storage_id, vnfd): + for storage in vnfd["local_storages"]: + if storage_id == storage["local_storage_id"]: + return parse_unit(storage["properties"]["size"], "GB") + return 0 + + +def parse_unit(val, base_unit): + recognized_units = ["B", "kB", "KiB", "MB", "MiB", "GB", "GiB", "TB", "TiB"] + units_rate = [1, 1000, 1024, 1000000, 1048576, 1000000000, 1073741824, 1000000000000, 1099511627776] + unit_rate_map = {unit.upper(): rate for unit, rate in zip(recognized_units, units_rate)} + num_unit = val.strip().split(" ") + if len(num_unit) != 2: + return val.strip() + num, unit = num_unit[0], num_unit[1] + return int(num) * unit_rate_map[unit.upper()] / unit_rate_map[base_unit.upper()] diff --git a/lcm/v2/handle_vnflcmooc_notification.py b/lcm/v2/handle_vnflcmooc_notification.py index 3ab4debe..4b13a246 100644 --- a/lcm/v2/handle_vnflcmooc_notification.py +++ b/lcm/v2/handle_vnflcmooc_notification.py @@ -82,23 +82,23 @@ class HandleVnfLcmOocNotification(object): vmId = ignore_case_get(computeResource, 'resourceId') vmName = ignore_case_get(computeResource, 'resourceId') # replaced with resouceId temporarily - if changeType == 'added': + if changeType == 'ADDED': VNFCInstModel(vnfcinstanceid=vnfcInstanceId, vduid=vduId, nfinstid=self.vnf_instid, vmid=vmId).save() VmInstModel(vmid=vmId, vimid=vimId, resouceid=vmId, insttype=INST_TYPE.VNF, instid=self.vnf_instid, vmname=vmName, hostid='1').save() if REPORT_TO_AAI: self.create_vserver_in_aai(vimId, vmId, vmName) - elif changeType == 'removed': + elif changeType == 'REMOVED': if REPORT_TO_AAI: self.delete_vserver_in_aai(vimId, vmId, vmName) VNFCInstModel.objects.filter(vnfcinstanceid=vnfcInstanceId).delete() - elif changeType == 'modified': + elif changeType == 'MODIFIED': VNFCInstModel.objects.filter(vnfcinstanceid=vnfcInstanceId).update(vduid=vduId, nfinstid=self.vnf_instid, vmid=vmId) else: - self.exception('affectedVnfc struct error: changeType not in {added,removed,modified}') + self.exception('affectedVnfc struct error: changeType not in {ADDED, REMOVED, MODIFIED, TEMPORARY}') logger.debug("Success to update all vserver to aai.") def update_Vl(self): @@ -116,17 +116,17 @@ class HandleVnfLcmOocNotification(object): ownerId = self.get_vnfinstid(self.m_vnfInstanceId, self.vnfmid) - if changeType == 'added': + if changeType == 'ADDED': VLInstModel(vlinstanceid=vlInstanceId, vldid=vldid, vlinstancename=resourceName, ownertype=0, ownerid=ownerId, relatednetworkid=resourceId, vltype=0).save() - elif changeType == 'removed': + elif changeType == 'REMOVED': VLInstModel.objects.filter(vlinstanceid=vlInstanceId).delete() - elif changeType == 'modified': + elif changeType == 'MODIFIED': VLInstModel.objects.filter(vlinstanceid=vlInstanceId)\ .update(vldid=vldid, vlinstancename=resourceName, ownertype=0, ownerid=ownerId, relatednetworkid=resourceId, vltype=0) else: - self.exception('affectedVl struct error: changeType not in {added,removed,modified}') + self.exception('affectedVl struct error: changeType not in {ADDED, REMOVED, MODIFIED, TEMPORARY}') def update_Cp(self): for cp in self.affectedCps: @@ -182,12 +182,12 @@ class HandleVnfLcmOocNotification(object): ownerId = self.get_vnfinstid(self.m_vnfInstanceId, self.vnfmid) - if changeType in ['added', 'modified']: + if changeType in ['ADDED', 'MODIFIED']: self.create_network_and_subnet_in_aai(vlInstanceId, ownerId) - elif changeType == 'removed': + elif changeType == 'REMOVED': self.delete_network_and_subnet_in_aai(vlInstanceId) else: - logger.error('affectedVl struct error: changeType not in {added,removed,modified}') + logger.error('affectedVl struct error: changeType not in {ADDED, REMOVED, MODIFIED, TEMPORARY}') except NSLCMException as e: logger.debug("Fail to create internal network to aai, detail message: %s" % e.message) except: diff --git a/lcm/v2/tests.py b/lcm/v2/tests.py index 55fa2f1d..996852f1 100644 --- a/lcm/v2/tests.py +++ b/lcm/v2/tests.py @@ -14,18 +14,22 @@ import unittest import json -from django.test import Client +import mock +from rest_framework.test import APIClient from rest_framework import status +from lcm.pub.database.models import NfInstModel +from lcm.pub.utils import restcall class VnfGrantViewTest(unittest.TestCase): def setUp(self): - self.client = Client() + self.client = APIClient() def tearDown(self): pass - def test_grant_vnf_normal(self): + @mock.patch.object(restcall, 'call_req') + def test_grant_vnf_normal(self, mock_call_req): data = { "vnfInstanceId": "1", "vnfLcmOpOccId": "2", @@ -40,7 +44,7 @@ class VnfGrantViewTest(unittest.TestCase): "type": "COMPUTE", "vduId": "2", "resourceTemplateId": "3", - "resource": { + "resourceTemplate": { "vimConnectionId": "4", "resourceProviderId": "5", "resourceId": "6", @@ -85,13 +89,24 @@ class VnfGrantViewTest(unittest.TestCase): } } } + vimConnections = { + "id": "1", + "vimId": "1", + } + mock_call_req.return_value = [0, json.JSONEncoder().encode(vimConnections), '200'] response = self.client.post("/api/nslcm/v2/grants", data=data, format='json') self.assertEqual(status.HTTP_201_CREATED, response.status_code, response.content) resp_data = json.loads(response.content) expect_resp_data = { "id": resp_data.get("id"), "vnfInstanceId": "1", - "vnfLcmOpOccId": "2" + "vnfLcmOpOccId": "2", + "vimConnections": [ + { + "id": "1", + "vimId": "1" + } + ] } self.assertEqual(expect_resp_data, resp_data) @@ -114,11 +129,11 @@ class VnfGrantViewTest(unittest.TestCase): "affectedVnfcs": [{ "id": "string", "vduId": "string", - "changeType": "added", + "changeType": "ADDED", "computeResource": { "vimConnectionId": "string", "resourceProviderId": "string", - "resouceId": "string", + "resourceId": "string", "vimLevelResourceType": "string" }, "metadata": {}, @@ -127,16 +142,28 @@ class VnfGrantViewTest(unittest.TestCase): "removedStorageResourceIds": [], }], "affectedVirtualLinks": [{ - "vlInstanceId": "string", - "vldId": "string", - "changeType": "added", + "id": "string", + "virtualLinkDescId": "string", + "changeType": "ADDED", "networkResource": { - "resourceType": "network", + "vimConnectionId": "string", + "resourceProviderId": "string", "resourceId": "string", - "resourceName": "string" + "vimLevelResourceType": "network", } }], - "affectedVirtualStorages": [{}], + "affectedVirtualStorages": [{ + "id": "string", + "virtualStorageDescId": "string", + "changeType": "ADDED", + "storageResource": { + "vimConnectionId": "string", + "resourceProviderId": "string", + "resourceId": "string", + "vimLevelResourceType": "network", + }, + "metadata": {} + }], "changedInfo": { "vnfInstanceName": "string", "vnfInstanceDescription": "string", @@ -220,5 +247,8 @@ class VnfGrantViewTest(unittest.TestCase): } } } + NfInstModel.objects.create(nfinstid='22', + mnfinstid='2', + vnfm_inst_id='1') response = self.client.post("/api/nslcm/v2/ns/1/vnfs/2/Notify", data=data, format='json') self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code, response.content) diff --git a/lcm/v2/views.py b/lcm/v2/views.py index a3ce25a7..9c953c19 100644 --- a/lcm/v2/views.py +++ b/lcm/v2/views.py @@ -75,6 +75,7 @@ class VnfNotifyView(APIView): vnfLcmOocNotificationSerializer = VnfLcmOperationOccurrenceNotificationSerializer(data=request.data) if not vnfLcmOocNotificationSerializer.is_valid(): raise Exception(vnfLcmOocNotificationSerializer.errors) + HandleVnfLcmOocNotification(vnfmId, vnfInstanceId, vnfLcmOocNotificationSerializer.data).do_biz() return Response(data={}, status=status.HTTP_204_NO_CONTENT) except Exception as e: |