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.interfaces.serializers.serializers import VnfInstReqParamsSerializer, ResponseSerializer
27 from driver.interfaces.serializers.serializers import VnfNotifyReqSerializer, VNFLCMOpOccSerializer
28 from driver.interfaces.serializers.serializers import VnfOperRespSerializer
29 from driver.interfaces.serializers.serializers import VnfTermReqSerializer, VnfQueryRespSerializer
30 from driver.interfaces.serializers.grant_request import GrantRequestSerializer
31 from driver.interfaces.serializers.grant import GrantSerializer
32 from driver.pub.exceptions import GvnfmDriverException
33 from driver.pub.utils import restcall
34 from driver.pub.utils.restcall import req_by_msb
36 logger = logging.getLogger(__name__)
39 class VnfInstInfo(APIView):
41 request_body=VnfInstReqParamsSerializer(),
43 status.HTTP_201_CREATED: ResponseSerializer(),
44 status.HTTP_404_NOT_FOUND: "The vnfm instance id is wrong",
45 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
48 def post(self, request, vnfmtype, vnfmid):
49 logger.debug("instantiate_vnf--post::> %s" % request.data)
50 logger.debug("Create vnf begin!")
52 requestSerializer = VnfInstReqParamsSerializer(data=request.data)
53 request_isValid = requestSerializer.is_valid()
54 if not request_isValid:
55 raise Exception(requestSerializer.errors)
57 # requestData = requestSerializer.data
58 requestData = request.data
60 "vnfdId": ignorcase_get(requestData, "vnfDescriptorId"),
61 "vnfInstanceName": ignorcase_get(requestData, "vnfInstanceName"),
62 "vnfInstanceDescription": ignorcase_get(requestData, "vnfInstanceDescription")
65 logger.debug("do_createvnf: request data=[%s],input_data=[%s],vnfm_id=[%s]",
66 request.data, input_data, vnfm_id)
67 resp = do_createvnf(vnfm_id, input_data)
68 logger.debug("do_createvnf: response data=[%s]", resp)
69 logger.debug("Create vnf end!")
71 logger.debug("Instantiate vnf start!")
72 vnfInstanceId = resp["id"]
74 "flavourId": ignorcase_get(requestData, "flavourId"),
75 "extVirtualLinks": ignorcase_get(requestData, "extVirtualLink"),
76 "additionalParams": ignorcase_get(requestData, "additionalParam"),
78 logger.debug("do_instvnf: vnfInstanceId=[%s],request data=[%s],input_data=[%s],vnfm_id=[%s]",
79 vnfInstanceId, request.data, input_data, vnfm_id)
80 resp = do_instvnf(vnfInstanceId, vnfm_id, input_data)
81 logger.debug("do_instvnf: response data=[%s]", resp)
83 "vnfInstanceId": vnfInstanceId,
84 "jobId": ignorcase_get(resp, "jobId")
86 logger.debug("Instantiate vnf end!")
87 return Response(data=resp_data, status=status.HTTP_201_CREATED)
88 except GvnfmDriverException as e:
89 logger.error('instantiate vnf failed, detail message: %s' % e.message)
90 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
92 logger.error(traceback.format_exc())
93 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
96 class VnfTermInfo(APIView):
98 request_body=VnfTermReqSerializer(),
100 status.HTTP_201_CREATED: ResponseSerializer(),
101 status.HTTP_404_NOT_FOUND: "The vnfmid and vnfInstanceId are wrong",
102 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
105 def post(self, request, vnfmtype, vnfmid, vnfInstanceId):
106 logger.debug("terminate_vnf--post::> %s" % request.data)
107 logger.debug("Terminate vnf begin!")
111 "terminationType": ignorcase_get(request.data, "terminationType"),
112 "gracefulTerminationTimeout": ignorcase_get(request.data, "gracefulTerminationTimeout")
114 logger.debug("do_terminatevnf: vnfm_id=[%s],vnfInstanceId=[%s],input_data=[%s]",
115 vnfm_id, vnfInstanceId, input_data)
116 resp = do_terminatevnf(vnfm_id, vnfInstanceId, input_data)
117 logger.debug("terminate_vnf: response data=[%s]", resp)
119 jobId = ignorcase_get(resp, "jobId")
120 gracefulTerminationTimeout = ignorcase_get(request.data, "gracefulTerminationTimeout")
121 logger.debug("wait4job: vnfm_id=[%s],jobId=[%s],gracefulTerminationTimeout=[%s]",
122 vnfm_id, jobId, gracefulTerminationTimeout)
123 resp = wait4job(vnfm_id, jobId, gracefulTerminationTimeout)
124 logger.debug("[wait4job] response=[%s]", resp)
126 logger.debug("Delete vnf start!")
127 logger.debug("do_deletevnf: vnfm_id=[%s],vnfInstanceId=[%s],request data=[%s]",
128 vnfm_id, vnfInstanceId, request.data)
129 resp = do_deletevnf(vnfm_id, vnfInstanceId, request.data)
130 logger.debug("do_deletevnf: response data=[%s]", resp)
131 logger.debug("Delete vnf end!")
133 return Response(data=resp, status=status.HTTP_204_NO_CONTENT)
134 except GvnfmDriverException as e:
135 logger.error('Terminate vnf failed, detail message: %s' % e.message)
136 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
138 logger.error(traceback.format_exc())
139 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
142 class VnfQueryInfo(APIView):
143 @swagger_auto_schema(
145 status.HTTP_201_CREATED: VnfQueryRespSerializer(),
146 status.HTTP_404_NOT_FOUND: "The vnfmid and vnfInstanceId are wrong",
147 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
150 def get(self, request, vnfmtype, vnfmid, vnfInstanceId):
151 logger.debug("query_vnf--post::> %s" % request.data)
154 logger.debug("[%s] request.data=%s", fun_name(), request.data)
155 resp = do_queryvnf(request, vnfm_id, vnfInstanceId)
156 query_vnf_resp_mapping = {
158 "vnfInstanceName": "",
159 "vnfInstanceDescription": "",
167 ResponseInfo = ignorcase_get(resp, "ResponseInfo")
168 resp_response_data = mapping_conv(query_vnf_resp_mapping, ResponseInfo)
170 "vnfInfo": resp_response_data
172 id = ignorcase_get(ResponseInfo, "id")
174 resp_data["vnfInfo"]["vnfInstanceId"] = id
175 vnfPkgId = ignorcase_get(ResponseInfo, "vnfPkgId")
177 resp_data["vnfInfo"]["vnfPackageId"] = vnfPkgId
178 vnfSoftwareVersion = ignorcase_get(ResponseInfo, "vnfSoftwareVersion")
179 if vnfSoftwareVersion:
180 resp_data["vnfInfo"]["version"] = vnfSoftwareVersion
181 if ignorcase_get(ResponseInfo, "instantiationState") == "INSTANTIATED":
182 resp_data["vnfInfo"]["vnfStatus"] = "ACTIVE"
183 logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
184 return Response(data=resp_data, status=status.HTTP_200_OK)
185 except GvnfmDriverException as e:
186 logger.error('Query vnf failed, detail message: %s' % e.message)
187 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
189 logger.error(traceback.format_exc())
190 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
193 class VnfOperInfo(APIView):
194 @swagger_auto_schema(
196 status.HTTP_201_CREATED: VnfOperRespSerializer(),
197 status.HTTP_404_NOT_FOUND: "The vnfmid, jobid and responseId are wrong",
198 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
201 def get(self, request, vnfmtype, vnfmid, jobid):
202 logger.debug("operation_status--post::> %s" % request.data)
204 logger.debug("[%s] request.data=%s", fun_name(), request.data)
207 responseId = ignorcase_get(request.META, 'responseId')
208 logger.debug("[operation_status] vnfm_id=%s", vnfm_id)
209 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
210 logger.debug("[operation_status] vnfm_info=[%s]", vnfm_info)
212 ret = call_vnfm("api/vnflcm/v1/vnf_lc_ops/%s?responseId=%s" % (jobId, responseId), "GET", vnfm_info)
214 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
215 raise GvnfmDriverException('Failed to query vnf operation status.')
216 resp_data = json.JSONDecoder().decode(ret[1])
217 logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
218 ResponseInfo = ignorcase_get(resp_data, "ResponseInfo")
219 responseDescriptor = ignorcase_get(ResponseInfo, "responseDescriptor")
220 status_tmp = ignorcase_get(responseDescriptor, "lcmOperationStatus")
221 del responseDescriptor["lcmOperationStatus"]
222 responseDescriptor["status"] = status_tmp
224 "jobId": ignorcase_get(ResponseInfo, "vnfLcOpId"),
225 "responseDescriptor": responseDescriptor
227 return Response(data=operation_data, status=status.HTTP_200_OK)
228 except GvnfmDriverException as e:
229 logger.error('Query vnf failed, detail message: %s' % e.message)
230 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
232 logger.error(traceback.format_exc())
233 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
236 class VnfGrantInfo(APIView):
237 @swagger_auto_schema(
238 request_body=GrantRequestSerializer(), # TODO: not used
240 status.HTTP_201_CREATED: GrantSerializer(),
241 status.HTTP_404_NOT_FOUND: "The request body is wrong",
242 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
245 def put(self, request, vnfmtype):
247 logger.debug("[grantvnf] req_data = %s", request.data)
248 grant_request = GrantRequestSerializer(data=request.data)
249 if not grant_request.is_valid():
250 raise GvnfmDriverException(grant_request.error_messages)
251 ret = req_by_msb('api/nslcm/v2/grants', "POST", content=json.JSONEncoder().encode(request.data))
252 logger.debug("ret = %s", ret)
254 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
255 raise GvnfmDriverException('Failed to grant vnf.')
256 resp = json.JSONDecoder().decode(ret[1])
257 grant = GrantSerializer(data=resp)
258 if not grant.is_valid():
259 raise GvnfmDriverException(grant.error_messages)
260 logger.debug("[%s]resp_data=%s", fun_name(), resp)
261 return Response(data=resp, status=status.HTTP_201_CREATED)
262 except GvnfmDriverException as e:
263 logger.error('Grant vnf failed, detail message: %s' % e.message)
264 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
266 logger.error(traceback.format_exc())
267 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
270 class VnfNotifyInfo(APIView):
271 @swagger_auto_schema(
272 request_body=VnfNotifyReqSerializer(),
274 status.HTTP_201_CREATED: "Successful Notify",
275 status.HTTP_404_NOT_FOUND: "The request body is wrong",
276 status.HTTP_500_INTERNAL_SERVER_ERROR: "The url is invalid"
279 def post(self, request, vnfmtype): # TODO: not compatable with VnfIdentifierCreationNotification and VnfIdentifierDeletionNotification
281 logger.debug("[%s]req_data = %s", fun_name(), request.data)
282 vnfminstid = ignorcase_get(request.data, 'vnfmInstId')
283 vnfinstanceid = ignorcase_get(request.data, 'vnfInstanceId')
284 request.data.pop("vnfmInstId")
285 ret = req_by_msb("api/nslcm/v2/ns/%s/vnfs/%s/Notify" % (vnfminstid, vnfinstanceid), "POST",
286 json.JSONEncoder().encode(request.data))
287 logger.debug("[%s]data = %s", fun_name(), ret)
289 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
290 raise GvnfmDriverException('Failed to notify vnf.')
291 return Response(data=None, status=status.HTTP_200_OK)
292 except GvnfmDriverException as e:
293 logger.error('Grant vnf failed, detail message: %s' % e.message)
294 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
296 logger.error(traceback.format_exc())
297 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
300 class VnfPkgsInfo(APIView):
301 def get(request, *args, **kwargs):
303 logger.debug("Enter %s", fun_name())
304 ret = req_by_msb("api/nslcm/v1/vnfpackage", "GET")
306 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
307 raise GvnfmDriverException('Failed to get vnfpkgs.')
308 resp = json.JSONDecoder().decode(ret[1])
309 return Response(data=resp, status=status.HTTP_200_OK)
310 except GvnfmDriverException as e:
311 logger.error('Get vnfpkgs failed, detail message: %s' % e.message)
312 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
314 logger.error(traceback.format_exc())
315 return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
317 class QuerySingleVnfLcmOpOcc(APIView):
318 @swagger_auto_schema(
320 status.HTTP_200_OK: VNFLCMOpOccSerializer(),
321 status.HTTP_500_INTERNAL_SERVER_ERROR: ""
324 def get(self, request, vnfmtype, vnfmid, lcmopoccid):
325 logger.debug("[%s]LCMOpOccId = %s", fun_name(), lcmopoccid)
327 vnfm_info = get_vnfminfo_from_nslcm(vnfmid)
328 logger.debug("[get lcm op occ] vnfm_info=[%s]", vnfm_info)
329 ret = call_vnfm("api/vnflcm/v1/vnf_lcm_op_occs/%s" % lcmopoccid, "GET", vnfm_info)
331 logger.error("Status code is %s. detail is %s.", ret[2], ret[1])
332 raise GvnfmDriverException("Failed to query vnf lcm op occ %s" % lcmopoccid)
333 resp_data = json.JSONDecoder().decode(ret[1])
334 vnf_lcm_op_occ_serializer = VNFLCMOpOccSerializer(data=resp_data)
335 if vnf_lcm_op_occ_serializer.is_valid():
336 logger.debug("[%s]resp_data=%s" % (fun_name(), resp_data))
337 return Response(data=vnf_lcm_op_occ_serializer.data, status=status.HTTP_200_OK)
339 raise GvnfmDriverException(vnf_lcm_op_occ_serializer.errors)
340 except GvnfmDriverException as e:
341 logger.error("Query vnflcmopocc failed, detail message: %s" % e.message)
342 return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
344 logger.error(traceback.format_exc())
345 return Response(data={'error': traceback.format_exc()}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
348 def call_vnfm(resource, method, vnfm_info, data=""):
349 ret = restcall.call_req(
350 base_url=ignorcase_get(vnfm_info, "url"),
351 user=ignorcase_get(vnfm_info, "userName"),
352 passwd=ignorcase_get(vnfm_info, "password"),
353 auth_type=restcall.rest_no_auth,
356 content=json.JSONEncoder().encode(data))
360 def mapping_conv(keyword_map, rest_return):
362 for param in keyword_map:
363 # if keyword_map[param]:
364 if isinstance(keyword_map[param], dict):
365 resp_data[param] = mapping_conv(keyword_map[param], ignorcase_get(rest_return, param))
367 value = ignorcase_get(rest_return, param)
369 resp_data[param] = value
374 return "=========%s=========" % inspect.stack()[1][3]
377 def ignorcase_get(args, key):
385 if old_key.upper() == key.upper():
390 def get_vnfminfo_from_nslcm(vnfm_id):
391 logger.debug("[get_vnfminfo_from_nslcm] vnfm_id=[%s]", vnfm_id)
392 # ret = req_by_msb("api/aai-esr-server/v1/vnfms/%s" % vnfm_id, "GET")
393 ret = req_by_msb("api/nslcm/v1/vnfms/%s" % vnfm_id, "GET")
394 logger.debug("[get_vnfminfo_from_nslcm] response=%s", ret)
396 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
397 raise GvnfmDriverException("Failed to query vnfm(%s) from nslcm." % vnfm_id)
398 return json.JSONDecoder().decode(ret[1])
401 def wait4job(vnfm_id, job_id, gracefulTerminationTimeout=1200, retry_count=60, interval_second=3):
402 logger.debug("[wait4job] vnfm_id=[%s],jobId=[%s],gracefulTerminationTimeout=[%s]",
403 vnfm_id, job_id, gracefulTerminationTimeout)
405 response_id, new_response_id = 0, 0
406 job_end_normal, job_timeout = False, True
407 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
408 logger.debug("[do_terminatevnf] vnfm_info=[%s]", vnfm_info)
409 while count < retry_count:
411 time.sleep(interval_second)
412 ret = call_vnfm("api/vnflcm/v1/vnf_lc_ops/%s?responseId=%s" % (job_id, response_id), "GET", vnfm_info)
414 logger.error("Failed to query job: %s:%s", ret[2], ret[1])
416 job_result = json.JSONDecoder().decode(ret[1])
417 if "responseDescriptor" not in job_result:
418 logger.error("Job(%s) does not exist.", job_id)
420 progress = job_result["responseDescriptor"]["progress"]
421 new_response_id = job_result["responseDescriptor"]["responseId"]
422 job_desc = job_result["responseDescriptor"]["statusDescription"]
423 if new_response_id != response_id:
424 logger.debug("%s:%s:%s", progress, new_response_id, job_desc)
425 response_id = new_response_id
429 logger.error("Job(%s) failed: %s", job_id, job_desc)
431 elif progress == 100:
432 job_end_normal, job_timeout = True, False
433 logger.debug("Job(%s) ended normally,job_end_normal=[%s],job_timeout=[%s]",
434 job_id, job_end_normal, job_timeout)
435 return {"success": "success"}
437 logger.error("Job(%s) timeout", job_id)
438 raise GvnfmDriverException("Fail to get job status!")
441 def do_createvnf(vnfm_id, data):
442 logger.debug("[%s] request.data=%s", fun_name(), data)
443 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
444 logger.debug("[do_createvnf] vnfm_info=[%s]", vnfm_info)
445 ret = call_vnfm("api/vnflcm/v1/vnf_instances", "POST", vnfm_info, data)
446 logger.debug("[%s] call_req ret=%s", fun_name(), ret)
448 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
449 raise GvnfmDriverException('Failed to create vnf.')
450 return json.JSONDecoder().decode(ret[1])
453 def do_instvnf(vnfInstanceId, vnfm_id, data):
454 logger.debug("[%s] request.data=%s", fun_name(), data)
455 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
456 logger.debug("[do_instvnf] vnfm_info=[%s]", vnfm_info)
457 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s/instantiate" % vnfInstanceId, "POST", vnfm_info, data)
458 logger.debug("[%s] call_req ret=%s", fun_name(), ret)
460 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
461 raise GvnfmDriverException('Failed to inst vnf.')
462 return json.JSONDecoder().decode(ret[1])
465 def do_terminatevnf(vnfm_id, vnfInstanceId, data):
466 logger.debug("[%s] request.data=%s", fun_name(), data)
467 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
468 logger.debug("[do_terminatevnf] vnfm_info=[%s]", vnfm_info)
469 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s/terminate" % vnfInstanceId, "POST", vnfm_info, data)
471 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
472 raise GvnfmDriverException('Failed to terminate vnf.')
473 return json.JSONDecoder().decode(ret[1])
476 def do_deletevnf(vnfm_id, vnfInstanceId, data):
477 logger.debug("[%s] request.data=%s", fun_name(), data)
478 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
479 logger.debug("[do_deletevnf] vnfm_info=[%s]", vnfm_info)
480 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s" % vnfInstanceId, "DELETE", vnfm_info)
482 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
483 raise GvnfmDriverException('Failed to delete vnf.')
484 return json.JSONDecoder().decode(ret[1])
487 def do_queryvnf(data, vnfm_id, vnfInstanceId):
488 logger.debug("[%s] request.data=%s", fun_name(), data)
489 vnfm_info = get_vnfminfo_from_nslcm(vnfm_id)
490 logger.debug("[do_deletevnf] vnfm_info=[%s]", vnfm_info)
491 ret = call_vnfm("api/vnflcm/v1/vnf_instances/%s" % vnfInstanceId, "GET", vnfm_info)
493 logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
494 raise GvnfmDriverException('Failed to query vnf.')
495 return json.JSONDecoder().decode(ret[1])