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