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