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