Add error logs for null scaling info
[vfc/nfvo/lcm.git] / lcm / pub / utils / scaleaspect.py
1 # Copyright 2017 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 os
18 import copy
19 from lcm.pub.database.models import NfInstModel
20 from lcm.pub.database.models import NSInstModel
21 from lcm.ns.vnfs.const import VNF_STATUS
22 from lcm.pub.msapi import catalog
23
24
25 logger = logging.getLogger(__name__)
26 SCALE_TYPE = ("SCALE_NS", "SCALE_VNF")
27
28 scale_vnf_data_mapping = {
29     "vnfInstanceId": "",
30     "scaleByStepData": {
31         "type": "",
32         "aspectId": "",
33         "numberOfSteps": ""
34     }
35 }
36
37
38 def ignorcase_get(args, key):
39     if not key:
40         return ""
41     if not args:
42         return ""
43     if key in args:
44         return args[key]
45     for old_key in args:
46         if old_key.upper() == key.upper():
47             return args[old_key]
48     return ""
49
50
51 def mapping_conv(keyword_map, rest_return):
52     resp_data = {}
53     for param in keyword_map:
54         if keyword_map[param]:
55             if isinstance(keyword_map[param], dict):
56                 resp_data[param] = mapping_conv(
57                     keyword_map[param], ignorcase_get(
58                         rest_return, param))
59             else:
60                 resp_data[param] = ignorcase_get(rest_return, param)
61     return resp_data
62
63
64 def get_vnf_scale_info(filename, ns_instanceId, aspect, step):
65     json_data = get_json_data(filename)
66     scale_options = ignorcase_get(json_data, "scale_options")
67     for i in range(scale_options.__len__()):
68         ns_scale_option = scale_options[i]
69         if (ignorcase_get(ns_scale_option, "ns_instanceId") == ns_instanceId) \
70                 and (ignorcase_get(ns_scale_option, "ns_scale_aspect") == aspect):
71             ns_scale_info_list = ignorcase_get(
72                 ns_scale_option, "ns_scale_info_list")
73             for j in range(ns_scale_info_list.__len__()):
74                 ns_scale_info = ns_scale_info_list[j]
75                 if ns_scale_info["step"] == step:
76                     return ns_scale_info["vnf_scale_info"]
77
78     return None
79
80
81 def get_vnf_instance_id_list(vnfd_id):
82     kwargs = {}
83     kwargs['package_id'] = vnfd_id
84     kwargs['status'] = VNF_STATUS.ACTIVE
85
86     nf_model_list = NfInstModel.objects.filter(**kwargs)
87     vnf_instance_id_list = list()
88     nf_model_len = nf_model_list.__len__()
89     if nf_model_len == 0:
90         logger.error("No VNF instances found(vnfd_id=%s)" % vnfd_id)
91     else:
92         for i in range(nf_model_len):
93             vnf_instance_id_list.append(nf_model_list[i].nfinstid)
94
95     return vnf_instance_id_list
96
97
98 def get_json_data(filename):
99     f = open(filename)
100     json_str = f.read()
101     data = json.JSONDecoder().decode(json_str)
102     f.close()
103     return data
104
105
106 def check_scale_list(vnf_scale_list, ns_instanceId, aspect, step):
107     if vnf_scale_list is None:
108         logger.debug(
109             "The scaling option[ns=%s, aspect=%s, step=%s] does not exist. Pls check the config file." %
110             (ns_instanceId, aspect, step))
111         raise Exception(
112             "The scaling option[ns=%s, aspect=%s, step=%s] does not exist. Pls check the config file." %
113             (ns_instanceId, aspect, step))
114     else:
115         return vnf_scale_list
116
117
118 def get_scale_vnf_data_list(filename, ns_instanceId, aspect, step, scale_type):
119
120     vnf_scale_list = get_vnf_scale_info(filename, ns_instanceId, aspect, step)
121     check_scale_list(vnf_scale_list, ns_instanceId, aspect, step)
122     scaleVnfDataList = set_scaleVnfData_type(vnf_scale_list, scale_type)
123     logger.debug("scaleVnfDataList = %s" % scaleVnfDataList)
124     return scaleVnfDataList
125
126
127 # Get the nsd id according to the ns instance id.
128 def get_nsdId(ns_instanceId):
129     if NSInstModel.objects.filter(id=ns_instanceId):
130         nsd_id = NSInstModel.objects.filter(id=ns_instanceId)[0].nsd_id
131         return nsd_id
132
133     return None
134
135
136 def get_and_check_params(scaleNsByStepsData, ns_InstanceId):
137
138     if scaleNsByStepsData is None:
139         pass
140         # raise NSLCMException("Error! scaleNsByStepsData in the request is Empty!")
141
142     aspect = scaleNsByStepsData["aspectId"]
143     numberOfSteps = scaleNsByStepsData["numberOfSteps"]
144     scale_type = scaleNsByStepsData["scalingDirection"]
145
146     return aspect, numberOfSteps, scale_type
147
148
149 def get_scale_vnf_data(scaleNsData, ns_InstanceId):
150     curdir_path = os.path.dirname(
151         os.path.dirname(
152             os.path.dirname(
153                 os.path.abspath(__file__))))
154     filename = curdir_path + "/ns/data/scalemapping.json"
155     logger.debug("filename = %s" % filename)
156     aspect, numberOfSteps, scale_type = get_and_check_params(
157         scaleNsData, ns_InstanceId)
158     return get_scale_vnf_data_list(
159         filename,
160         ns_InstanceId,
161         aspect,
162         numberOfSteps,
163         scale_type)
164
165
166 # Get scaling vnf data info list according to the ns instance id and request ScaleNsData.
167 def get_scale_vnf_data_info_list(scaleNsData, ns_InstanceId):
168     # Gets the nsd id accordign to the ns instance id.
169     nsd_id = get_nsdId(ns_InstanceId)
170
171     # Gets the scalingmap json data from the package according to the ns instance id.
172     scalingmap_json = catalog.get_scalingmap_json_package(ns_InstanceId)
173
174     # Gets and checks the values of parameters.
175     aspect, numberOfSteps, scale_type = get_and_check_params(
176         scaleNsData, ns_InstanceId)
177
178     # Firstly, gets the scaling vnf data info list from the scaling map json data.
179     scale_vnf_data_info_list_from_json = get_scale_vnf_data_from_json(scalingmap_json, nsd_id, aspect, numberOfSteps)
180     check_scale_list(scale_vnf_data_info_list_from_json, ns_InstanceId, aspect, numberOfSteps)
181
182     # Secondly, adds the property of vnfInstanceId to the list according to the vnfd id.
183     scale_vnf_data_info_list = set_scacle_vnf_instance_id(scale_vnf_data_info_list_from_json)
184     check_scale_list(scale_vnf_data_info_list, ns_InstanceId, aspect, numberOfSteps)
185
186     # Lastly, adds the property of type to the list acoording to the request ScaleNsData.
187     scale_vnf_data_info_list = set_scaleVnfData_type(scale_vnf_data_info_list, scale_type)
188     check_scale_list(scale_vnf_data_info_list, ns_InstanceId, aspect, numberOfSteps)
189
190     return scale_vnf_data_info_list
191
192
193 # Get the vnf scaling info from the scaling_map.json according to the ns package id.
194 def get_scale_vnf_data_from_json(scalingmap_json, nsd_id, aspect, step):
195     scale_options = ignorcase_get(scalingmap_json, "scale_options")
196     for i in range(scale_options.__len__()):
197         ns_scale_option = scale_options[i]
198         if (ignorcase_get(ns_scale_option, "nsd_id") == nsd_id) and (
199                 ignorcase_get(ns_scale_option, "ns_scale_aspect") == aspect):
200             ns_scale_info_list = ignorcase_get(
201                 ns_scale_option, "ns_scale_info")
202             for j in range(ns_scale_info_list.__len__()):
203                 ns_scale_info = ns_scale_info_list[j]
204                 if ns_scale_info["step"] == step:
205                     vnf_scale_info_list = ns_scale_info["vnf_scale_info"]
206
207                     return vnf_scale_info_list
208
209     logger.error("get_scale_vnf_data_from_json method retuan null")
210     return None
211
212
213 # Gets the vnf instance id according to the vnfd_id and modify the list of scaling vnf info accrodingly.
214 def set_scacle_vnf_instance_id(vnf_scale_info_list):
215     scale_vnf_data_info_list = []
216     for i in range(vnf_scale_info_list.__len__()):
217         vnf_scale_info = vnf_scale_info_list[i]
218         vnfd_id = vnf_scale_info["vnfd_id"]
219         vnf_instance_id_list = get_vnf_instance_id_list(vnfd_id)
220         index = 0
221         while index < vnf_instance_id_list.__len__():
222             copy_vnf_scale_info = copy.deepcopy(vnf_scale_info)
223             copy_vnf_scale_info.pop("vnfd_id")
224             copy_vnf_scale_info["vnfInstanceId"] = vnf_instance_id_list[index]
225             index += 1
226             scale_vnf_data_info_list.append(copy_vnf_scale_info)
227
228     return scale_vnf_data_info_list
229
230
231 # Sets the scaling type of vnf data info list.
232 def set_scaleVnfData_type(vnf_scale_list, scale_type):
233     logger.debug(
234         "vnf_scale_list = %s, type = %s" %
235         (vnf_scale_list, scale_type))
236     scaleVnfDataList = []
237     if vnf_scale_list is not None:
238         for i in range(vnf_scale_list.__len__()):
239             scaleVnfData = copy.deepcopy(scale_vnf_data_mapping)
240             scaleVnfData["vnfInstanceId"] = vnf_scale_list[i]["vnfInstanceId"]
241             scaleVnfData["scaleByStepData"]["type"] = scale_type
242             scaleVnfData["scaleByStepData"]["aspectId"] = vnf_scale_list[i]["vnf_scaleAspectId"]
243             scaleVnfData["scaleByStepData"]["numberOfSteps"] = vnf_scale_list[i]["numberOfSteps"]
244             scaleVnfDataList.append(scaleVnfData)
245     logger.debug("scaleVnfDataList = %s" % scaleVnfDataList)
246     return scaleVnfDataList