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