update link to upper-constraints.txt
[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.sdc_run_catalog import query_vnfpackage_by_id
22 from lcm.pub.utils.values import ignore_case_get
23 from lcm.ns_vnfs.const import SCALAR_UNIT_DICT
24
25 logger = logging.getLogger(__name__)
26
27
28 class GrantVnf(object):
29     def __init__(self, grant_data):
30         self.data = grant_data
31
32     def exec_grant(self):
33         logger.debug("grant data from vnfm:%s", self.data)
34         if isinstance(self.data, str):
35             self.data = json.JSONDecoder().decode(self.data)
36         has_res_tpl = False
37         grant_type = None
38         action_type = ignore_case_get(self.data, "operation")
39         vimConnections = []
40         if ignore_case_get(self.data, "addResources"):
41             grant_type = "addResources"
42         elif ignore_case_get(self.data, "removeResources"):
43             grant_type = "removeResources"
44         else:
45             has_res_tpl = True
46
47         for res in ignore_case_get(self.data, grant_type):
48             if "resourceTemplate" in res:
49                 has_res_tpl = True
50                 break
51
52         if not has_res_tpl:
53             m_vnf_inst_id = ignore_case_get(self.data, "vnfInstanceId")
54             additional_param = ignore_case_get(self.data, "additionalparams")
55             vnfm_inst_id = ignore_case_get(additional_param, "vnfmid")
56             vim_id = ignore_case_get(additional_param, "vimid")
57             if vnfm_inst_id and vnfm_inst_id != "":
58                 vnfinsts = NfInstModel.objects.filter(
59                     mnfinstid=m_vnf_inst_id, vnfm_inst_id=vnfm_inst_id)
60             else:
61                 vnfinsts = NfInstModel.objects.filter(
62                     mnfinstid=m_vnf_inst_id)
63             if not vnfinsts:
64                 raise NSLCMException("Vnfinst(%s) is not found in vnfm(%s)" % (
65                     m_vnf_inst_id, vnfm_inst_id))
66
67             vnf_pkg_id = vnfinsts[0].package_id
68             nfpackage_info = query_vnfpackage_by_id(vnf_pkg_id)
69             vnf_pkg = nfpackage_info["packageInfo"]
70             vnfd = json.JSONDecoder().decode(vnf_pkg["vnfdModel"])
71
72             req_param = {
73                 "vnfInstanceId": m_vnf_inst_id,
74                 "vimId": vim_id,
75                 "vnfLcmOpOccId": ignore_case_get(self.data, "vnfLcmOpOccId"),
76                 "additionalParams": additional_param,
77                 grant_type: []
78             }
79             for res in ignore_case_get(self.data, grant_type):
80                 vdu_name = ignore_case_get(res, "vdu")
81                 grant_res = {
82                     "resourceDefinitionId": ignore_case_get(res, "resourceDefinitionId"),
83                     "type": ignore_case_get(res, "type"),
84                     "vdu": vdu_name
85                 }
86                 for vdu in vnfd["vdus"]:
87                     if vdu_name in (vdu["vdu_id"], vdu["properties"].get("name", "")):
88                         grant_res["resourceTemplate"] = self.get_res_tpl(vdu, vnfd)
89                         break
90                 req_param[grant_type].append(grant_res)
91             self.data = req_param
92         res = vim_connections_get(self.data)
93         vimConnections.append(
94             {
95                 "id": res["vim"]["vimId"],
96                 "vimId": res["vim"]["vimId"],
97                 "vimType": None,
98                 "interfaceInfo": None,
99                 "accessInfo": {
100                     "tenant": res["vim"]["accessInfo"]["tenant"]
101                 },
102                 "extra": None
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(
116                     service_resource_id=ignore_case_get(self.data, "vnfInstanceId"))
117                 if not (offs.exists() and offs[0].vdu_info):
118                     logger.debug("Cannot find oof data, retry%s" % (i + 1))
119                     time.sleep(5)
120                     continue
121                 try:
122                     vdu_info = json.loads(offs[0].vdu_info)
123                     grant_resp['vimAssets'] = {'computeResourceFlavours': []}
124                     for vdu in vdu_info:
125                         grant_resp['vimAssets']['computeResourceFlavours'].append({
126                             'vimConnectionId': offs[0].vim_id,
127                             'resourceProviderId': vdu.get("vduName"),
128                             'vnfdVirtualComputeDescId': None,  # TODO: required
129                             'vimFlavourId': vdu.get("flavorId")
130                         })
131                         # grant_resp['additionalparams'][off.vim_id] = off.directive
132                 except Exception:
133                     logger.debug("Load OOF data error")
134                 break
135
136         logger.debug("grant_resp=%s", grant_resp)
137         return grant_resp
138
139     def get_res_tpl(self, vdu, vnfd):
140         storage_size = 0
141         for storage_id in vdu["local_storages"]:
142             storage_size = storage_size + self.get_storage_size(storage_id, vnfd)
143         resourceTemplate = {
144             "virtualComputeDescriptor": {
145                 "virtualCpu": {
146                     "numVirtualCpu": int(vdu["virtual_compute"]["virtual_cpu"]["num_virtual_cpu"])
147                 },
148                 "virtualMemory": {
149                     "virtualMemSize": parse_unit(
150                         vdu["virtual_compute"]["virtual_memory"]["virtual_mem_size"], "MB")
151                 }
152             },
153             "virtualStorageDescriptor": {
154                 "typeOfStorage": "",
155                 "sizeOfStorage": storage_size,
156                 "swImageDescriptor": ""
157             }
158         }
159         return resourceTemplate
160
161     def get_storage_size(self, storage_id, vnfd):
162         for storage in vnfd["local_storages"]:
163             if storage_id == storage["local_storage_id"]:
164                 return parse_unit(storage["properties"]["size"], "GB")
165         return 0
166
167
168 def parse_unit(val, base_unit):
169     # recognized_units = ["B", "kB", "KiB", "MB", "MiB", "GB", "GiB", "TB", "TiB"]
170     # units_rate = [1, 1000, 1024, 1000000, 1048576, 1000000000, 1073741824, 1000000000000, 1099511627776]
171     # unit_rate_map = {unit.upper(): rate for unit, rate in zip(recognized_units, units_rate)}
172     num_unit = val.strip().split(" ")
173     if len(num_unit) != 2:
174         return val.strip()
175     num, unit = num_unit[0], num_unit[1]
176     return int(num) * SCALAR_UNIT_DICT[unit.upper()] / SCALAR_UNIT_DICT[base_unit.upper()]
177
178
179 def vim_connections_get(req_param):
180     vim_id = ""
181     if "vimId" in req_param:
182         vim_id = req_param["vimId"]
183     elif "additionalparam" in req_param and "vimid" in req_param["additionalparam"]:
184         vim_id = req_param["additionalparam"]["vimid"]
185     elif "additionalParams" in req_param and "vimid" in req_param["additionalParams"]:
186         vim_id = req_param["additionalParams"]["vimid"]
187     try:
188         from lcm.pub.msapi import extsys
189         vim = extsys.get_vim_by_id(vim_id)
190         if isinstance(vim, list):
191             vim = vim[0]
192             vim_id = vim["vimId"]
193         if "vimId" in vim:
194             vim_id = vim["vimId"]
195         rsp = {
196             "vim": {
197                 "vimId": vim_id,
198                 "accessInfo": {
199                     "tenant": vim["tenant"]
200                 }
201             }
202         }
203         logger.debug("rsp=%s" % rsp)
204         return rsp
205     except:
206         raise NSLCMException('Failed to get vimConnections info')