update version of lcm
[vfc/nfvo/lcm.git] / lcm / ns / biz / ns_terminate.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 import json
15 import logging
16 import threading
17 import time
18 import traceback
19
20 from lcm.pub.database.models import NSInstModel, VLInstModel, FPInstModel, NfInstModel
21 from lcm.pub.exceptions import NSLCMException
22 from lcm.pub.msapi.nslcm import call_from_ns_cancel_resource
23 from lcm.pub.utils.jobutil import JobUtil
24 from lcm.pub.utils.values import ignore_case_get
25 from lcm.pub.utils import restcall
26 from lcm.ns.const import OWNER_TYPE
27
28 JOB_ERROR = 255
29
30 logger = logging.getLogger(__name__)
31
32
33 class TerminateNsService(threading.Thread):
34     def __init__(self, ns_inst_id, terminate_type, terminate_timeout, job_id):
35         threading.Thread.__init__(self)
36         self.ns_inst_id = ns_inst_id
37         self.terminate_type = terminate_type
38         self.terminate_timeout = terminate_timeout
39         self.job_id = job_id
40
41     def run(self):
42         try:
43             if not NSInstModel.objects.filter(id=self.ns_inst_id):
44                 JobUtil.add_job_status(self.job_id, 100, "Need not terminate.", '')
45                 return
46             JobUtil.add_job_status(self.job_id, 10, "Starting terminate...", '')
47
48             self.cancel_sfc_list()
49             self.cancel_vnf_list()
50             self.cancel_vl_list()
51
52             NSInstModel.objects.filter(id=self.ns_inst_id).update(status='null')
53             JobUtil.add_job_status(self.job_id, 100, "ns terminate ends.", '')
54         except NSLCMException as e:
55             JobUtil.add_job_status(self.job_id, JOB_ERROR, e.message)
56         except Exception as ex:
57             logger.error(ex.message)
58             logger.error(traceback.format_exc())
59             JobUtil.add_job_status(self.job_id, JOB_ERROR, "ns terminate fail.")
60
61     def cancel_vl_list(self):
62         array_vlinst = VLInstModel.objects.filter(ownertype=OWNER_TYPE.NS, ownerid=self.ns_inst_id)
63         if not array_vlinst:
64             logger.info("[cancel_vl_list] no vlinst attatch to ns_inst_id: %s" % self.ns_inst_id)
65             return
66         step_progress = 20 / len(array_vlinst)
67         cur_progress = 70
68         for vlinst in array_vlinst:
69             delete_result = "failed"
70             cur_progress += step_progress
71             try:
72                 ret = call_from_ns_cancel_resource('vl', vlinst.vlinstanceid)
73                 if ret[0] == 0:
74                     result = json.JSONDecoder().decode(ret[1]).get("result", "")
75                     if str(result) == '0':
76                         delete_result = "success"
77             except Exception as e:
78                 logger.error("[cancel_vl_list] error[%s]!" % e.message)
79                 logger.error(traceback.format_exc())
80             job_msg = "Delete vlinst:[%s] %s." % (vlinst.vlinstanceid, delete_result)
81             JobUtil.add_job_status(self.job_id, cur_progress, job_msg)
82
83     def cancel_sfc_list(self):
84         array_sfcinst = FPInstModel.objects.filter(nsinstid=self.ns_inst_id)
85         if not array_sfcinst:
86             logger.info("[cancel_sfc_list] no sfcinst attatch to ns_inst_id: %s" % self.ns_inst_id)
87             return
88         step_progress = 20 / len(array_sfcinst)
89         cur_progress = 30
90         for sfcinst in array_sfcinst:
91             cur_progress += step_progress
92             delete_result = "failed"
93             try:
94                 ret = call_from_ns_cancel_resource('sfc', sfcinst.sfcid)
95                 if ret[0] == 0:
96                     result = json.JSONDecoder().decode(ret[1]).get("result", "")
97                     if str(result) == '0':
98                         delete_result = "success"
99             except Exception as e:
100                 logger.error("[cancel_sfc_list] error[%s]!" % e.message)
101                 logger.error(traceback.format_exc())
102             job_msg = "Delete sfcinst:[%s] %s." % (sfcinst.sfcid, delete_result)
103             JobUtil.add_job_status(self.job_id, cur_progress, job_msg)
104
105     def cancel_vnf_list(self):
106         array_vnfinst = NfInstModel.objects.filter(ns_inst_id=self.ns_inst_id)
107         if not array_vnfinst:
108             logger.info("[cancel_vnf_list] no vnfinst attatch to ns_inst_id: %s" % self.ns_inst_id)
109             return
110         step_progress = 20 / len(array_vnfinst)
111         cur_progress = 50
112         for vnfinst in array_vnfinst:
113             cur_progress += step_progress
114             delete_result = "failed"
115             try:
116                 if self.delete_vnf(vnfinst.nfinstid):
117                     delete_result = "success"
118             except Exception as e:
119                 logger.error("[cancel_vnf_list] error[%s]!" % e.message)
120                 logger.error(traceback.format_exc())
121             job_msg = "Delete vnfinst:[%s] %s." % (vnfinst.nfinstid, delete_result)
122             JobUtil.add_job_status(self.job_id, cur_progress, job_msg)
123
124     def delete_vnf(self, nf_instid):
125         ret = call_from_ns_cancel_resource('vnf', nf_instid)
126         if ret[0] != 0:
127             return False
128         job_info = json.JSONDecoder().decode(ret[1])
129         vnf_job_id = ignore_case_get(job_info, "jobid")
130         return self.wait_delete_vnf_job_finish(vnf_job_id)
131
132     def wait_delete_vnf_job_finish(self, vnf_job_id):
133         count = 0
134         retry_count = 400
135         interval_second = 2
136         response_id, new_response_id = 0, 0
137         job_end_normal, job_timeout = False, True
138         while count < retry_count:
139             count = count + 1
140             time.sleep(interval_second)
141             uri = "/api/nslcm/v1/jobs/%s?responseId=%s" % (vnf_job_id, response_id)
142             ret = restcall.req_by_msb(uri, "GET")
143             if ret[0] != 0:
144                 logger.error("Failed to query job: %s:%s", ret[2], ret[1])
145                 continue
146             job_result = json.JSONDecoder().decode(ret[1])
147             if "responseDescriptor" not in job_result:
148                 logger.error("Job(%s) does not exist.", vnf_job_id)
149                 continue
150             progress = job_result["responseDescriptor"]["progress"]
151             new_response_id = job_result["responseDescriptor"]["responseId"]
152             job_desc = job_result["responseDescriptor"]["statusDescription"]
153             if new_response_id != response_id:
154                 logger.debug("%s:%s:%s", progress, new_response_id, job_desc)
155                 response_id = new_response_id
156                 count = 0
157             if progress == JOB_ERROR:
158                 job_timeout = False
159                 logger.error("Job(%s) failed: %s", vnf_job_id, job_desc)
160                 break
161             elif progress == 100:
162                 job_end_normal, job_timeout = True, False
163                 logger.info("Job(%s) ended normally", vnf_job_id)
164                 break
165         if job_timeout:
166             logger.error("Job(%s) timeout", vnf_job_id)
167         return job_end_normal