bf8e34a08f4d12b6b4b9313e9cb0411ea184526a
[vfc/gvnfm/vnflcm.git] / lcm / lcm / nf / biz / heal_vnf.py
1 # Copyright (C) 2018 Verizon. All Rights Reserved.
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 json
16 import logging
17 import traceback
18 from threading import Thread
19
20 from lcm.pub.database.models import NfInstModel, VmInstModel
21 from lcm.pub.exceptions import NFLCMException
22 from lcm.pub.msapi.gvnfmdriver import notify_lcm_to_nfvo, prepare_notification_data
23 from lcm.pub.utils.jobutil import JobUtil
24 from lcm.pub.utils.timeutil import now_time
25 from lcm.pub.utils.values import ignore_case_get
26 from lcm.pub.vimapi import adaptor
27 from lcm.nf.biz.grant_vnf import grant_resource
28 from lcm.nf.const import VNF_STATUS, GRANT_TYPE, HEAL_ACTION_TYPE, CHANGE_TYPE, OPERATION_TYPE
29 from lcm.nf.biz import common
30
31 logger = logging.getLogger(__name__)
32
33
34 class HealVnf(Thread):
35     def __init__(self, data, nf_inst_id, job_id):
36         super(HealVnf, self).__init__()
37         self.data = data
38         self.nf_inst_id = nf_inst_id
39         self.job_id = job_id
40         self.affectedvm = ignore_case_get(ignore_case_get(self.data, "additionalParams"), "affectedvm")
41         # TODO: Check if we could move the action param into the list of affectedvm structure
42         self.action = ignore_case_get(ignore_case_get(self.data, "additionalParams"), "action")
43         self.grant_type = ""
44         if self.action == HEAL_ACTION_TYPE.START:
45             self.grant_type = GRANT_TYPE.HEAL_CREATE
46         elif self.action == HEAL_ACTION_TYPE.RESTART:
47             self.grant_type = GRANT_TYPE.HEAL_RESTART
48
49     def run(self):
50         try:
51             self.heal_pre()
52             self.apply_grant()
53             self.heal_resource()
54             JobUtil.add_job_status(self.job_id, 100, "Heal Vnf success.")
55             NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status='INSTANTIATED', lastuptime=now_time())
56             self.lcm_notify()
57         except NFLCMException as e:
58             logger.error(e.message)
59             self.vnf_heal_failed_handle(e.message)
60         except Exception as e:
61             logger.error(e.message)
62             self.vnf_heal_failed_handle(traceback.format_exc())
63
64     def heal_pre(self):
65         if self.action not in (HEAL_ACTION_TYPE.START, HEAL_ACTION_TYPE.RESTART):
66             raise NFLCMException("Action type in Request in invalid. Should be %s or %s" % (HEAL_ACTION_TYPE.START, HEAL_ACTION_TYPE.RESTART))
67
68         self.vm_id = ignore_case_get(self.affectedvm, "vmid")
69         self.vdu_id = ignore_case_get(self.affectedvm, "vduid")
70         self.vm_name = ignore_case_get(self.affectedvm, "vmname")
71         if not (self.vm_id and self.vdu_id and self.vm_name):
72             raise NFLCMException("VM identifiers is not present in request.")
73
74         self.vnf_insts = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
75         self.vnfd_info = json.loads(self.vnf_insts[0].vnfd_model)
76
77     def apply_grant(self):
78         if self.action == HEAL_ACTION_TYPE.RESTART:
79             self.vdu = VmInstModel.objects.filter(instid=self.nf_inst_id, is_predefined=1, vmid=self.vm_id, vmname=self.vm_name)
80             if not self.vdu:
81                 raise NFLCMException("VNF Vm does not exist.")
82             self.vimid = self.vdu[0].vimid
83             self.tenant = self.vdu[0].tenant
84         elif self.action == HEAL_ACTION_TYPE.START:
85             vdus = ignore_case_get(self.vnfd_info, "vdus")
86             self.vdu = [elem for elem in vdus if ignore_case_get(elem, "vdu_id") == self.vdu_id]
87             if not self.vdu:
88                 raise NFLCMException("VNF Vm does not exist.")
89         apply_result = grant_resource(data=self.data, nf_inst_id=self.nf_inst_id, job_id=self.job_id,
90                                       grant_type=self.grant_type, vdus=self.vdu)
91         if self.action == HEAL_ACTION_TYPE.START:
92             self.vimid = ignore_case_get(apply_result, "vimid"),
93             self.tenant = ignore_case_get(apply_result, "tenant")
94         logger.info("Grant resource, response: %s" % apply_result)
95         JobUtil.add_job_status(self.job_id, 20, 'Nf Healing grant_resource finish')
96
97     def heal_resource(self):
98         logger.info('Heal resource begin')
99         data = {'action': self.action, 'vimid': self.vimid, 'tenant': self.tenant}
100         adaptor.heal_vim_res(self.vdu, self.vnfd_info, self.do_notify, data, json.loads(self.vnf_insts[0].vimInfo), json.loads(self.vnf_insts[0].resInfo))
101         logger.info('Heal resource complete')
102
103     def do_notify(self, res_type, ret):
104         logger.info('Creating [%s] resource' % res_type)
105         resource_save_method = getattr(common, res_type + '_save')
106         resource_save_method(self.job_id, self.nf_inst_id, ret)
107
108     def lcm_notify(self):
109         notification_content = prepare_notification_data(self.nf_inst_id, self.job_id, CHANGE_TYPE.MODIFIED, OPERATION_TYPE.HEAL)
110         logger.info('Notify request data = %s' % notification_content)
111         resp = notify_lcm_to_nfvo(json.dumps(notification_content))
112         logger.info('Lcm notify end, response %s' % resp)
113
114     def vnf_heal_failed_handle(self, error_msg):
115         logger.error('VNF Healing failed, detail message: %s' % error_msg)
116         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status=VNF_STATUS.FAILED, lastuptime=now_time())
117         JobUtil.add_job_status(self.job_id, 255, error_msg)