add gvnfm codes
[vfc/nfvo/driver/vnfm/gvnfm.git] / gvnfmadapter / driver / interfaces / views.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
16
17 import inspect
18 import json
19 import logging
20 import time
21 from rest_framework.decorators import api_view
22 from rest_framework.response import Response
23 from driver.pub.utils import restcall
24 from driver.pub.utils.restcall import req_by_msb
25 from rest_framework import status
26
27 # ==================================================
28 vnf_create_url = "openoapi/vnflcm/v1/vnf_instances"
29 vnf_inst_url = "openoapi/vnflcm/v1/vnf_instances/%s/instantiate"
30 vnf_delete_url = "openoapi/vnflcm/v1/vnf_instances/%s"
31 vnf_terminate_url = "openoapi/vnflcm/v1/vnf_instances/%s/terminate"
32 operation_status_url = "openoapi/vnflcm/v1/vnf_lc_ops/%s?responseId=%s"
33 vnf_detail_url = "openoapi/vnflcm/v1/vnf_instances/%s"
34 EXTSYS_GET_VNFM = "openoapi/extsys/v1/vnfms/%s"
35 vnf_query_url = "openoapi/vnflcm/v1/vnf_instances/%s"
36 notify_url = 'openoapi/nslcm/v1/vnfs/{vnfInstanceId}/Notify'
37
38 query_vnf_resp_mapping = {
39         "vnfInstanceId": "",
40         "vnfInstanceName": "",
41         "vnfInstanceDescription": "",
42         "vnfdId": "",
43         "vnfPackageId":"",
44         "version":"",
45         "vnfProvider":"",
46         "vnfType":"",
47         "vnfStatus":""
48 }
49
50
51 logger = logging.getLogger(__name__)
52
53
54 def mapping_conv(keyword_map, rest_return):
55     resp_data = {}
56     for param in keyword_map:
57         if keyword_map[param]:
58             if isinstance(keyword_map[param], dict):
59                 resp_data[param] = mapping_conv(keyword_map[param], ignorcase_get(rest_return, param))
60             else:
61                 resp_data[param] = ignorcase_get(rest_return, param)
62     return resp_data
63
64 def fun_name():
65     return "=================%s==================" % inspect.stack()[1][3]
66
67 def ignorcase_get(args, key):
68     if not key:
69         return ""
70     if not args:
71         return ""
72     if key in args:
73         return args[key]
74     for old_key in args:
75         if old_key.upper() == key.upper():
76             return args[old_key]
77     return ""
78
79 def set_createvnf_params(data):
80     input_data = {}
81     input_data["vnfdId"] = ignorcase_get(data,"vnfDescriptorId")
82     input_data["vnfInstanceName"] = ignorcase_get(data, "vnfInstanceName")
83     input_data["vnfInstanceDescription"] = ignorcase_get(data, "vnfInstanceDescription")
84
85     return input_data
86
87 def set_instantvnf_params(data):
88     input_data = {}
89     input_data["flavourId"] = ignorcase_get(data, "flavourId")
90     input_data["extVirtualLinks"] = ignorcase_get(data, "extVirtualLink")
91     input_data["additionalParams"] = ignorcase_get(data,"additionalParams")
92     input_data["flavourId"] = ignorcase_get(data,"flavourId")
93
94     return input_data
95
96 def set_terminatevnf_params(data):
97     input_data = {}
98     input_data["terminationType"] = ignorcase_get(data,"terminationType")
99     input_data["gracefulTerminationTimeout"] = ignorcase_get(data,"gracefulTerminationTimeout")
100
101     return input_data
102
103 def set_deletevnf_params(data):
104     pass
105
106
107 def get_inst_levelId(vnfdId):
108     inst_levelId = 0
109
110     return inst_levelId
111
112 def get_vnfm_info(vnfm_id):
113     ret = req_by_msb((EXTSYS_GET_VNFM) % vnfm_id, "GET")
114     if ret[0] != 0:
115         return 255, Response(data={'error': ret[1]}, status=ret[2])
116     vnfm_info = json.JSONDecoder().decode(ret[1])
117     logger.debug("[%s] vnfm_info=%s", fun_name(), vnfm_info)
118     return 0, vnfm_info
119
120 def call_vnfm_rest(vnfm_info, input_data, res_url, call_method = "post"):
121     ret = restcall.call_req(
122         base_url=ignorcase_get(vnfm_info, "url"),
123         user=ignorcase_get(vnfm_info, "userName"),
124         passwd=ignorcase_get(vnfm_info, "password"),
125         auth_type=restcall.rest_no_auth,
126         resource=res_url,
127         method=call_method,
128         content=json.JSONEncoder().encode(input_data))
129
130     return ret
131
132 def call_vnfm_createvnf(vnfm_info, input_data):
133     return call_vnfm_rest(vnfm_info, input_data, vnf_create_url)
134
135 def call_vnfm_instvnf(vnfm_info, input_data, vnfInstanceId):
136     return call_vnfm_rest(vnfm_info, input_data, vnf_inst_url % vnfInstanceId, "post")
137
138 def call_vnfm_terminatevnf(vnfm_info, input_data, vnfInstanceId):
139     return call_vnfm_rest(vnfm_info, input_data, vnf_terminate_url % vnfInstanceId, "post")
140
141 def call_vnfm_deletevnf(vnfm_info, vnfInstanceId):
142     return call_vnfm_rest(vnfm_info, None, vnf_delete_url % vnfInstanceId, "delete")
143
144 def call_vnfm_queryvnf(vnfm_info,vnfInstanceId):
145     return call_vnfm_rest(vnfm_info, None, vnf_query_url % vnfInstanceId, "get")
146
147 def call_vnfm_operation_status(vnfm_info, jobId, responseId = None):
148     return call_vnfm_rest(vnfm_info, None, operation_status_url % (jobId, responseId), "get")
149
150 def wait4job(vnfm_id,jobId,gracefulTerminationTimeout):
151
152     begin_time = time.time()
153     try:
154         ret, vnfm_info = get_vnfm_info(vnfm_id)
155         if ret != 0:
156             return 255, Response(data={"error":"Fail to get VNFM!"}, status=status.HTTP_412_PRECONDITION_FAILED)
157
158         responseId = None
159         while ret == 0:
160             cur_time = time.time()
161             if gracefulTerminationTimeout and (cur_time - begin_time > gracefulTerminationTimeout):
162                 return 255, Response(data={"error":"Fail to terminate VNF!"}, status=status.HTTP_408_REQUEST_TIMEOUT)
163
164             ret = call_vnfm_operation_status(vnfm_info,jobId,responseId)
165             if ret[0] != 0:
166                 return 255, Response(data={"error":"Fail to get job status!"}, status=status.HTTP_412_PRECONDITION_FAILED)
167             if json.JSONDecoder().decode(ret[2]) != 200:
168                 return 255, Response(data={"error":"Fail to get job status!"}, status=status.HTTP_412_PRECONDITION_FAILED)
169             job_info = json.JSONDecoder().decode(ret[1])
170             responseId = ignorcase_get(ignorcase_get(job_info, "VnfLcOpResponseDescriptor"), "responseId")
171             progress = ignorcase_get(ignorcase_get(job_info, "VnfLcOpResponseDescriptor"), "progress")
172             if progress == "100":
173                 return 0, Response(data={"success":"success"}, status=status.HTTP_204_NO_CONTENT)
174     except Exception as e:
175         logger.error("Error occurred when do_createvnf")
176         return 255, Response(data={"error":"Exception caught! Fail to get job status!"}, status=status.HTTP_412_PRECONDITION_FAILED)
177
178
179 def do_createvnf(request, data, vnfm_id):
180     logger.debug("[%s] request.data=%s", fun_name(), request.data)
181
182     try:
183         ret, vnfm_info = get_vnfm_info(vnfm_id)
184         if ret != 0:
185             return ret, vnfm_info
186
187         ret = call_vnfm_createvnf(vnfm_info, data)
188         logger.debug("[%s] call_req ret=%s", fun_name(), ret)
189         if ret[0] != 0:
190             return 255, Response(data={'error': ret[1]}, status=ret[2])
191         resp = json.JSONDecoder().decode(ret[1])
192     except Exception as e:
193         logger.error("Error occurred when do_createvnf")
194         raise e
195
196     return 0, resp
197
198 def do_instvnf(vnfInstanceId, request, data, vnfm_id):
199     logger.debug("[%s] request.data=%s", fun_name(), request.data)
200
201     try:
202         ret, vnfm_info = get_vnfm_info(vnfm_id)
203         if ret != 0:
204             return ret, vnfm_info
205
206         ret = call_vnfm_instvnf(vnfm_info,data, vnfInstanceId)
207         logger.debug("[%s] call_req ret=%s", fun_name(), ret)
208         if ret[0] != 0:
209             return 255, Response(data={'error': ret[1]}, status=ret[2])
210         resp = json.JSONDecoder().decode(ret[1])
211     except Exception as e:
212         logger.error("Error occurred when do_instvnf")
213         raise e
214
215     return 0, resp
216
217 def do_terminatevnf(request, data, vnfm_id, vnfInstanceId):
218     logger.debug("[%s] request.data=%s", fun_name(), request.data)
219     try:
220         ret, vnfm_info = get_vnfm_info(vnfm_id)
221         if ret != 0:
222             return ret,vnfm_info
223
224         ret = call_vnfm_terminatevnf(vnfm_info, data, vnfInstanceId)
225         if ret[0] != 0:
226             return 255, Response(data={'error': ret[1]}, status=ret[2])
227         resp_data = json.JSONDecoder().decode(ret[1])
228         logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
229     except Exception as e:
230         logger.error("Error occurred when do_terminatevnf")
231         raise e
232
233     return 0, resp_data
234
235 def do_deletevnf(request, vnfm_id, vnfInstanceId):
236     logger.debug("[%s] request.data=%s", fun_name(), request.data)
237     input_data = set_deletevnf_params(request.data)
238     try:
239         ret, vnfm_info = get_vnfm_info(vnfm_id)
240         if ret != 0:
241             return ret, vnfm_info
242
243         ret = call_vnfm_deletevnf(vnfm_info, vnfInstanceId)
244
245         if ret[0] != 0:
246             return 255, Response(data={'error': ret[1]}, status=ret[2])
247         resp_data = json.JSONDecoder().decode(ret[1])
248         logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
249     except Exception as e:
250         logger.error("Error occurred when do_deletevnf")
251         raise e
252     return 0, resp_data
253
254 def do_queryvnf(request, vnfm_id, vnfInstanceId):
255     logger.debug("[%s] request.data=%s", fun_name(), request.data)
256     try:
257         ret, vnfm_info = get_vnfm_info(vnfm_id)
258         if ret != 0:
259             return ret, vnfm_info
260
261         ret = call_vnfm_queryvnf(vnfm_info, vnfInstanceId)
262
263         if ret[0] != 0:
264             return 255, Response(data={'error': ret[1]}, status=ret[2])
265         resp_data = json.JSONDecoder().decode(ret[1])
266         logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
267     except Exception as e:
268         logger.error("Error occurred when do_query vnf")
269         raise e
270     return 0, resp_data
271
272 @api_view(http_method_names=['POST'])
273 def instantiate_vnf(request, *args, **kwargs):
274     try:
275         input_data = set_createvnf_params(request.data)
276         vnfm_id = ignorcase_get(kwargs, "vnfmid")
277         ret, resp = do_createvnf(request, input_data, vnfm_id)
278         if ret != 0:
279             return resp
280
281         logger.info("[%s]resp_data=%s", fun_name(), resp)
282         vnfInstanceId = resp["vnfInstanceId"]
283         logger.info("[%s]vnfInstanceId=%s", fun_name(), vnfInstanceId)
284
285         input_data = set_instantvnf_params(request.data)
286         ret, resp = do_instvnf(vnfInstanceId, request, input_data, vnfm_id)
287         if ret != 0:
288             return resp
289
290         resp_data = {"jobId":"", "vnfInstanceId":""}
291         resp_data["vnfInstanceId"] = vnfInstanceId
292         resp_data["jobId"] = resp["vnfLcOpId"]
293     except Exception as e:
294         logger.error("Error occurred when instantiating VNF")
295         raise e
296
297     return Response(data=resp_data, status=status.HTTP_201_CREATED)
298
299
300 @api_view(http_method_names=['POST'])
301 def terminate_vnf(request, *args, **kwargs):
302     vnfm_id = ignorcase_get(kwargs, "vnfmid")
303     vnfInstanceId = ignorcase_get(kwargs, "vnfInstanceId")
304     try:
305         input_data = set_terminatevnf_params(request.data)
306         ret, resp = do_terminatevnf(request, input_data, vnfm_id, vnfInstanceId)
307         if ret != 0:
308             return resp
309
310         jobId = ignorcase_get(resp, "vnfLcOpId")
311         gracefulTerminationTimeout = ignorcase_get(request.data, "gracefulTerminationTimeout")
312         ret, response = wait4job(vnfm_id,jobId,gracefulTerminationTimeout)
313         if ret != 0:
314             return response
315
316         ret, resp = do_deletevnf(request, vnfm_id, vnfInstanceId)
317         if ret != 0:
318             return resp
319
320     except Exception as e:
321         logger.error("Error occurred when terminating VNF")
322         raise e
323
324     return Response(data=resp, status=status.HTTP_204_NO_CONTENT)
325
326 @api_view(http_method_names=['GET'])
327 def query_vnf(request, *args, **kwargs):
328     vnfm_id = ignorcase_get(kwargs, "vnfmid")
329     vnfInstanceId = ignorcase_get(kwargs, "vnfInstanceId")
330     try:
331         logger.debug("[%s] request.data=%s", fun_name(), request.data)
332         ret, resp = do_queryvnf(request, vnfm_id, vnfInstanceId)
333         if ret != 0:
334             return resp
335
336         resp_response_data = mapping_conv(query_vnf_resp_mapping, ignorcase_get(resp, "ResponseInfo"))
337         resp_data = {
338             "vnfInfo":resp_response_data
339         }
340         #Handle vnfSoftwareVersion and vnfStatus specially
341         resp_data["vnfInfo"]["version"] = ignorcase_get(ignorcase_get(resp, "ResponseInfo"), "vnfSoftwareVersion")
342         if ignorcase_get(ignorcase_get(resp, "ResponseInfo"), "instantiationState"):
343             if ignorcase_get(ignorcase_get(resp, "ResponseInfo"), "instantiationState") == "INSTANTIATED":
344                 resp_data["vnfInfo"]["vnfStatus"] = "ACTIVE"
345         if ignorcase_get(ignorcase_get(resp, "ResponseInfo"), "vnfInstanceId"):
346             resp_data["vnfInfo"]["vnfInstanceId"] = ignorcase_get(ignorcase_get(resp, "ResponseInfo"), "vnfInstanceId")
347         logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
348     except Exception as e:
349         logger.error("Error occurred when querying VNF information.")
350         raise e
351     return Response(data=resp_data, status=status.HTTP_200_OK)
352
353 # ==================================================
354
355
356 @api_view(http_method_names=['GET'])
357 def operation_status(request, *args, **kwargs):
358     data = {}
359     try:
360         logger.debug("[%s] request.data=%s", fun_name(), request.data)
361         vnfm_id = ignorcase_get(kwargs, "vnfmid")
362         jobId = ignorcase_get(kwargs, "jobId")
363         responseId = ignorcase_get(kwargs, "responseId")
364
365         ret, vnfm_info = get_vnfm_info(vnfm_id)
366         if ret != 0:
367             return Response(data={'error': ret[1]}, status=ret[2])
368         logger.debug("[%s] vnfm_info=%s", fun_name(), vnfm_info)
369
370         ret = call_vnfm_operation_status(vnfm_info, jobId, responseId)
371
372         if ret[0] != 0:
373             return Response(data={'error': ret[1]}, status=ret[2])
374         resp_data = json.JSONDecoder().decode(ret[1])
375         logger.info("[%s]resp_data=%s", fun_name(), resp_data)
376         ResponseInfo = ignorcase_get(resp_data, "ResponseInfo")
377         operation_data = {}
378         operation_data["jobId"] = ignorcase_get(ResponseInfo, "vnfLcOpId")
379         operation_data["responseDescriptor"] = {}
380         operation_data["responseDescriptor"]["status"] = ignorcase_get(ignorcase_get(ResponseInfo, "responseDescriptor"),"lcmOperationStatus")
381         operation_data["responseDescriptor"]["progress"] = ignorcase_get(ignorcase_get(ResponseInfo, "responseDescriptor"),"progress")
382         operation_data["responseDescriptor"]["statusDescription"] = ignorcase_get(ignorcase_get(ResponseInfo, "responseDescriptor"),"statusDescription")
383         operation_data["responseDescriptor"]["errorCode"] = ignorcase_get(ignorcase_get(ResponseInfo, "responseDescriptor"),"errorCode")
384         operation_data["responseDescriptor"]["responseId"] = ignorcase_get(ignorcase_get(ResponseInfo, "responseDescriptor"),"responseId")
385         operation_data["responseDescriptor"]["responseHistoryList"] = ignorcase_get(ignorcase_get(ResponseInfo, "responseDescriptor"),"responseHistoryList")
386
387     except Exception as e:
388         logger.error("Error occurred when getting operation status information.")
389         raise e
390     return Response(data=operation_data, status=status.HTTP_200_OK)
391
392
393 # ==================================================
394 grant_vnf_url = 'openoapi/nslcm/v1/grantvnf'
395
396 @api_view(http_method_names=['PUT'])
397 def grantvnf(request, *args, **kwargs):
398     logger.info("=====grantvnf=====")
399     try:
400         resp_data = {}
401         logger.info("req_data = %s", request.data)
402         ret = req_by_msb(grant_vnf_url, "POST", content=json.JSONEncoder().encode(request.data))
403         logger.info("ret = %s", ret)
404         if ret[0] != 0:
405             return Response(data={'error': ret[1]}, status=ret[2])
406         resp = json.JSONDecoder().decode(ret[1])
407         resp_data['vimid'] = ignorcase_get(resp['vim'], 'vimid')
408         resp_data['tenant'] = ignorcase_get(ignorcase_get(resp['vim'], 'accessinfo'), 'tenant')
409         logger.info("[%s]resp_data=%s", fun_name(), resp_data)
410     except Exception as e:
411         logger.error("Error occurred in Grant VNF.")
412         raise e
413     return Response(data=resp_data, status=ret[2])
414
415
416 # ==================================================
417
418
419 @api_view(http_method_names=['POST'])
420 def notify(request, *args, **kwargs):
421     try:
422         logger.info("[%s]req_data = %s", fun_name(), request.data)
423         ret = req_by_msb(notify_url.format(vnfmid=ignorcase_get(request.data, 'VNFMID'),
424                                            vnfInstanceId=ignorcase_get(request.data, 'vnfinstanceid')),
425                          "POST", content=json.JSONEncoder().encode(request.data))
426         logger.info("[%s]data = %s", fun_name(), ret)
427         if ret[0] != 0:
428             return Response(data={'error': ret[1]}, status=ret[2])
429     except Exception as e:
430         logger.error("Error occurred in LCM notification.")
431         raise e
432     return Response(data=None, status=ret[2])
433     
434 @api_view(http_method_names=['GET'])
435 def get_vnfpkgs(request, *args, **kwargs):
436     logger.info("Enter %s", fun_name())
437     ret = req_by_msb("openoapi/nslcm/v1/vnfpackage", "GET")
438     if ret[0] != 0:
439         return Response(data={'error': ret[1]}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
440     resp = json.JSONDecoder().decode(ret[1])
441     return Response(data=resp, status=status.HTTP_200_OK)