1 # Copyright 2017 ZTE Corporation.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
21 from drf_yasg.utils import swagger_auto_schema
22 from rest_framework import status
23 from rest_framework.response import Response
24 from rest_framework.views import APIView
26 from driver.pub.exceptions import GvnfmDriverException
27 from driver.pub.utils import restcall
28 from driver.pub.utils.restcall import req_by_msb
29 from driver.interfaces.serializers import VnfInstReqParamsSerializer, ResponseSerializer
30 from driver.interfaces.serializers import VnfTermReqSerializer, VnfQueryRespSerializer
31 from driver.interfaces.serializers import VnfOperRespSerializer, VnfGrantReqSerializer, VnfGrantRespSerializer
32 from driver.interfaces.serializers import VnfNotifyReqSerializer, VNFLCMOpOccSerializer
34 logger = logging.getLogger(__name__)
37 class VnfInstInfo(APIView):
39 request_body=VnfInstReqParamsSerializer(),
41 status.HTTP_201_CREATED: ResponseSerializer(),
42 status.HTTP_404_NOT_FOUND: "The vnfm instance id is wrong",
43 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
46 def post(self, request, vnfmtype, vnfmid):
47 logger.debug("instantiate_vnf--post::> %s" % request.data)
48 logger.debug("Create vnf begin!")
50 requestSerializer = VnfInstReqParamsSerializer(data=request.data)
51 request_isValid = requestSerializer.is_valid()
52 if not request_isValid:
53 raise Exception(requestSerializer.errors)
55 # requestData = requestSerializer.data
56 requestData = request.data
58 "vnfdId": ignorcase_get(requestData, "vnfDescriptorId"),
59 "vnfInstanceName": ignorcase_get(requestData, "vnfInstanceName"),
60 "vnfInstanceDescription": ignorcase_get(requestData, "vnfInstanceDescription")
63 logger.debug("do_createvnf: request data=[%s],input_data=[%s],vnfm_id=[%s]",
64 request.data, input_data, vnfm_id)
65 resp = do_createvnf(vnfm_id, input_data)
66 logger.debug("do_createvnf: response data=[%s]", resp)
67 logger.debug("Create vnf end!")
69 logger.debug("Instantiate vnf start!")
70 vnfInstanceId = resp["id"]
72 "flavourId": ignorcase_get(requestData, "flavourId"),
73 "extVirtualLinks": ignorcase_get(requestData, "extVirtualLink"),
74 "additionalParams": ignorcase_get(requestData, "additionalParam"),
76 logger.debug("do_instvnf: vnfInstanceId=[%s],request data=[%s],input_data=[%s],vnfm_id=[%s]",
77 vnfInstanceId, request.data, input_data, vnfm_id)
78 resp = do_instvnf(vnfInstanceId, vnfm_id, input_data)
79 logger.debug("do_instvnf: response data=[%s]", resp)
81 "vnfInstanceId": vnfInstanceId,
82 "jobId": ignorcase_get(resp, "jobId")
84 logger.debug("Instantiate vnf end!")
85 return Response(data=resp_data, status=status.HTTP_201_CREATED)
86 except GvnfmDriverException as e:
87 logger.error('instantiate vnf failed, detail message: %s' % e.message)
88 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
90 logger.error(traceback.format_exc())
91 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
94 class VnfTermInfo(APIView):
96 request_body=VnfTermReqSerializer(),
98 status.HTTP_201_CREATED: ResponseSerializer(),
99 status.HTTP_404_NOT_FOUND: "The vnfmid and vnfInstanceId are wrong",
100 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
103 def post(self, request, vnfmtype, vnfmid, vnfInstanceId):
104 logger.debug("terminate_vnf--post::> %s" % request.data)
105 logger.debug("Terminate vnf begin!")
109 "terminationType": ignorcase_get(request.data, "terminationType"),
110 "gracefulTerminationTimeout": ignorcase_get(request.data, "gracefulTerminationTimeout")
112 logger.debug("do_terminatevnf: vnfm_id=[%s],vnfInstanceId=[%s],input_data=[%s]",
113 vnfm_id, vnfInstanceId, input_data)
114 resp = do_terminatevnf(vnfm_id, vnfInstanceId, input_data)
115 logger.debug("terminate_vnf: response data=[%s]", resp)
117 jobId = ignorcase_get(resp, "jobId")
118 gracefulTerminationTimeout = ignorcase_get(request.data, "gracefulTerminationTimeout")
119 logger.debug("wait4job: vnfm_id=[%s],jobId=[%s],gracefulTerminationTimeout=[%s]",
120 vnfm_id, jobId, gracefulTerminationTimeout)
121 resp = wait4job(vnfm_id, jobId, gracefulTerminationTimeout)
122 logger.debug("[wait4job] response=[%s]", resp)
124 logger.debug("Delete vnf start!")
125 logger.debug("do_deletevnf: vnfm_id=[%s],vnfInstanceId=[%s],request data=[%s]",
126 vnfm_id, vnfInstanceId, request.data)
127 resp = do_deletevnf(vnfm_id, vnfInstanceId, request.data)
128 logger.debug("do_deletevnf: response data=[%s]", resp)
129 logger.debug("Delete vnf end!")
131 return Response(data=resp, status=status.HTTP_204_NO_CONTENT)
132 except GvnfmDriverException as e:
133 logger.error('Terminate vnf failed, detail message: %s' % e.message)
134 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
136 logger.error(traceback.format_exc())
137 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
140 class VnfQueryInfo(APIView):
141 @swagger_auto_schema(
143 status.HTTP_201_CREATED: VnfQueryRespSerializer(),
144 status.HTTP_404_NOT_FOUND: "The vnfmid and vnfInstanceId are wrong",
145 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
148 def get(self, request, vnfmtype, vnfmid, vnfInstanceId):
149 logger.debug("query_vnf--post::> %s" % request.data)
152 logger.debug("[%s] request.data=%s", fun_name(), request.data)
153 resp = do_queryvnf(request, vnfm_id, vnfInstanceId)
154 query_vnf_resp_mapping = {
156 "vnfInstanceName": "",
157 "vnfInstanceDescription": "",
165 ResponseInfo = ignorcase_get(resp, "ResponseInfo")
166 resp_response_data = mapping_conv(query_vnf_resp_mapping, ResponseInfo)
168 "vnfInfo": resp_response_data
170 id = ignorcase_get(ResponseInfo, "id")
172 resp_data["vnfInfo"]["vnfInstanceId"] = id
173 vnfPkgId = ignorcase_get(ResponseInfo, "vnfPkgId")
175 resp_data["vnfInfo"]["vnfPackageId"] = vnfPkgId
176 vnfSoftwareVersion = ignorcase_get(ResponseInfo, "vnfSoftwareVersion")
177 if vnfSoftwareVersion:
178 resp_data["vnfInfo"]["version"] = vnfSoftwareVersion
179 if ignorcase_get(ResponseInfo, "instantiationState") == "INSTANTIATED":
180 resp_data["vnfInfo"]["vnfStatus"] = "ACTIVE"
181 logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
182 return Response(data=resp_data, status=status.HTTP_200_OK)
183 except GvnfmDriverException as e:
184 logger.error('Query vnf failed, detail message: %s' % e.message)
185 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
187 logger.error(traceback.format_exc())
188 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
191 class VnfOperInfo(APIView):
192 @swagger_auto_schema(
194 status.HTTP_201_CREATED: VnfOperRespSerializer(),
195 status.HTTP_404_NOT_FOUND: "The vnfmid, jobid and responseId are wrong",
196 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
199 def get(self, request, vnfmtype, vnfmid, jobid):
200 logger.debug("operation_status--post::> %s" % request.data)
202 logger.debug("[%s] request.data=%s", fun_name(), request.data)
205 responseId = ignorcase_get(request.META, 'responseId')
206 logger.debug("[operation_status] vnfm_id=%s", vnfm_id)
207 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
208 logger.debug("[operation_status] vnfm_info=[%s]", vnfm_info)
210 ret = call_vnfm("api/vnflcm/v1/vnf_lc_ops/%s?responseId=%s" % (jobId, responseId), "GET", vnfm_info)
212 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
213 raise GvnfmDriverException('Failed to query vnf operation status.')
214 resp_data = json.JSONDecoder().decode(ret[1])
215 logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
216 ResponseInfo = ignorcase_get(resp_data, "ResponseInfo")
217 responseDescriptor = ignorcase_get(ResponseInfo, "responseDescriptor")
218 status_tmp = ignorcase_get(responseDescriptor, "lcmOperationStatus")
219 del responseDescriptor["lcmOperationStatus"]
220 responseDescriptor["status"] = status_tmp
222 "jobId": ignorcase_get(ResponseInfo, "vnfLcOpId"),
223 "responseDescriptor": responseDescriptor
225 return Response(data=operation_data, status=status.HTTP_200_OK)
226 except GvnfmDriverException as e:
227 logger.error('Query vnf failed, detail message: %s' % e.message)
228 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
230 logger.error(traceback.format_exc())
231 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
234 class VnfGrantInfo(APIView):
235 @swagger_auto_schema(
236 request_body=VnfGrantReqSerializer(),
238 status.HTTP_201_CREATED: VnfGrantRespSerializer(),
239 status.HTTP_404_NOT_FOUND: "The request body is wrong",
240 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
243 def put(self, request, vnfmtype):
245 logger.debug("[grantvnf] req_data = %s", request.data)
246 ret = req_by_msb('api/nslcm/v2/grants', "POST", content=json.JSONEncoder().encode(request.data))
247 logger.debug("ret = %s", ret)
249 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
250 raise GvnfmDriverException('Failed to grant vnf.')
251 resp = json.JSONDecoder().decode(ret[1])
252 logger.debug("[%s]resp_data=%s", fun_name(), resp)
253 return Response(data=resp, status=status.HTTP_201_CREATED)
254 except GvnfmDriverException as e:
255 logger.error('Grant vnf failed, detail message: %s' % e.message)
256 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
258 logger.error(traceback.format_exc())
259 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
262 class VnfNotifyInfo(APIView):
263 @swagger_auto_schema(
264 request_body=VnfNotifyReqSerializer(),
266 status.HTTP_201_CREATED: "Successful Notify",
267 status.HTTP_404_NOT_FOUND: "The request body is wrong",
268 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
271 def post(self, request, vnfmtype):
273 logger.debug("[%s]req_data = %s", fun_name(), request.data)
274 vnfminstid = ignorcase_get(request.data, 'vnfmInstId')
275 vnfinstanceid = ignorcase_get(request.data, 'vnfInstanceId')
276 request.data.pop("vnfmInstId")
277 ret = req_by_msb("api/nslcm/v2/ns/%s/vnfs/%s/Notify" % (vnfminstid, vnfinstanceid), "POST",
278 json.JSONEncoder().encode(request.data))
279 logger.debug("[%s]data = %s", fun_name(), ret)
281 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
282 raise GvnfmDriverException('Failed to notify vnf.')
283 return Response(data=None, status=status.HTTP_200_OK)
284 except GvnfmDriverException as e:
285 logger.error('Grant vnf failed, detail message: %s' % e.message)
286 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
288 logger.error(traceback.format_exc())
289 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
292 class VnfPkgsInfo(APIView):
293 def get(request, *args, **kwargs):
295 logger.debug("Enter %s", fun_name())
296 ret = req_by_msb("api/nslcm/v1/vnfpackage", "GET")
298 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
299 raise GvnfmDriverException('Failed to get vnfpkgs.')
300 resp = json.JSONDecoder().decode(ret[1])
301 return Response(data=resp, status=status.HTTP_200_OK)
302 except GvnfmDriverException as e:
303 logger.error('Get vnfpkgs failed, detail message: %s' % e.message)
304 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
306 logger.error(traceback.format_exc())
307 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
309 class QuerySingleVnfLcmOpOcc(APIView):
310 @swagger_auto_schema(
312 status.HTTP_200_OK: VNFLCMOpOccSerializer(),
313 status.HTTP_500_INTERNAL_SERVER_ERROR: ""
316 def get(self, request, vnfmtype, vnfmid, lcmopoccid):
317 logger.debug("[%s]LCMOpOccId = %s", fun_name(), lcmopoccid)
319 vnfm_info = get_vnfminfo_from_nslcm(vnfmid)
320 logger.debug("[get lcm op occ] vnfm_info=[%s]", vnfm_info)
321 ret = call_vnfm("api/vnflcm/v1/vnf_lcm_op_occs/%s" % lcmopoccid, "GET", vnfm_info)
323 logger.error("Status code is %s. detail is %s.", ret[2], ret[1])
324 raise GvnfmDriverException("Failed to query vnf lcm op occ %s" % lcmopoccid)
325 resp_data = json.JSONDecoder().decode(ret[1])
326 vnf_lcm_op_occ_serializer = VNFLCMOpOccSerializer(data=resp_data)
327 if vnf_lcm_op_occ_serializer.is_valid():
328 logger.debug("[%s]resp_data=%s" % (fun_name(), resp_data))
329 return Response(data=vnf_lcm_op_occ_serializer.data, status=status.HTTP_200_OK)
331 raise GvnfmDriverException(vnf_lcm_op_occ_serializer.errors)
332 except GvnfmDriverException as e:
333 logger.error("Query vnflcmopocc failed, detail message: %s" % e.message)
334 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
336 logger.error(traceback.format_exc())
337 return Response(data={'error': traceback.format_exc()}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
340 def call_vnfm(resource, method, vnfm_info, data=""):
341 ret = restcall.call_req(
342 base_url=ignorcase_get(vnfm_info, "url"),
343 user=ignorcase_get(vnfm_info, "userName"),
344 passwd=ignorcase_get(vnfm_info, "password"),
345 auth_type=restcall.rest_no_auth,
348 content=json.JSONEncoder().encode(data))
352 def mapping_conv(keyword_map, rest_return):
354 for param in keyword_map:
355 # if keyword_map[param]:
356 if isinstance(keyword_map[param], dict):
357 resp_data[param] = mapping_conv(keyword_map[param], ignorcase_get(rest_return, param))
359 value = ignorcase_get(rest_return, param)
361 resp_data[param] = value
366 return "=========%s=========" % inspect.stack()[1][3]
369 def ignorcase_get(args, key):
377 if old_key.upper() == key.upper():
382 def get_vnfminfo_from_nslcm(vnfm_id):
383 logger.debug("[get_vnfminfo_from_nslcm] vnfm_id=[%s]", vnfm_id)
384 # ret = req_by_msb("api/aai-esr-server/v1/vnfms/%s" % vnfm_id, "GET")
385 ret = req_by_msb("api/nslcm/v1/vnfms/%s" % vnfm_id, "GET")
386 logger.debug("[get_vnfminfo_from_nslcm] response=%s", ret)
388 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
389 raise GvnfmDriverException("Failed to query vnfm(%s) from nslcm." % vnfm_id)
390 return json.JSONDecoder().decode(ret[1])
393 def wait4job(vnfm_id, job_id, gracefulTerminationTimeout=1200, retry_count=60, interval_second=3):
394 logger.debug("[wait4job] vnfm_id=[%s],jobId=[%s],gracefulTerminationTimeout=[%s]",
395 vnfm_id, job_id, gracefulTerminationTimeout)
397 response_id, new_response_id = 0, 0
398 job_end_normal, job_timeout = False, True
399 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
400 logger.debug("[do_terminatevnf] vnfm_info=[%s]", vnfm_info)
401 while count < retry_count:
403 time.sleep(interval_second)
404 ret = call_vnfm("api/vnflcm/v1/vnf_lc_ops/%s?responseId=%s" % (job_id, response_id), "GET", vnfm_info)
406 logger.error("Failed to query job: %s:%s", ret[2], ret[1])
408 job_result = json.JSONDecoder().decode(ret[1])
409 if "responseDescriptor" not in job_result:
410 logger.error("Job(%s) does not exist.", job_id)
412 progress = job_result["responseDescriptor"]["progress"]
413 new_response_id = job_result["responseDescriptor"]["responseId"]
414 job_desc = job_result["responseDescriptor"]["statusDescription"]
415 if new_response_id != response_id:
416 logger.debug("%s:%s:%s", progress, new_response_id, job_desc)
417 response_id = new_response_id
421 logger.error("Job(%s) failed: %s", job_id, job_desc)
423 elif progress == 100:
424 job_end_normal, job_timeout = True, False
425 logger.debug("Job(%s) ended normally,job_end_normal=[%s],job_timeout=[%s]",
426 job_id, job_end_normal, job_timeout)
427 return {"success": "success"}
429 logger.error("Job(%s) timeout", job_id)
430 raise GvnfmDriverException("Fail to get job status!")
433 def do_createvnf(vnfm_id, data):
434 logger.debug("[%s] request.data=%s", fun_name(), data)
435 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
436 logger.debug("[do_createvnf] vnfm_info=[%s]", vnfm_info)
437 ret = call_vnfm("api/vnflcm/v1/vnf_instances", "POST", vnfm_info, data)
438 logger.debug("[%s] call_req ret=%s", fun_name(), ret)
440 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
441 raise GvnfmDriverException('Failed to create vnf.')
442 return json.JSONDecoder().decode(ret[1])
445 def do_instvnf(vnfInstanceId, vnfm_id, data):
446 logger.debug("[%s] request.data=%s", fun_name(), data)
447 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
448 logger.debug("[do_instvnf] vnfm_info=[%s]", vnfm_info)
449 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s/instantiate" % vnfInstanceId, "POST", vnfm_info, data)
450 logger.debug("[%s] call_req ret=%s", fun_name(), ret)
452 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
453 raise GvnfmDriverException('Failed to inst vnf.')
454 return json.JSONDecoder().decode(ret[1])
457 def do_terminatevnf(vnfm_id, vnfInstanceId, data):
458 logger.debug("[%s] request.data=%s", fun_name(), data)
459 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
460 logger.debug("[do_terminatevnf] vnfm_info=[%s]", vnfm_info)
461 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s/terminate" % vnfInstanceId, "POST", vnfm_info, data)
463 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
464 raise GvnfmDriverException('Failed to terminate vnf.')
465 return json.JSONDecoder().decode(ret[1])
468 def do_deletevnf(vnfm_id, vnfInstanceId, data):
469 logger.debug("[%s] request.data=%s", fun_name(), data)
470 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
471 logger.debug("[do_deletevnf] vnfm_info=[%s]", vnfm_info)
472 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s" % vnfInstanceId, "DELETE", vnfm_info)
474 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
475 raise GvnfmDriverException('Failed to delete vnf.')
476 return json.JSONDecoder().decode(ret[1])
479 def do_queryvnf(data, vnfm_id, vnfInstanceId):
480 logger.debug("[%s] request.data=%s", fun_name(), data)
481 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
482 logger.debug("[do_deletevnf] vnfm_info=[%s]", vnfm_info)
483 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s" % vnfInstanceId, "GET", vnfm_info)
485 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
486 raise GvnfmDriverException('Failed to query vnf.')
487 return json.JSONDecoder().decode(ret[1])