Update VNF interface and IP information in A&AI
[vfc/nfvo/lcm.git] / lcm / ns_vnfs / biz / handle_notification.py
1 # Copyright 2016 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 logging
16 import traceback
17 import uuid
18
19
20 from rest_framework import status
21 from rest_framework.response import Response
22
23 from lcm.ns_vnfs.enum import INST_TYPE
24 from lcm.pub.config.config import REPORT_TO_AAI
25 from lcm.pub.database.models import (CPInstModel, NfInstModel, PortInstModel,
26                                      VLInstModel, VmInstModel, VNFCInstModel)
27 from lcm.pub.exceptions import NSLCMException, RequestException
28 from lcm.pub.msapi.aai import (create_network_aai, create_vserver_aai,
29                                delete_network_aai, delete_vserver_aai,
30                                query_network_aai, query_vserver_aai, create_l_interface_aai,
31                                create_l3_interface_ipv4_address_list_aai, query_l_interface_aai,
32                                delete_l_interface_aai)
33 from lcm.pub.msapi.extsys import get_vim_by_id, split_vim_to_owner_region
34 from lcm.pub.utils.values import ignore_case_get
35
36 logger = logging.getLogger(__name__)
37
38
39 class HandleVnfLcmOocNotification(object):
40     def __init__(self, vnfmid, vnfInstanceId, data):
41         logger.debug("[Notify LCM] vnfmid=%s, vnfInstanceId=%s, data=%s" % (vnfmid, vnfInstanceId, data))
42         self.vnfmid = vnfmid
43         self.m_vnfInstanceId = vnfInstanceId
44         self.vnf_instid = get_vnfinstid(self.m_vnfInstanceId, self.vnfmid)
45         self.operation = ignore_case_get(data, 'operation')
46         self.affectedVnfcs = ignore_case_get(data, 'affectedVnfcs')
47         self.affectedVls = ignore_case_get(data, 'affectedVirtualLinks')
48         self.affectedCps = ignore_case_get(data, 'changedExtConnectivity')
49         self.affectedVirtualStorage = ignore_case_get(data, 'affectedVirtualStorages')
50
51     def do_biz(self):
52         try:
53             self.update_Vnfc()
54             self.update_Vl()
55             self.update_Cp()
56             self.update_Storage()
57             if REPORT_TO_AAI:
58                 self.update_network_in_aai()
59                 self.update_ip_addr_in_aai()
60             logger.debug("notify lcm end")
61         except NSLCMException as e:
62             exception(e.args[0])
63         except Exception:
64             logger.error(traceback.format_exc())
65             exception('unexpected exception')
66
67     def update_Vnfc(self):
68         for vnfc in self.affectedVnfcs:
69             vnfcInstanceId = ignore_case_get(vnfc, 'id')
70             vduId = ignore_case_get(vnfc, 'vduId')
71             changeType = ignore_case_get(vnfc, 'changeType')
72             computeResource = ignore_case_get(vnfc, 'computeResource')
73             vimId = ignore_case_get(computeResource, "vimConnectionId")
74             vmId = ignore_case_get(computeResource, 'resourceId')
75             vmName = ignore_case_get(computeResource, 'resourceId')  # replaced with resouceId temporarily
76
77             if changeType == 'ADDED':
78                 VNFCInstModel(vnfcinstanceid=vnfcInstanceId, vduid=vduId,
79                               nfinstid=self.vnf_instid, vmid=vmId).save()
80                 VmInstModel(vmid=vmId, vimid=vimId, resouceid=vmId, insttype=INST_TYPE.VNF,
81                             instid=self.vnf_instid, vmname=vmName, hostid='1').save()
82                 if REPORT_TO_AAI:
83                     self.create_vserver_in_aai(vimId, vmId, vmName)
84             elif changeType == 'REMOVED':
85                 if REPORT_TO_AAI:
86                     self.delete_vserver_in_aai(vimId, vmId, vmName)
87                 VNFCInstModel.objects.filter(vnfcinstanceid=vnfcInstanceId).delete()
88             elif changeType == 'MODIFIED':
89                 VNFCInstModel.objects.filter(vnfcinstanceid=vnfcInstanceId).update(vduid=vduId,
90                                                                                    nfinstid=self.vnf_instid,
91                                                                                    vmid=vmId)
92             else:
93                 exception('affectedVnfc struct error: changeType not in {ADDED, REMOVED, MODIFIED, TEMPORARY}')
94         logger.debug("Success to update all vserver to aai.")
95
96     def update_Vl(self):
97         for vl in self.affectedVls:
98             vlInstanceId = ignore_case_get(vl, 'id')
99             vldid = ignore_case_get(vl, 'virtualLinkDescId')
100             changeType = ignore_case_get(vl, 'changeType')
101             networkResource = ignore_case_get(vl, 'networkResource')
102             resourceType = ignore_case_get(networkResource, 'vimLevelResourceType')
103             resourceId = ignore_case_get(networkResource, 'resourceId')
104             resourceName = ignore_case_get(networkResource, 'resourceId')  # replaced with resouceId temporarily
105
106             if resourceType != 'network':
107                 exception('affectedVl struct error: resourceType not euqal network')
108
109             ownerId = self.vnf_instid
110
111             if changeType == 'ADDED':
112                 VLInstModel(vlinstanceid=vlInstanceId, vldid=vldid, vlinstancename=resourceName, ownertype=0,
113                             ownerid=ownerId, relatednetworkid=resourceId, vltype=0).save()
114             elif changeType == 'REMOVED':
115                 VLInstModel.objects.filter(vlinstanceid=vlInstanceId).delete()
116             elif changeType == 'MODIFIED':
117                 VLInstModel.objects.filter(vlinstanceid=vlInstanceId)\
118                     .update(vldid=vldid, vlinstancename=resourceName, ownertype=0, ownerid=ownerId,
119                             relatednetworkid=resourceId, vltype=0)
120             else:
121                 exception('affectedVl struct error: changeType not in {ADDED, REMOVED, MODIFIED, TEMPORARY}')
122
123     def update_Cp(self):
124         for cp in self.affectedCps:
125             # virtualLinkInstanceId = ignore_case_get(cp, 'id')
126             ownertype = 0
127             ownerid = self.vnf_instid
128             for extLinkPorts in ignore_case_get(cp, 'extLinkPorts'):
129                 cpInstanceId = ignore_case_get(extLinkPorts, 'cpInstanceId')
130                 cpdId = ignore_case_get(extLinkPorts, 'id')
131                 # changeType = ignore_case_get(cp, 'changeType')
132                 relatedportId = ''
133
134                 portResource = ignore_case_get(extLinkPorts, 'resourceHandle')
135                 if portResource:
136                     vimId = ignore_case_get(portResource, 'vimConnectionId')
137                     resourceId = ignore_case_get(portResource, 'resourceId')
138                     resourceName = ignore_case_get(portResource, 'resourceProviderId')
139                     tenant = ignore_case_get(portResource, 'tenant')
140                     ipAddress = ignore_case_get(portResource, 'ipAddress')
141                     macAddress = ignore_case_get(portResource, 'macAddress')
142                     instId = ignore_case_get(portResource, 'instId')
143                     portid = ignore_case_get(portResource, 'portId')
144                     networkId = ignore_case_get(portResource, 'networkId')
145                     subnetId = ignore_case_get(portResource, 'subnetId')
146
147                     # portid = str(uuid.uuid4())
148
149                     PortInstModel(portid=portid, networkid=networkId, subnetworkid=subnetId, vimid=vimId,
150                                   resourceid=resourceId, name=resourceName, instid=instId, cpinstanceid=cpInstanceId,
151                                   bandwidth='unknown', operationalstate='active', ipaddress=ipAddress,
152                                   macaddress=macAddress,
153                                   floatipaddress='unknown', serviceipaddress='unknown', typevirtualnic='unknown',
154                                   sfcencapsulation='gre', direction='unknown', tenant=tenant).save()
155                     relatedportId = portid
156
157                 CPInstModel(cpinstanceid=cpInstanceId, cpdid=cpdId, ownertype=ownertype, ownerid=ownerid,
158                             relatedtype=2, relatedport=relatedportId, status='active').save()
159
160     def update_Storage(self):
161         pass
162
163     def del_l_interface_from_aai(self, vnf_id, l_interface_name):
164         logger.debug("Delete l_interface::delete_l_interface_in_aai[%s] in aai.", l_interface_name)
165         try:
166             l_interface_info = query_l_interface_aai(vnf_id, l_interface_name)
167             resource_version = l_interface_info.get("resource-version", '')
168             resp_data, resp_status = delete_l_interface_aai(vnf_id, l_interface_name, resource_version)
169             logger.debug("Delete l_interface[%s] from aai successfully, status: %s", l_interface_name,
170                          resp_status)
171         except RequestException:
172             logger.debug("l_interface delete exception in AAI")
173         except NSLCMException as e:
174             logger.debug("Fail to delete l_interface[%s] from aai: %s", l_interface_name, e.args[0])
175         except Exception as e:
176             logger.error("Exception occurs when delete l_interface[%s] from aai: %s", l_interface_name,
177                          e.args[0])
178             logger.error(traceback.format_exc())
179
180     def create_l_interface_aai(self, vnf_instid, l_interfaces_name):
181         logger.debug("Createl_interface::createl_interface_aai::report l_interface[%s] to aai." % l_interfaces_name)
182         try:
183
184             resp_data, resp_status = create_l_interface_aai(vnf_instid, l_interfaces_name)
185             logger.debug("Success to create l_interface[%s] to aai: [%s].", l_interfaces_name, resp_status)
186         except NSLCMException as e:
187             logger.debug(
188                 "Fail to create l_interfaces_name[%s] to aai, detail message: %s" % (l_interfaces_name, e.args[0]))
189         except:
190             logger.error(traceback.format_exc())
191
192     def create_l3_interface_ipv4_address_list_aai(self, vnf_instid, l_interfaces_name, ip):
193         logger.debug(
194             "Create l3_interface_ipv4_address_list::create_l3_interface_ipv4_address_list_aai::report "
195             "l_interface[%s]::ip_list[%s] to aai." % (l_interfaces_name, ip))
196         try:
197             resp_data, resp_status = create_l3_interface_ipv4_address_list_aai(vnf_instid, l_interfaces_name, ip)
198             logger.debug("Success to create l_interface_ip_list[%s] to aai: [%s].", ip, resp_status)
199         except NSLCMException as e:
200             logger.debug(
201                 "Fail to create ip_list[%s] to aai, detail message: %s" % (l_interfaces_name, e.args[0]))
202         except:
203             logger.error(traceback.format_exc())
204
205     def update_ip_addr_in_aai(self):
206         logger.debug("update ip addr in aai::begin to report ip to aai.")
207         try:
208             for ext in self.affectedCps:
209                 extLinkPorts = ignore_case_get(ext, 'extLinkPorts')
210                 changeType = ignore_case_get(ext, 'changeType')
211                 for res in extLinkPorts:
212                     resourceHandle = ignore_case_get(res, 'resourceHandle')
213                     l_interfaces_name = ignore_case_get(resourceHandle, 'resourceProviderId')
214                     print(l_interfaces_name)
215                     ip = ignore_case_get(resourceHandle, 'ipAddress')
216                     if changeType in ['ADDED', 'MODIFIED']:
217                         self.create_l_interface_aai(self.vnf_instid, l_interfaces_name)
218                         self.create_l3_interface_ipv4_address_list_aai(self.vnf_instid, l_interfaces_name, ip)
219                     elif changeType == 'REMOVED':
220                         self.del_l_interface_from_aai(self.vnf_instid, l_interfaces_name)
221                     else:
222                         logger.error('update ip addr struct error: changeType not in'
223                                      ' {ADDED, REMOVED, MODIFIED, TEMPORARY}')
224         except Exception as e:
225             logger.debug("Fail to update ip addr to aai, detail message: %s" % e.args[0])
226         except:
227             logger.error(traceback.format_exc())
228
229     def update_network_in_aai(self):
230         logger.debug("update_network_in_aai::begin to report network to aai.")
231         try:
232             for vl in self.affectedVls:
233                 vlInstanceId = ignore_case_get(vl, 'id')
234                 # vldid = ignore_case_get(vl, 'vldid')
235                 changeType = ignore_case_get(vl, 'changeType')
236                 networkResource = ignore_case_get(vl, 'networkResource')
237                 resourceType = ignore_case_get(networkResource, 'vimLevelResourceType')
238                 # resourceId = ignore_case_get(networkResource, 'resourceId')
239
240                 if resourceType != 'network':
241                     logger.error('affectedVl struct error: resourceType not euqal network')
242                     raise NSLCMException("affectedVl struct error: resourceType not euqal network")
243
244                 ownerId = self.vnf_instid
245
246                 if changeType in ['ADDED', 'MODIFIED']:
247                     self.create_network_and_subnet_in_aai(vlInstanceId, ownerId)
248                 elif changeType == 'REMOVED':
249                     self.delete_network_and_subnet_in_aai(vlInstanceId)
250                 else:
251                     logger.error('affectedVl struct error: changeType not in {ADDED, REMOVED, MODIFIED, TEMPORARY}')
252         except NSLCMException as e:
253             logger.debug("Fail to create internal network to aai, detail message: %s" % e.args[0])
254         except:
255             logger.error(traceback.format_exc())
256
257     def create_network_and_subnet_in_aai(self, vlInstanceId, ownerId):
258         logger.debug("CreateVls::create_network_in_aai::report network[%s] to aai." % vlInstanceId)
259         try:
260             data = {
261                 "network-id": vlInstanceId,
262                 "network-name": vlInstanceId,
263                 "is-bound-to-vpn": False,
264                 "is-provider-network": True,
265                 "is-shared-network": True,
266                 "is-external-network": True,
267                 "relationship-list": {
268                     "relationship": [
269                         {
270                             "related-to": "generic-vnf",
271                             "relationship-data": [
272                                 {
273                                     "relationship-key": "generic-vnf.vnf-id",
274                                     "relationship-value": ownerId
275                                 }
276                             ]
277                         }
278                     ]
279                 }
280             }
281             resp_data, resp_status = create_network_aai(vlInstanceId, data)
282             logger.debug("Success to create network[%s] to aai: [%s].", vlInstanceId, resp_status)
283         except NSLCMException as e:
284             logger.debug("Fail to create network[%s] to aai, detail message: %s" % (vlInstanceId, e.args[0]))
285         except:
286             logger.error(traceback.format_exc())
287
288     def delete_network_and_subnet_in_aai(self, vlInstanceId):
289         logger.debug("DeleteVls::delete_network_in_aai::delete network[%s] in aai." % vlInstanceId)
290         try:
291             # query network in aai, get resource_version
292             customer_info = query_network_aai(vlInstanceId)
293             if customer_info:
294                 resource_version = customer_info["resource-version"]
295
296                 # delete network from aai
297                 resp_data, resp_status = delete_network_aai(vlInstanceId, resource_version)
298                 logger.debug("Success to delete network[%s] from aai, resp_status: [%s]."
299                              % (vlInstanceId, resp_status))
300         except RequestException:
301             logger.debug("Network has been delted in aai")
302         except NSLCMException as e:
303             logger.debug("Fail to delete network[%s] to aai, detail message: %s" % (vlInstanceId, e.args[0]))
304         except:
305             logger.error(traceback.format_exc())
306
307     def create_vserver_in_aai(self, vim_id, vserver_id, vserver_name):
308         logger.debug("NotifyLcm::create_vserver_in_aai::report vserver instance to aai.")
309         try:
310             cloud_owner, cloud_region_id = split_vim_to_owner_region(vim_id)
311
312             # query vim_info from aai
313             vim_info = get_vim_by_id({"cloud_owner": cloud_owner, 'cloud_regionid': cloud_region_id})
314             tenant_id = vim_info["tenantId"]
315             data = {
316                 "vserver-id": vserver_id,
317                 "vserver-name": vserver_name,
318                 "prov-status": "ACTIVE",
319                 "vserver-selflink": "",
320                 "in-maint": True,
321                 "is-closed-loop-disabled": False,
322                 "relationship-list": {
323                     "relationship": [
324                         {
325                             "related-to": "generic-vnf",
326                             "relationship-data": [
327                                 {
328                                     "relationship-key": "generic-vnf.vnf-id",
329                                     "relationship-value": self.vnf_instid
330                                 }
331                             ]
332                         }
333                     ]
334                 }
335             }
336
337             # create vserver instance in aai
338             resp_data, resp_status = create_vserver_aai(cloud_owner, cloud_region_id, tenant_id, vserver_id, data)
339             logger.debug("Success to create vserver[%s] to aai, vnf instance=[%s], resp_status: [%s]."
340                          % (vserver_id, self.vnf_instid, resp_status))
341         except NSLCMException as e:
342             logger.debug("Fail to create vserver to aai, vnf instance=[%s], detail message: %s"
343                          % (self.vnf_instid, e.args[0]))
344         except:
345             logger.error(traceback.format_exc())
346
347     def delete_vserver_in_aai(self, vim_id, vserver_id, vserver_name):
348         logger.debug("delete_vserver_in_aai start![%s]", vserver_name)
349         try:
350             cloud_owner, cloud_region_id = split_vim_to_owner_region(vim_id)
351             # query vim_info from aai, get tenant
352             vim_info = get_vim_by_id({"cloud_owner": cloud_owner, 'cloud_regionid': cloud_region_id})
353             tenant_id = vim_info["tenantId"]
354
355             # query vserver instance in aai, get resource_version
356             vserver_info = query_vserver_aai(cloud_owner, cloud_region_id, tenant_id, vserver_id)
357             if vserver_info:
358                 resource_version = vserver_info["resource-version"]
359
360                 # delete vserver instance from aai
361                 resp_data, resp_status = delete_vserver_aai(cloud_owner, cloud_region_id,
362                                                             tenant_id, vserver_id, resource_version)
363                 logger.debug(
364                     "Success to delete vserver instance[%s] from aai, resp_status: [%s]." %
365                     (vserver_id, resp_status))
366                 logger.debug("delete_vserver_in_aai end!")
367         except RequestException:
368             logger.debug("Vserver has been deleted from aai")
369         except NSLCMException as e:
370             logger.debug("Fail to delete vserver from aai, detail message: %s" % e.args[0])
371         except:
372             logger.error(traceback.format_exc())
373
374
375 class HandleVnfIdentifierCreationNotification(object):
376     def __init__(self, vnfmId, vnfInstanceId, data):
377         logger.debug("[Notify VNF Identifier Creation] vnfmId=%s, vnfInstanceId=%s, data=%s" % (vnfmId, vnfInstanceId, data))
378         self.vnfm_id = vnfmId
379         self.m_vnf_instance_id = vnfInstanceId
380         self.time_stamp = ignore_case_get(data, 'timeStamp')
381         # TODO: self.subscription_id = ignore_case_get(data, 'subscriptionId')
382         # TODO: self._links = ignore_case_get(data, '_links')
383
384     def do_biz(self):
385         try:
386             NfInstModel(
387                 nfinstid=str(uuid.uuid4()),
388                 mnfinstid=self.m_vnf_instance_id,
389                 vnfm_inst_id=self.vnfm_id,
390                 create_time=self.time_stamp
391             ).save()
392             logger.debug("Notify VNF identifier creation end.")
393         except Exception:
394             logger.error(traceback.format_exc())
395             exception('unexpected exception')
396
397
398 class HandleVnfIdentifierDeletionNotification(object):
399     def __init__(self, vnfmId, vnfInstanceId, data):
400         logger.debug("[Notify VNF Identifier Deletion] vnfmId=%s, vnfInstanceId=%s, data=%s" % (vnfmId, vnfInstanceId, data))
401         self.vnfm_id = vnfmId
402         self.m_vnf_instance_id = vnfInstanceId
403         self.vnf_instance_id = get_vnfinstid(self.m_vnf_instance_id, self.vnfm_id)
404         self.time_stamp = ignore_case_get(data, 'timeStamp')
405         # TODO: self.subscription_id = ignore_case_get(data, 'subscriptionId')
406         # TODO: self._links = ignore_case_get(data, '_links')
407
408     def do_biz(self):
409         try:
410             nf_insts = NfInstModel.objects.filter(
411                 mnfinstid=self.m_vnf_instance_id, vnfm_inst_id=self.vnfm_id)
412             if nf_insts.exists():
413                 nf_insts.delete()
414             logger.debug("Notify VNF identifier deletion end.")
415         except Exception:
416             logger.error(traceback.format_exc())
417             exception('unexpected exception')
418
419
420 def get_vnfinstid(mnfinstid, vnfm_inst_id):
421     logger.debug("vnfinstid in vnfm is:%s,vnfmid is:%s", mnfinstid, vnfm_inst_id)
422     logger.debug("mnfinstid=%s, vnfm_inst_id=%s", mnfinstid, vnfm_inst_id)
423     nfinst = NfInstModel.objects.filter(mnfinstid=mnfinstid, vnfm_inst_id=vnfm_inst_id).first()
424     if nfinst:
425         return nfinst.nfinstid
426     raise NSLCMException("vnfinstid not exist")
427
428
429 def exception(error_msg):
430     logger.error('Notify Lcm failed, detail message: %s' % error_msg)
431     return Response(data={'error': '%s' % error_msg}, status=status.HTTP_409_CONFLICT)