Fix bug for delete subscription in ns termination
[vfc/nfvo/lcm.git] / lcm / ns_vnfs / biz / terminate_nfs.py
1 # Copyright 2016-2018 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 json
16 import logging
17 import threading
18 import traceback
19
20 from lcm.pub.config.config import REPORT_TO_AAI
21 from lcm.pub.database.models import NfInstModel, VmInstModel, OOFDataModel
22 from lcm.pub.exceptions import NSLCMException
23 from lcm.pub.msapi import resmgr
24 from lcm.pub.msapi.aai import query_vnf_aai, delete_vnf_aai, query_vserver_aai, delete_vserver_aai
25 from lcm.pub.msapi.extsys import split_vim_to_owner_region, get_vim_by_id
26 from lcm.pub.msapi.vnfmdriver import send_nf_terminate_request
27 from lcm.pub.utils.jobutil import JobUtil
28 from lcm.jobs.enum import JOB_MODEL_STATUS
29 from lcm.pub.utils.values import ignore_case_get
30 from lcm.ns_vnfs.const import NFVO_VNF_INST_TIMEOUT_SECOND
31 from lcm.ns_vnfs.enum import VNF_STATUS, INST_TYPE
32 from lcm.ns_vnfs.biz.wait_job import wait_job_finish
33 from lcm.ns_vnfs.biz.subscribe import SubscriptionDeletion
34
35 logger = logging.getLogger(__name__)
36
37
38 class TerminateVnfs(threading.Thread):
39     def __init__(self, data, vnf_inst_id, job_id):
40         threading.Thread.__init__(self)
41         self.vnf_inst_id = vnf_inst_id
42         self.job_id = job_id
43         self.vnfm_inst_id = ''
44         self.vnf_uuid = ''
45         self.vnfm_job_id = ''
46         self.terminationType = data['terminationType']
47         self.gracefulTerminationTimeout = data['gracefulTerminationTimeout']
48         if not self.gracefulTerminationTimeout:
49             self.gracefulTerminationTimeout = 120
50         else:
51             self.gracefulTerminationTimeout = int(self.gracefulTerminationTimeout)
52
53         self.initdata()
54
55     def run(self):
56         try:
57             self.check_nf_valid()
58             self.send_nf_terminate_to_vnfmDriver()
59             self.wait_vnfm_job_finish()
60             self.send_terminate_vnf_to_resMgr()
61             if REPORT_TO_AAI:
62                 self.delete_vserver_in_aai()
63                 self.delete_vnf_in_aai()
64             self.delete_subscription()
65             self.delete_data_from_db()
66         except NSLCMException as e:
67             self.set_job_err(e.args[0])
68         except Exception as ex:
69             logger.error(traceback.format_exc())
70             self.set_job_err(ex.args[0])
71
72     def set_vnf_status(self, vnf_inst_info):
73         vnf_status = vnf_inst_info.status
74         if (vnf_status == VNF_STATUS.TERMINATING):
75             logger.info('[VNF terminate] VNF is dealing by other application,try again later.')
76             raise NSLCMException('[VNF terminate] VNF is dealing by other application,try again later.')
77         else:
78             vnf_inst_info.status = VNF_STATUS.TERMINATING
79             vnf_inst_info.save()
80
81     def get_vnf_inst(self):
82         vnf_inst = NfInstModel.objects.filter(nfinstid=self.vnf_inst_id)
83         if not vnf_inst.exists():
84             logger.warning('[VNF terminate] Vnf terminate [%s] does not exist.' % self.vnf_inst_id)
85             return None
86         return vnf_inst[0]
87
88     def add_progress(self, progress, status_decs, error_code=""):
89         JobUtil.add_job_status(self.job_id, progress, status_decs, error_code)
90
91     def initdata(self):
92         vnf_inst_info = self.get_vnf_inst()
93         if not vnf_inst_info:
94             self.add_progress(100, "TERM_VNF_NOT_EXIST_SUCCESS", "finished")
95             return None
96         self.add_progress(2, "GET_VNF_INST_SUCCESS")
97         self.vnfm_inst_id = vnf_inst_info.vnfm_inst_id
98         self.vnf_uuid = vnf_inst_info.mnfinstid
99         if not self.vnf_uuid:
100             self.add_progress(100, "TERM_VNF_NOT_EXIST_SUCCESS", "finished")
101
102     def check_nf_valid(self):
103         vnf_inst = NfInstModel.objects.filter(nfinstid=self.vnf_inst_id)
104         if not vnf_inst.exists():
105             logger.warning('[VNF terminate] Vnf instance [%s] is not exist.' % self.vnf_inst_id)
106             raise NSLCMException('[VNF terminate] Vnf instance is not exist.')
107         if not vnf_inst:
108             self.add_progress(100, "TERM_VNF_NOT_EXIST_SUCCESS", "finished")
109             raise NSLCMException('[VNF terminate] Vnf instance is not exist.')
110         self.set_vnf_status(vnf_inst[0])
111
112     def set_job_err(self, error_msg):
113         logger.error('VNF Terminate failed, detail message: %s' % error_msg)
114         NfInstModel.objects.filter(nfinstid=self.vnf_inst_id).update(status=VNF_STATUS.FAILED)
115         JobUtil.add_job_status(self.job_id, 255, 'VNF Terminate failed, detail message: %s' % error_msg, 0)
116
117     def send_nf_terminate_to_vnfmDriver(self):
118         req_param = json.JSONEncoder().encode({
119             'terminationType': self.terminationType,
120             'gracefulTerminationTimeout': self.gracefulTerminationTimeout})
121         rsp = send_nf_terminate_request(self.vnfm_inst_id, self.vnf_uuid, req_param)
122         self.vnfm_job_id = ignore_case_get(rsp, 'jobId')
123
124     def send_terminate_vnf_to_resMgr(self):
125         resmgr.terminate_vnf(self.vnf_inst_id)
126
127     def wait_vnfm_job_finish(self):
128         if not self.vnfm_job_id:
129             logger.warn("No Job, need not wait")
130             return
131         ret = wait_job_finish(vnfm_id=self.vnfm_inst_id,
132                               vnfo_job_id=self.job_id,
133                               vnfm_job_id=self.vnfm_job_id,
134                               progress_range=[10, 90],
135                               timeout=NFVO_VNF_INST_TIMEOUT_SECOND)
136
137         if ret != JOB_MODEL_STATUS.FINISHED:
138             logger.error('VNF terminate failed on VNFM side.')
139             raise NSLCMException('VNF terminate failed on VNFM side.')
140
141     def delete_subscription(self):
142         try:
143             SubscriptionDeletion(self.vnfm_inst_id, self.vnf_uuid).do_biz()
144         except Exception as e:
145             logger.error("delete_subscription failed: %s", e.args[0])
146
147     def delete_data_from_db(self):
148         NfInstModel.objects.filter(nfinstid=self.vnf_inst_id).delete()
149         VmInstModel.objects.filter(instid=self.vnf_inst_id).delete()
150         OOFDataModel.objects.filter(service_resource_id=self.vnf_inst_id).delete()
151         JobUtil.add_job_status(self.job_id, 100, 'vnf terminate success', 0)
152
153     def delete_vnf_in_aai(self):
154         logger.debug("TerminateVnfs::delete_vnf_in_aai::delete vnf instance[%s] in aai." % self.vnf_inst_id)
155         try:
156             # query vnf instance in aai, get resource_version
157             customer_info = query_vnf_aai(self.vnf_inst_id)
158             resource_version = customer_info["resource-version"]
159
160             # delete vnf instance from aai
161             resp_data, resp_status = delete_vnf_aai(self.vnf_inst_id, resource_version)
162             logger.debug(
163                 "Success to delete vnf[%s] from aai, resp_status: [%s]." % (self.vnf_inst_id, resp_status))
164         except NSLCMException as e:
165             logger.debug("Fail to delete vnf from aai[%s], detail message: %s" % (self.vnf_inst_id, e.args[0]))
166         except:
167             logger.error(traceback.format_exc())
168
169     def delete_vserver_in_aai(self):
170         logger.debug("delete_vserver_in_aai start!")
171         try:
172             vm_inst_infos = VmInstModel.objects.filter(insttype=INST_TYPE.VNF, instid=self.vnf_inst_id)
173             for vm_inst_info in vm_inst_infos:
174                 vserver_id = vm_inst_info.resouceid
175                 vim_id = vm_inst_info.vimid
176                 cloud_owner, cloud_region_id = split_vim_to_owner_region(vim_id)
177                 # query vim_info from aai, get tenant
178                 vim_info = get_vim_by_id({"cloud_owner": cloud_owner, 'cloud_regionid': cloud_region_id})
179                 tenant_id = vim_info["tenantId"]
180
181                 # query vserver instance in aai, get resource_version
182                 vserver_info = query_vserver_aai(cloud_owner, cloud_region_id, tenant_id, vserver_id)
183                 resource_version = vserver_info["resource-version"]
184
185                 # delete vserver instance from aai
186                 resp_data, resp_status = delete_vserver_aai(cloud_owner, cloud_region_id,
187                                                             tenant_id, vserver_id, resource_version)
188                 logger.debug(
189                     "Success to delete vserver instance[%s] from aai, resp_status: [%s]." %
190                     (vserver_id, resp_status))
191             logger.debug("delete_vserver_in_aai end!")
192         except NSLCMException as e:
193             logger.debug("Fail to delete vserver from aai, detail message: %s" % e.args[0])
194         except:
195             logger.error(traceback.format_exc())