Remove vfc-svnfm-zte-driver openo labels
[vfc/nfvo/driver/vnfm/svnfm.git] / zte / vmanager / driver / interfaces / views.py
1 # Copyright 2016-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 inspect
16 import json
17 import logging
18 import traceback
19
20 from rest_framework.decorators import api_view
21 from rest_framework.response import Response
22
23 from driver.pub.utils import restcall
24 from driver.pub.utils.restcall import req_by_msb
25
26 logger = logging.getLogger(__name__)
27
28
29 def fun_name():
30     return "=================%s==================" % inspect.stack()[1][3]
31
32
33 def ignorcase_get(args, key):
34     if not key:
35         return ""
36     if not args:
37         return ""
38     if key in args:
39         return args[key]
40     for old_key in args:
41         if old_key.upper() == key.upper():
42             return args[old_key]
43     return ""
44
45
46 def mapping_conv(keyword_map, rest_return):
47     resp_data = {}
48     for param in keyword_map:
49         if keyword_map[param]:
50             resp_data[keyword_map[param]] = ignorcase_get(rest_return, param)
51     return resp_data
52
53
54 query_vnfd_url = "api/nslcm/v1/vnfpackage/%s"
55 query_vnfm_url = "api/extsys/v1/vnfms/%s"
56 query_package_url = "api/nslcm/v1/vnfpackage/%s"
57
58
59 # Query VNFM by VNFMID
60 def vnfm_get(vnfmid):
61     ret = req_by_msb("api/extsys/v1/vnfms/%s" % vnfmid, "GET")
62     return ret
63
64
65 def vnfd_get(vnfpackageid):
66     ret = req_by_msb("api/nslcm/v1/vnfpackage/%s" % vnfpackageid, "GET")
67     return ret
68
69
70 def vnfpackage_get(csarid):
71     ret = req_by_msb("api/nslcm/v1/vnfpackage/%s" % csarid, "GET")
72     return ret
73
74
75 # ==================================================
76 create_vnf_url = "v1/vnfs"
77 create_vnf_param_mapping = {
78     "packageUrl": "",
79     "instantiateUrl": "",
80     "instantiationLevel": "",
81     "vnfInstanceName": "",
82     "vnfPackageId": "",
83     "vnfDescriptorId": "",
84     "flavorId": "",
85     "vnfInstanceDescription": "",
86     "extVirtualLink": "",
87     "additionalParam": ""}
88 create_vnf_resp_mapping = {
89     "VNFInstanceID": "vnfInstanceId",
90     "JobId": "jobid",}
91
92
93 @api_view(http_method_names=['POST'])
94 def instantiate_vnf(request, *args, **kwargs):
95     try:
96         logger.debug("[%s] request.data=%s", fun_name(), request.data)
97         vnfm_id = ignorcase_get(kwargs, "vnfmid")
98         ret = vnfm_get(vnfm_id)
99         if ret[0] != 0:
100             return Response(data={'error': ret[1]}, status=ret[2])
101         vnfm_info = json.JSONDecoder().decode(ret[1])
102         logger.debug("[%s] vnfm_info=%s", fun_name(), vnfm_info)
103         vnf_package_id = ignorcase_get(request.data, "vnfPackageId")
104         ret = vnfd_get(vnf_package_id)
105         if ret[0] != 0:
106             return Response(data={'error': ret[1]}, status=ret[2])
107         vnfd_info = json.JSONDecoder().decode(ret[1])
108         logger.debug("[%s] vnfd_info=%s", fun_name(), vnfd_info)
109         csar_id = ignorcase_get(vnfd_info, "csarId")
110         ret = vnfpackage_get(csar_id)
111         if ret[0] != 0:
112             return Response(data={'error': ret[1]}, status=ret[2])
113         vnf_package_info = json.JSONDecoder().decode(ret[1])
114         packageInfo = ignorcase_get(vnf_package_info, "packageInfo")
115         logger.debug("[%s] packageInfo=%s", fun_name(), packageInfo)
116         data = {}
117         data["NFVOID"] = 1
118         data["VNFMID"] = vnfm_id
119         # data["VNFD"] = ignorcase_get(packageInfo, "downloadUri")
120         # data["VNFURL"] = ignorcase_get(packageInfo, "downloadUri")
121         vnfdId = ignorcase_get(packageInfo, "vnfdId")
122         from urlparse import urlparse
123         vnfm_ip = urlparse(ignorcase_get(vnfm_info, "url")).netloc.split(':')[0]
124         if "vCSCF_NF_ZTE" == vnfdId:
125             data["VNFD"] = "ftp://VMVERSION:vmversion@" + "192.168.128.159" + ":21/CSCF"
126             data["VNFURL"] = "ftp://VMVERSION:vmversion@" + "192.168.128.159" + ":21/CSCF"
127         elif "vPCRF_NF_ZTE" == vnfdId:
128             data["VNFD"] = "ftp://VMVERSION:vmversion@" + "192.168.128.159" + ":21/PCRF"
129             data["VNFURL"] = "ftp://VMVERSION:vmversion@" + "192.168.128.159" + ":21/PCRF"
130         elif "vTAS_NF_ZTE" == vnfdId:
131             data["VNFD"] = "ftp://VMVERSION:vmversion@" + "192.168.128.159" + ":21/SSS"
132             data["VNFURL"] = "ftp://VMVERSION:vmversion@" + "192.168.128.159" + ":21/SSS"
133         elif "vSPGW_NF_ZTE" == vnfdId:
134             data["VNFD"] = "ftp://VMVERSION:vmversion@" + "192.168.237.159" + ":21/vgw31"
135             data["VNFURL"] = "ftp://VMVERSION:vmversion@" + "192.168.237.159" + ":21/vgw31"
136         else:
137             data["VNFD"] = ignorcase_get(packageInfo, "downloadUri")
138             data["VNFURL"] = ignorcase_get(packageInfo, "downloadUri")
139
140         data["extension"] = {}
141         inputs = []
142         for name, value in ignorcase_get(ignorcase_get(request.data, "additionalParam"), "inputs").items():
143             inputs.append({"name": name, "value": value})
144
145         logger.info(
146             "ignorcase_get(request.data, \"additionalParam\") = %s" % ignorcase_get(request.data, "additionalParam"))
147         data["extension"]["inputs"] = json.dumps(inputs)
148         data["extension"]["extVirtualLinks"] = ignorcase_get(
149             ignorcase_get(request.data, "additionalParam"), "extVirtualLinks")
150         data["extension"]["vnfinstancename"] = ignorcase_get(request.data, "vnfInstanceName")
151         data["extension"]["vnfid"] = data["VNFD"]
152         data["extension"]["multivim"] = 0
153         logger.debug("[%s] call_req data=%s", fun_name(), data)
154         ret = restcall.call_req(
155             base_url=ignorcase_get(vnfm_info, "url"),
156             user=ignorcase_get(vnfm_info, "userName"),
157             passwd=ignorcase_get(vnfm_info, "password"),
158             auth_type=restcall.rest_no_auth,
159             resource=create_vnf_url,
160             method='post',
161             content=json.JSONEncoder().encode(data))
162         logger.debug("[%s] call_req ret=%s", fun_name(), ret)
163         if ret[0] != 0:
164             return Response(data={'error': ret[1]}, status=ret[2])
165         resp = json.JSONDecoder().decode(ret[1])
166         resp_data = mapping_conv(create_vnf_resp_mapping, resp)
167         logger.info("[%s]resp_data=%s", fun_name(), resp_data)
168     except Exception as e:
169         logger.error("Error occurred when instantiating VNF")
170         raise e
171     return Response(data=resp_data, status=ret[2])
172
173
174 # ==================================================
175 vnf_delete_url = "v1/vnfs/%s"
176 vnf_delete_param_mapping = {
177     "terminationType": "terminationType",
178     "gracefulTerminationTimeout": "gracefulTerminationTimeout"}
179 vnf_delete_resp_mapping = {
180     "vnfInstanceId": "vnfInstanceId",
181     "JobId": "jobid"}
182
183
184 @api_view(http_method_names=['POST'])
185 def terminate_vnf(request, *args, **kwargs):
186     try:
187         logger.debug("[%s] request.data=%s", fun_name(), request.data)
188         vnfm_id = ignorcase_get(kwargs, "vnfmid")
189         ret = vnfm_get(vnfm_id)
190         if ret[0] != 0:
191             return Response(data={'error': ret[1]}, status=ret[2])
192         vnfm_info = json.JSONDecoder().decode(ret[1])
193         logger.debug("[%s] vnfm_info=%s", fun_name(), vnfm_info)
194         data = {}
195         logger.debug("[%s]req_data=%s", fun_name(), data)
196         ret = restcall.call_req(
197             base_url=ignorcase_get(vnfm_info, "url"),
198             user=ignorcase_get(vnfm_info, "userName"),
199             passwd=ignorcase_get(vnfm_info, "password"),
200             auth_type=restcall.rest_no_auth,
201             resource=vnf_delete_url % (ignorcase_get(kwargs, "vnfInstanceID")),
202             method='delete',
203             content=json.JSONEncoder().encode(data))
204         if ret[0] != 0:
205             return Response(data={'error': ret[1]}, status=ret[2])
206         resp = json.JSONDecoder().decode(ret[1])
207         resp_data = mapping_conv(vnf_delete_resp_mapping, resp)
208         logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
209     except Exception as e:
210         logger.error("Error occurred when terminating VNF")
211         raise e
212     return Response(data=resp_data, status=ret[2])
213
214
215 # ==================================================
216
217
218 vnf_detail_url = "v1/vnfs/%s"
219 vnf_detail_resp_mapping = {
220     "VNFInstanseStatus": "status",}
221
222
223 @api_view(http_method_names=['GET'])
224 def query_vnf(request, *args, **kwargs):
225     try:
226         logger.debug("[%s] request.data=%s", fun_name(), request.data)
227         vnfm_id = ignorcase_get(kwargs, "vnfmid")
228         ret = vnfm_get(vnfm_id)
229         if ret[0] != 0:
230             return Response(data={'error': ret[1]}, status=ret[2])
231         vnfm_info = json.JSONDecoder().decode(ret[1])
232         logger.debug("[%s] vnfm_info=%s", fun_name(), vnfm_info)
233         data = {}
234         ret = restcall.call_req(
235             base_url=ignorcase_get(vnfm_info, "url"),
236             user=ignorcase_get(vnfm_info, "userName"),
237             passwd=ignorcase_get(vnfm_info, "password"),
238             auth_type=restcall.rest_no_auth,
239             resource=vnf_detail_url % (ignorcase_get(kwargs, "vnfInstanceID")),
240             method='get',
241             content=json.JSONEncoder().encode(data))
242         if ret[0] != 0:
243             return Response(data={'error': ret[1]}, status=ret[2])
244         resp = json.JSONDecoder().decode(ret[1])
245         vnf_status = ignorcase_get(resp, "vnfinstancestatus")
246         resp_data = {"vnfInfo": {"vnfStatus": vnf_status}}
247         logger.debug("[%s]resp_data=%s", fun_name(), resp_data)
248     except Exception as e:
249         logger.error("Error occurred when querying VNF information.")
250         raise e
251     return Response(data=resp_data, status=ret[2])
252
253
254 # Get Operation Status
255 operation_status_url = '/v1/jobs/{jobId}?NFVOID={nfvoId}&VNFMID={vnfmId}&ResponseID={responseId}'
256 operation_status_resp_map = {
257     "JobId": "jobId",
258     "Status": "status",
259     "Progress": "progress",
260     "StatusDescription": "currentStep",
261     "ErrorCode": "errorCode",
262     "ResponseId": "responseId",
263     "ResponseHistoryList": "responseHistoryList",
264     "ResponseDescriptor": "responseDescriptor",}
265
266
267 @api_view(http_method_names=['GET'])
268 def operation_status(request, *args, **kwargs):
269     data = {}
270     try:
271         logger.debug("[%s] request.data=%s", fun_name(), request.data)
272         vnfm_id = ignorcase_get(kwargs, "vnfmid")
273         ret = vnfm_get(vnfm_id)
274         if ret[0] != 0:
275             return Response(data={'error': ret[1]}, status=ret[2])
276         vnfm_info = json.JSONDecoder().decode(ret[1])
277         logger.debug("[%s] vnfm_info=%s", fun_name(), vnfm_info)
278         ret = restcall.call_req(
279             base_url=ignorcase_get(vnfm_info, 'url'),
280             user=ignorcase_get(vnfm_info, 'userName'),
281             passwd=ignorcase_get(vnfm_info, 'password'),
282             auth_type=restcall.rest_no_auth,
283             resource=operation_status_url.format(jobId=ignorcase_get(kwargs, 'jobid'), nfvoId=1,
284                                                  vnfmId=ignorcase_get(kwargs, 'vnfmid'),
285                                                  responseId=ignorcase_get(request.GET, 'responseId')),
286             method='get',
287             content=json.JSONEncoder().encode(data))
288
289         if ret[0] != 0:
290             return Response(data={'error': ret[1]}, status=ret[2])
291         resp_data = json.JSONDecoder().decode(ret[1])
292         logger.info("[%s]resp_data=%s", fun_name(), resp_data)
293     except Exception as e:
294         logger.error("Error occurred when getting operation status information.")
295         raise e
296     return Response(data=resp_data, status=ret[2])
297
298
299 # Grant VNF Lifecycle Operation
300 grant_vnf_url = 'api/nslcm/v1/ns/grantvnf'
301 grant_vnf_param_map = {
302     "VNFMID": "",
303     "NFVOID": "",
304     "VIMID": "",
305     "ExVIMIDList": "",
306     "ExVIMID": "",
307     "Tenant": "",
308     "VNFInstanceID": "vnfInstanceId",
309     "OperationRight": "",
310     "VMList": "",
311     "VMFlavor": "",
312     "VMNumber": ""}
313
314
315 @api_view(http_method_names=['PUT'])
316 def grantvnf(request, *args, **kwargs):
317     logger.info("=====grantvnf=====")
318     try:
319         resp_data = {}
320         logger.info("req_data = %s", request.data)
321         data = mapping_conv(grant_vnf_param_map, request.data)
322         logger.info("grant_vnf_url = %s", grant_vnf_url)
323         data["vnfDescriptorId"] = ""
324         if ignorcase_get(request.data, "operationright") == 0:
325             data["lifecycleOperation"] = "Instantiate"
326             data["addresource"] = []
327             for vm in ignorcase_get(request.data, "vmlist"):
328                 for i in range(int(ignorcase_get(vm, "vmnumber"))):
329                     data["addresource"].append(
330                         {"type": "vdu",
331                          "resourceDefinitionId": i,
332                          "vdu": ignorcase_get(vm, "vmflavor"),
333                          "vimid": ignorcase_get(vm, "vimid"),
334                          "tenant": ignorcase_get(vm, "tenant")
335                          })
336
337         data["additionalparam"] = {}
338         data["additionalparam"]["vnfmid"] = ignorcase_get(request.data, "vnfmid")
339         data["additionalparam"]["vimid"] = ignorcase_get(request.data, "vimid")
340         data["additionalparam"]["tenant"] = ignorcase_get(request.data, "tenant")
341
342         logger.info("data = %s", data)
343         ret = req_by_msb(grant_vnf_url, "POST", content=json.JSONEncoder().encode(data))
344         logger.info("ret = %s", ret)
345         if ret[0] != 0:
346             return Response(data={'error': ret[1]}, status=ret[2])
347         resp = json.JSONDecoder().decode(ret[1])
348
349         resp_data['vimid'] = ignorcase_get(resp['vim'], 'vimid')
350         resp_data['tenant'] = ignorcase_get(ignorcase_get(resp['vim'], 'accessinfo'), 'tenant')
351
352         logger.info("[%s]resp_data=%s", fun_name(), resp_data)
353     except Exception as e:
354         logger.error("Error occurred in Grant VNF.")
355         raise e
356     return Response(data=resp_data, status=ret[2])
357
358
359 # Notify LCM Events
360 notify_url = 'api/nslcm/v1/ns/{vnfmid}/vnfs/{vnfInstanceId}/Notify'
361 notify_param_map = {
362     "NFVOID": "",
363     "VNFMID": "VNFMID",
364     "VIMID": "vimid",
365     "VNFInstanceID": "vnfInstanceId",
366     "TimeStamp": "",
367     "EventType": "operation",
368     "VMList": "",
369     "VMFlavor": "",
370     "VMNumber": "",
371     "VMIDlist": "",
372     "VMUUID": "",}
373
374
375 @api_view(http_method_names=['POST'])
376 def notify(request, *args, **kwargs):
377     try:
378         logger.info("[%s]req_data = %s", fun_name(), request.data)
379         data = mapping_conv(notify_param_map, request.data)
380         logger.info("[%s]data = %s", fun_name(), data)
381
382         data["status"] = "result"
383         data["jobId"] = "notMust"
384         data["affectedVnfc"] = []
385         data["affectedVl"] = []
386         data["affectedVirtualStorage"] = []
387         data["affectedCp"] = []
388
389         affectedvnfcs = ignorcase_get(ignorcase_get(request.data, "extension"), "affectedvnfc")
390         affectedvls = ignorcase_get(ignorcase_get(request.data, "extension"), "affectedvl")
391         affectedcps = ignorcase_get(ignorcase_get(request.data, "extension"), "affectedcp")
392         vnfdmodule = ignorcase_get(ignorcase_get(request.data, "extension"), "vnfdmodule")
393
394         data["vnfdmodule"] = vnfdmodule
395
396         for affectedvnfc in affectedvnfcs:
397             data["affectedVnfc"].append({
398                 "vnfcInstanceId": ignorcase_get(affectedvnfc, "vnfcinstanceid"),
399                 "vduId": ignorcase_get(affectedvnfc, "vduId"),
400                 "changeType": ignorcase_get(affectedvnfc, "changeType"),
401                 "vimid": ignorcase_get(ignorcase_get(affectedvnfc, "computeresource"), "vimid"),
402                 "vmId": ignorcase_get(ignorcase_get(affectedvnfc, "computeresource"), "resourceid"),
403                 "vmName": ignorcase_get(ignorcase_get(affectedvnfc, "computeresource"), "resourcename")
404             })
405
406         for affectedvl in affectedvls:
407             data["affectedVl"].append({
408                 "vlInstanceId": ignorcase_get(affectedvl, "virtuallinkinstanceid"),
409                 "vimid": ignorcase_get(ignorcase_get(affectedvl, "networkresource"), "vimid"),
410                 "vldid": ignorcase_get(affectedvl, "virtuallinkdescid"),
411                 "vllid": ignorcase_get(ignorcase_get(affectedvl, "networkresource"), "resourceid"),
412                 "vlName": ignorcase_get(ignorcase_get(affectedvl, "networkresource"), "resourcename")
413             })
414
415         for affectedcp in affectedcps:
416             data["affectedCp"].append(affectedcp)
417             #     {
418             #     "virtualLinkInstanceId": ignorcase_get(affectedcp, "virtuallinkinstanceid"),
419             #     "ownerId": ignorcase_get(affectedcp, "ownerId"),
420             #     "ownerType": ignorcase_get(affectedcp, "ownerType")
421             # }
422         ret = req_by_msb(notify_url.format(vnfmid=ignorcase_get(data, 'VNFMID'),
423                                            vnfInstanceId=ignorcase_get(data, 'vnfinstanceid')),
424                          "POST", content=json.JSONEncoder().encode(data))
425
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
435 nf_scaling_url = '/v1/vnfs/{vnfInstanceID}/scale'
436
437
438 @api_view(http_method_names=['POST'])
439 def scale(request, *args, **kwargs):
440     logger.info("====scale_vnf===")
441     try:
442         logger.info("request.data = %s", request.data)
443         logger.info("requested_url = %s", request.get_full_path())
444         vnfm_id = ignorcase_get(kwargs, "vnfmid")
445         nf_instance_id = ignorcase_get(kwargs, "nfInstanceId")
446         ret = vnfm_get(vnfm_id)
447         if ret[0] != 0:
448             return Response(data={'error': ret[1]}, status=ret[2])
449         vnfm_info = json.JSONDecoder().decode(ret[1])
450         scale_type = ignorcase_get(request.data, "type")
451         aspect_id = ignorcase_get(request.data, "aspectId")
452         number_of_steps = ignorcase_get(request.data, "numberOfSteps")
453         extension = ignorcase_get(request.data, "additionalParam")
454         vnfd_model = ignorcase_get(extension, "vnfdModel")
455         data = {
456             'vnfmid': vnfm_id,
457             'nfvoid': 1,
458             'scaletype': '0' if scale_type == 'SCALE_OUT' else '1',
459             'vmlist': [{'VMNumber':number_of_steps,'VMFlavor':aspect_id}],
460             'extension':''
461         }
462         '''
463         for vdu_id in get_vdus(vnfd_model, aspect_id):
464             data['vmlist'].append({
465                 "VMFlavor": vdu_id,
466                 "VMNumber": number_of_steps
467             })
468         '''
469         logger.info("data = %s", data)
470         ret = restcall.call_req(
471             base_url=ignorcase_get(vnfm_info, "url"),
472             user=ignorcase_get(vnfm_info, "userName"),
473             passwd=ignorcase_get(vnfm_info, "password"),
474             auth_type=restcall.rest_no_auth,
475             resource=nf_scaling_url.format(vnfInstanceID=nf_instance_id),
476             method='put',  # POST
477             content=json.JSONEncoder().encode(data))
478         logger.info("ret=%s", ret)
479         if ret[0] != 0:
480             return Response(data={'error':'scale error'}, status=ret[2])
481         resp_data = json.JSONDecoder().decode(ret[1])
482         jobId = resp_data["jobid"]
483         logger.info("resp_data=%s", resp_data)
484     except Exception as e:
485         logger.error("Error occurred when scaling VNF")
486         logger.error(traceback.format_exc())
487         return Response(data={'error':'scale expection'}, status='500')
488     return Response(data=resp_data, status=ret[2])
489
490
491 #@staticmethod
492 def get_vdus(nf_model, aspect_id):
493     associated_group = ''
494     members = []
495     vnf_flavours = nf_model['vnf_flavours']
496     for vnf_flaour in vnf_flavours:
497         scaling_aspects = vnf_flaour['scaling_aspects']
498         for aspect in scaling_aspects:
499             if aspect_id == aspect['id']:
500                 associated_group = aspect['associated_group']
501                 break
502     if not associated_group:
503         logger.error('Cannot find the corresponding element group')
504         raise Exception('Cannot find the corresponding element group')
505     for element_group in nf_model['element_groups']:
506         if element_group['group_id'] == associated_group:
507             members = element_group['members']
508     if not members:
509         logger.error('Cannot find the corresponding members')
510         raise Exception('Cannot find the corresponding members')
511     return members
512
513
514 @api_view(http_method_names=['GET'])
515 def samples(request, *args, **kwargs):
516     return Response(data={"status": "ok"})