move heal test json from code to indepandent file
[vfc/nfvo/lcm.git] / lcm / ns / biz / ns_heal.py
1 # Copyright 2017 Intel 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 datetime
16 import logging
17 import threading
18 import time
19 import traceback
20
21 from lcm.ns.enum import NS_INST_STATUS
22 from lcm.pub.database.models import JobModel, NSInstModel, NfInstModel, VNFCInstModel, VmInstModel
23 from lcm.pub.exceptions import NSLCMException
24 from lcm.pub.utils.jobutil import JobUtil, JOB_MODEL_STATUS
25 from lcm.pub.utils.values import ignore_case_get
26 from lcm.ns_vnfs.biz.heal_vnfs import NFHealService
27 from lcm.ns.biz.ns_lcm_op_occ import NsLcmOpOcc
28
29 JOB_ERROR = 255
30 logger = logging.getLogger(__name__)
31
32
33 class NSHealService(threading.Thread):
34     def __init__(self, ns_instance_id, request_data, job_id):
35         super(NSHealService, self).__init__()
36         self.ns_instance_id = ns_instance_id
37         self.request_data = request_data
38         self.job_id = job_id
39         self.occ_id = NsLcmOpOcc.create(ns_instance_id, "HEAL", "PROCESSING", False, request_data)
40         self.heal_vnf_data = ''
41         self.heal_ns_data = ''
42
43     def run(self):
44         try:
45             self.do_biz()
46         except NSLCMException as e:
47             JobUtil.add_job_status(self.job_id, JOB_ERROR, e.message)
48             NsLcmOpOcc.update(self.occ_id, operationState="FAILED", error=e.message)
49         except Exception as e:
50             logger.error(traceback.format_exc())
51             JobUtil.add_job_status(self.job_id, JOB_ERROR, 'ns heal fail')
52             NsLcmOpOcc.update(self.occ_id, operationState="FAILED", error=e.message)
53
54     def do_biz(self):
55         self.update_job(1, desc='ns heal start')
56         self.get_and_check_params()
57         self.update_ns_status(NS_INST_STATUS.HEALING)
58         self.do_heal()
59         self.update_ns_status(NS_INST_STATUS.ACTIVE)
60         self.update_job(100, desc='ns heal success')
61         NsLcmOpOcc.update(self.occ_id, "COMPLETED")
62
63     def get_and_check_params(self):
64         ns_info = NSInstModel.objects.filter(id=self.ns_instance_id)
65         if not ns_info:
66             logger.error('NS [id=%s] does not exist' % self.ns_instance_id)
67             raise NSLCMException(
68                 'NS [id=%s] does not exist' % self.ns_instance_id)
69         self.heal_ns_data = ignore_case_get(self.request_data, 'healNsData')
70         self.heal_vnf_data = ignore_case_get(self.request_data, 'healVnfData')
71         if self.heal_ns_data and self.heal_vnf_data:
72             logger.error('healNsData and healVnfData can not exist together')
73             raise NSLCMException(
74                 'healNsData and healVnfData can not exist together')
75         if not self.heal_ns_data and not self.heal_vnf_data:
76             logger.error(
77                 'healNsData and healVnfData parameters does not exist or value is incorrect.')
78             raise NSLCMException(
79                 'healNsData and healVnfData parameters does not exist or value is incorrect.')
80
81     def do_heal(self):
82         if self.heal_vnf_data:
83             vnf_heal_params = self.prepare_vnf_heal_params(self.heal_vnf_data)
84             status = self.do_vnf_or_ns_heal(vnf_heal_params, 15)
85             if status is JOB_MODEL_STATUS.FINISHED:
86                 logger.info('nf[%s] heal handle end' % vnf_heal_params.get('vnfInstanceId'))
87                 self.update_job(90, desc='nf[%s] heal handle end' % vnf_heal_params.get('vnfInstanceId'))
88             else:
89                 logger.error('nf heal failed')
90                 raise NSLCMException('nf heal failed')
91         else:
92             ns_heal_params = self.prepare_ns_heal_params(self.heal_ns_data)
93             for ns_heal_param in ns_heal_params:
94                 status = self.do_vnf_or_ns_heal(ns_heal_param, 15)
95                 if status is JOB_MODEL_STATUS.FINISHED:
96                     logger.info('nf[%s] heal handle end' % ns_heal_param.get('vnfInstanceId'))
97                     self.update_job(90, desc='nf[%s] heal handle end' % ns_heal_param.get('vnfInstanceId'))
98                 else:
99                     logger.error('nf heal failed')
100                     raise NSLCMException('nf heal failed')
101
102     def do_vnf_or_ns_heal(self, heal_param, progress):
103         instance_id = heal_param.get('vnfInstanceId')
104         nf_service = NFHealService(instance_id, heal_param)
105         nf_service.start()
106         self.update_job(
107             progress, desc='nf[%s] heal handle start' % instance_id)
108         status = self.wait_job_finish(nf_service.job_id)
109         return status
110
111     def prepare_ns_heal_params(self, ns_data):
112         degree_healing = ignore_case_get(ns_data, 'degreeHealing')
113         if not degree_healing:
114             logger.error('degreeHealing does not exist.')
115             raise NSLCMException('degreeHealing does not exist.')
116         ns_instance_id = self.ns_instance_id
117         cause = 'vm is down'
118         # action = ignore_case_get(ns_data, 'actionsHealing')
119         if degree_healing == "HEAL_RESTORE":
120             ns_inst_infos = NfInstModel.objects.filter(ns_inst_id=self.ns_instance_id)
121             if not ns_inst_infos.exists():
122                 raise NSLCMException('NSInsts(%s) does not exist' % self.ns_instance_id)
123             result_arr = []
124             for ns_inst_info in ns_inst_infos:
125                 vnfc_insts = VNFCInstModel.objects.filter(nfinstid=ns_inst_info.nfinstid)
126                 # If a condition is not met, will it all terminate?
127                 if not vnfc_insts.exists():
128                     raise NSLCMException('vnfcinsts(%s) does not exist' % ns_inst_info.nfinstid)
129                 for vnfc_inst in vnfc_insts:
130                     vm_id = vnfc_inst.vmid
131                     vdu_id = vnfc_inst.vduid
132                     vm_inst_info = VmInstModel.objects.filter(vmid=vm_id)
133                     if not vm_inst_info.exists():
134                         raise NSLCMException('vminstinfo(%s) does not exist' % vm_id)
135                     vm_name = vm_inst_info[0].vmname
136
137                     result = {
138                         "vnfInstanceId": ns_instance_id,
139                         "cause": cause,
140                         "additionalParams": {
141                             "action": "restartvm",
142                             "actionvminfo": {
143                                 "vmid": vm_id,
144                                 "vduid": vdu_id,
145                                 "vmname": vm_name
146                             }
147                         }
148                     }
149                     result_arr.append(result)
150             return result_arr
151         else:
152             logger.error(
153                 'The degree of healing dose not exist or value is incorrect.')
154             raise NSLCMException(
155                 'The degree of healing dose not exist or value is incorrect.')
156
157     def prepare_vnf_heal_params(self, vnf_data):
158         vnf_instance_id = ignore_case_get(vnf_data, 'vnfInstanceId')
159         if not vnf_instance_id:
160             logger.error('vnfinstanceid does not exist or value is incorrect.')
161             raise NSLCMException(
162                 'vnfinstanceid does not exist or value is incorrect.')
163         cause = ignore_case_get(vnf_data, 'cause')
164         additional_params = ignore_case_get(vnf_data, 'additionalParams')
165         action = ignore_case_get(additional_params, 'action')
166         action_vm_info = ignore_case_get(additional_params, 'actionvminfo')
167         vm_id = ignore_case_get(action_vm_info, 'vmid')
168         vdu_id = ignore_case_get(action_vm_info, 'vduid')
169         vm_name = ignore_case_get(action_vm_info, 'vmname')
170
171         result = {
172             "vnfInstanceId": vnf_instance_id,
173             "cause": cause,
174             "additionalParams": {
175                 "action": action,
176                 "actionvminfo": {
177                     "vmid": vm_id,
178                     "vduid": vdu_id,
179                     "vmname": vm_name
180                 }
181             }
182         }
183         return result
184
185     @staticmethod
186     def wait_job_finish(sub_job_id, timeout=3600):
187         query_interval = 2
188         start_time = end_time = datetime.datetime.now()
189         while (end_time - start_time).seconds < timeout:
190             job_result = JobModel.objects.get(jobid=sub_job_id)
191             time.sleep(query_interval)
192             end_time = datetime.datetime.now()
193             if job_result.progress == 100:
194                 return JOB_MODEL_STATUS.FINISHED
195             elif job_result.progress > 100:
196                 return JOB_MODEL_STATUS.ERROR
197             else:
198                 continue
199         return JOB_MODEL_STATUS.TIMEOUT
200
201     def update_job(self, progress, desc=''):
202         JobUtil.add_job_status(self.job_id, progress, desc)
203
204     def update_ns_status(self, status):
205         NSInstModel.objects.filter(
206             id=self.ns_instance_id).update(status=status)