1 # Copyright (C) 2018 Verizon. All Rights Reserved.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
19 from threading import Thread
21 from lcm.pub.database.models import NfInstModel
22 from lcm.pub.database.models import VmInstModel
23 from lcm.pub.database.models import VNFCInstModel
24 from lcm.pub.exceptions import NFLCMException
25 from lcm.pub.utils.jobutil import JobUtil
26 from lcm.pub.utils.notificationsutil import NotificationsUtil
27 from lcm.pub.utils.timeutil import now_time
28 from lcm.pub.utils.values import ignore_case_get
29 from lcm.pub.vimapi import adaptor
30 from lcm.nf.biz.grant_vnf import grant_resource
31 from lcm.nf.const import VNF_STATUS, GRANT_TYPE, OPERATION_STATE_TYPE, LCM_NOTIFICATION_STATUS
32 from lcm.nf.const import CHANGE_TYPE, OPERATION_TYPE, HEAL_ACTION_TYPE
33 from lcm.nf.const import OPERATION_TASK
34 from lcm.nf.biz import common
35 from .operate_vnf_lcm_op_occ import VnfLcmOpOcc
38 logger = logging.getLogger(__name__)
41 class HealVnf(Thread):
42 def __init__(self, data, nf_inst_id, job_id):
43 super(HealVnf, self).__init__()
45 self.nf_inst_id = nf_inst_id
47 self.affectedvm = ignore_case_get(ignore_case_get(self.data, "additionalParams"), "affectedvm")
48 # TODO: Check if we could move the action param into the list of affectedvm structure
49 self.action = ignore_case_get(ignore_case_get(self.data, "additionalParams"), "action")
51 if self.action == HEAL_ACTION_TYPE.START:
52 self.grant_type = GRANT_TYPE.HEAL_CREATE
53 elif self.action == HEAL_ACTION_TYPE.RESTART:
54 self.grant_type = GRANT_TYPE.HEAL_RESTART
55 self.lcm_op_occ = VnfLcmOpOcc(
56 vnf_inst_id=nf_inst_id,
58 operation=OPERATION_TYPE.HEAL,
59 task=OPERATION_TASK.HEAL
65 self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.STARTING)
67 self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.PROCESSING)
69 JobUtil.add_job_status(self.job_id, 100, "Heal Vnf success.")
70 NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(
71 status='INSTANTIATED',
75 LCM_NOTIFICATION_STATUS.RESULT,
76 OPERATION_STATE_TYPE.COMPLETED
78 except NFLCMException as e:
79 logger.error(e.message)
80 self.vnf_heal_failed_handle(e.message)
81 except Exception as e:
82 logger.error(e.message)
83 logger.error(traceback.format_exc())
84 self.vnf_heal_failed_handle(e.message)
87 if self.action not in (HEAL_ACTION_TYPE.START, HEAL_ACTION_TYPE.RESTART):
88 raise NFLCMException("Action should be %s or %s" % (HEAL_ACTION_TYPE.START, HEAL_ACTION_TYPE.RESTART))
90 self.vm_id = ignore_case_get(self.affectedvm, "vmid")
91 self.vdu_id = ignore_case_get(self.affectedvm, "vduid")
92 self.vm_name = ignore_case_get(self.affectedvm, "vmname")
93 if not (self.vm_id and self.vdu_id and self.vm_name):
94 raise NFLCMException("VM identifiers is not present in request.")
96 self.vnf_insts = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
97 self.vnfd_info = json.loads(self.vnf_insts[0].vnfd_model)
99 def apply_grant(self):
100 if self.action == HEAL_ACTION_TYPE.RESTART:
101 self.vdu = VmInstModel.objects.filter(instid=self.nf_inst_id, resourceid=self.vm_id)
103 raise NFLCMException("VNF Vm(%s) does not exist." % self.vm_id)
104 self.vimid = self.vdu[0].vimid
105 self.tenant = self.vdu[0].tenant
106 logger.debug("Get heal vnf vm(%s,%s) info successfully.", self.vm_id, self.vm_name)
107 JobUtil.add_job_status(self.job_id, 20, 'Nf Healing get vnf vm info finish')
110 vdus = ignore_case_get(self.vnfd_info, "vdus")
111 self.vdu = [elem for elem in vdus if ignore_case_get(elem, "vdu_id") == self.vdu_id]
113 raise NFLCMException("VNF Vdu(%s) does not exist." % self.vdu_id)
114 apply_result = grant_resource(data=self.data, nf_inst_id=self.nf_inst_id, job_id=self.job_id,
115 grant_type=self.grant_type, vdus=self.vdu)
117 self.vimid = ignore_case_get(apply_result, "vimid"),
118 self.tenant = ignore_case_get(apply_result, "tenant")
119 logger.info("Grant resource, response: %s" % apply_result)
120 JobUtil.add_job_status(self.job_id, 20, 'Nf Healing grant_resource finish')
122 def heal_resource(self):
123 logger.info('Heal resource begin')
124 data = {'action': self.action, 'vimid': self.vimid, 'tenant': self.tenant}
125 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))
126 logger.info('Heal resource complete')
128 def do_notify(self, res_type, ret):
129 logger.info('Creating [%s] resource' % res_type)
130 resource_save_method = getattr(common, res_type + '_save')
131 resource_save_method(self.job_id, self.nf_inst_id, ret)
133 def vnf_heal_failed_handle(self, error_msg):
134 logger.error('VNF Healing failed, detail message: %s' % error_msg)
135 NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(
136 status=VNF_STATUS.FAILED,
137 lastuptime=now_time()
139 self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.FAILED, error_msg)
140 JobUtil.add_job_status(self.job_id, 255, error_msg)
142 def lcm_notify(self, status, opState, err=None):
143 notification_content = self.prepareNotificationData(status, opState, err)
144 logger.info('Notify data = %s' % notification_content)
145 NotificationsUtil().send_notification(notification_content)
146 logger.info('Notify end')
148 def prepareNotificationData(self, status, opState, err=None):
150 if status == LCM_NOTIFICATION_STATUS.RESULT and opState == OPERATION_STATE_TYPE.COMPLETED:
152 if self.action == HEAL_ACTION_TYPE.START:
153 chtype = CHANGE_TYPE.ADDED
155 chtype = CHANGE_TYPE.MODIFIED
156 vnfcs = VNFCInstModel.objects.filter(instid=self.nf_inst_id, vmid=self.vm_id)
158 vm = VmInstModel.objects.filter(instid=self.nf_inst_id, resourceid=self.vm_id)
161 'vimConnectionId': vm[0].vimid,
162 'resourceId': vm[0].resourceid,
163 'vimLevelResourceType': 'vm'
166 affected_vnfcs.append({
167 'id': vnfcs[0].vnfcinstanceid,
168 'vduId': vnfcs[0].vduid,
169 'changeType': chtype,
170 'computeResource': vm_resource
173 notification_content = {
174 "id": str(uuid.uuid4()),
175 "notificationType": "VnfLcmOperationOccurrenceNotification",
176 "subscriptionId": "",
177 "timeStamp": now_time(),
178 "notificationStatus": status,
179 "operationState": opState,
180 "vnfInstanceId": self.nf_inst_id,
181 "operation": OPERATION_TYPE.HEAL,
182 "isAutomaticInvocation": "false",
183 "vnfLcmOpOccId": self.job_id,
184 "affectedVnfcs": affected_vnfcs,
185 "affectedVirtualLinks": [],
186 "affectedVirtualStorages": [],
188 "changedExtConnectivity": [],
189 "_links": {"vnfInstance": {"href": ""},
190 "subscription": {"href": ""},
191 "vnfLcmOpOcc": {"href": ""}}
193 if opState in (OPERATION_STATE_TYPE.FAILED, OPERATION_STATE_TYPE.FAILED_TEMP):
194 notification_content["error"] = {"status": 500, "detail": err}
195 notification_content["_links"]["vnfInstance"]["href"] = "/vnf_instances/%s" % self.nf_inst_id
196 notification_content["_links"]["vnfLcmOpOcc"]["href"] = "/vnf_lc_ops/%s" % self.job_id
197 return notification_content