882edd521a68f1b6701aa8c4a33595e393ef1edc
[vfc/nfvo/lcm.git] / lcm / ns_vnfs / biz / grant_vnf.py
1 # Copyright 2018 ZTE Corporation.
2 #
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
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 import json
16 import logging
17 import uuid
18 import time
19 from lcm.pub.database.models import NfInstModel, OOFDataModel
20 from lcm.pub.exceptions import NSLCMException
21 from lcm.pub.msapi import resmgr
22 from lcm.pub.msapi.sdc_run_catalog import query_vnfpackage_by_id
23 from lcm.pub.utils.values import ignore_case_get
24 from lcm.ns_vnfs.const import SCALAR_UNIT_DICT
25
26 logger = logging.getLogger(__name__)
27
28
29 class GrantVnf(object):
30     def __init__(self, grant_data):
31         self.data = grant_data
32
33     def exec_grant(self):
34         logger.debug("grant data from vnfm:%s", self.data)
35         if isinstance(self.data, str):
36             self.data = json.JSONDecoder().decode(self.data)
37         has_res_tpl = False
38         grant_type = None
39         action_type = ignore_case_get(self.data, "operation")
40         vimConnections = []
41         if ignore_case_get(self.data, "addResources"):
42             grant_type = "addResources"
43         elif ignore_case_get(self.data, "removeResources"):
44             grant_type = "removeResources"
45         else:
46             has_res_tpl = True
47
48         for res in ignore_case_get(self.data, grant_type):
49             if "resourceTemplate" in res:
50                 has_res_tpl = True
51                 break
52
53         if not has_res_tpl:
54             m_vnf_inst_id = ignore_case_get(self.data, "vnfInstanceId")
55             additional_param = ignore_case_get(self.data, "additionalparams")
56             vnfm_inst_id = ignore_case_get(additional_param, "vnfmid")
57             vim_id = ignore_case_get(additional_param, "vimid")
58             if vnfm_inst_id and vnfm_inst_id != "":
59                 vnfinsts = NfInstModel.objects.filter(
60                     mnfinstid=m_vnf_inst_id, vnfm_inst_id=vnfm_inst_id)
61             else:
62                 vnfinsts = NfInstModel.objects.filter(
63                     mnfinstid=m_vnf_inst_id)
64             if not vnfinsts:
65                 raise NSLCMException("Vnfinst(%s) is not found in vnfm(%s)" % (
66                     m_vnf_inst_id, vnfm_inst_id))
67
68             vnf_pkg_id = vnfinsts[0].package_id
69             nfpackage_info = query_vnfpackage_by_id(vnf_pkg_id)
70             vnf_pkg = nfpackage_info["packageInfo"]
71             vnfd = json.JSONDecoder().decode(vnf_pkg["vnfdModel"])
72
73             req_param = {
74                 "vnfInstanceId": m_vnf_inst_id,
75                 "vimId": vim_id,
76                 "vnfLcmOpOccId": ignore_case_get(self.data, "vnfLcmOpOccId"),
77                 "additionalParams": additional_param,
78                 grant_type: []
79             }
80             for res in ignore_case_get(self.data, grant_type):
81                 vdu_name = ignore_case_get(res, "vdu")
82                 grant_res = {
83                     "resourceDefinitionId": ignore_case_get(res, "resourceDefinitionId"),
84                     "type": ignore_case_get(res, "type"),
85                     "vdu": vdu_name
86                 }
87                 for vdu in vnfd["vdus"]:
88                     if vdu_name in (vdu["vdu_id"], vdu["properties"].get("name", "")):
89                         grant_res["resourceTemplate"] = self.get_res_tpl(vdu, vnfd)
90                         break
91                 req_param[grant_type].append(grant_res)
92             self.data = req_param
93         tmp = resmgr.grant_vnf(self.data)
94         vimConnections.append(
95             {
96                 "id": tmp["vim"]["vimId"],
97                 "vimId": tmp["vim"]["vimId"],
98                 "vimType": None,
99                 "interfaceInfo": None,
100                 "accessInfo": tmp["vim"]["accessInfo"],
101                 "extra": None
102             }
103         )
104
105         grant_resp = {
106             "id": str(uuid.uuid4()),
107             "vnfInstanceId": ignore_case_get(self.data, 'vnfInstanceId'),
108             "vnfLcmOpOccId": ignore_case_get(self.data, "vnfLcmOpOccId"),
109             "vimConnections": vimConnections
110         }
111
112         logger.debug("action_type=%s" % action_type)
113         if action_type == 'INSTANTIATE':
114             for i in range(18):
115                 offs = OOFDataModel.objects.filter(service_resource_id=ignore_case_get(self.data, "vnfInstanceId"))
116                 if not (offs.exists() and offs[0].vdu_info):
117                     logger.debug("Cannot find oof data, retry%s" % (i + 1))
118                     time.sleep(5)
119                     continue
120                 try:
121                     vdu_info = json.loads(offs[0].vdu_info)
122                     grant_resp['vimAssets'] = {'computeResourceFlavours': []}
123                     for vdu in vdu_info:
124                         grant_resp['vimAssets']['computeResourceFlavours'].append({
125                             'vimConnectionId': offs[0].vim_id,
126                             'resourceProviderId': vdu.get("vduName"),
127                             'vnfdVirtualComputeDescId': None,  # TODO: required
128                             'vimFlavourId': vdu.get("flavorId")
129                         })
130                         # grant_resp['additionalparams'][off.vim_id] = off.directive
131                 except Exception:
132                     logger.debug("Load OOF data error")
133                 break
134
135         logger.debug("grant_resp=%s", grant_resp)
136         return grant_resp
137
138     def get_res_tpl(self, vdu, vnfd):
139         storage_size = 0
140         for storage_id in vdu["local_storages"]:
141             storage_size = storage_size + self.get_storage_size(storage_id, vnfd)
142         resourceTemplate = {
143             "virtualComputeDescriptor": {
144                 "virtualCpu": {
145                     "numVirtualCpu": int(vdu["virtual_compute"]["virtual_cpu"]["num_virtual_cpu"])
146                 },
147                 "virtualMemory": {
148                     "virtualMemSize": parse_unit(vdu["virtual_compute"]["virtual_memory"]["virtual_mem_size"], "MB")
149                 }
150             },
151             "virtualStorageDescriptor": {
152                 "typeOfStorage": "",
153                 "sizeOfStorage": storage_size,
154                 "swImageDescriptor": ""
155             }
156         }
157         return resourceTemplate
158
159     def get_storage_size(self, storage_id, vnfd):
160         for storage in vnfd["local_storages"]:
161             if storage_id == storage["local_storage_id"]:
162                 return parse_unit(storage["properties"]["size"], "GB")
163         return 0
164
165
166 def parse_unit(val, base_unit):
167     # recognized_units = ["B", "kB", "KiB", "MB", "MiB", "GB", "GiB", "TB", "TiB"]
168     # units_rate = [1, 1000, 1024, 1000000, 1048576, 1000000000, 1073741824, 1000000000000, 1099511627776]
169     # unit_rate_map = {unit.upper(): rate for unit, rate in zip(recognized_units, units_rate)}
170     num_unit = val.strip().split(" ")
171     if len(num_unit) != 2:
172         return val.strip()
173     num, unit = num_unit[0], num_unit[1]
174     return int(num) * SCALAR_UNIT_DICT[unit.upper()] / SCALAR_UNIT_DICT[base_unit.upper()]