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.timeutil import now_time
27 from lcm.pub.utils.values import ignore_case_get
28 from lcm.pub.vimapi import adaptor
29 from lcm.nf.biz.grant_vnf import grant_resource
30 from lcm.nf.const import VNF_STATUS, GRANT_TYPE, OPERATION_STATE_TYPE, LCM_NOTIFICATION_STATUS
31 from lcm.nf.const import CHANGE_TYPE, OPERATION_TYPE, HEAL_ACTION_TYPE
32 from lcm.nf.const import OPERATION_TASK
33 from lcm.nf.biz import common
34 from .operate_vnf_lcm_op_occ import VnfLcmOpOcc
37 logger = logging.getLogger(__name__)
40 class HealVnf(Thread):
41 def __init__(self, data, nf_inst_id, job_id):
42 super(HealVnf, self).__init__()
44 self.nf_inst_id = nf_inst_id
46 self.affectedvm = ignore_case_get(ignore_case_get(self.data, "additionalParams"), "affectedvm")
47 # TODO: Check if we could move the action param into the list of affectedvm structure
48 self.action = ignore_case_get(ignore_case_get(self.data, "additionalParams"), "action")
50 if self.action == HEAL_ACTION_TYPE.START:
51 self.grant_type = GRANT_TYPE.HEAL_CREATE
52 elif self.action == HEAL_ACTION_TYPE.RESTART:
53 self.grant_type = GRANT_TYPE.HEAL_RESTART
54 self.lcm_op_occ = VnfLcmOpOcc(
55 vnf_inst_id=nf_inst_id,
57 operation=OPERATION_TYPE.HEAL,
58 task=OPERATION_TASK.HEAL
64 self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.STARTING)
66 self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.PROCESSING)
68 JobUtil.add_job_status(self.job_id, 100, "Heal Vnf success.")
69 NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(
70 status='INSTANTIATED',
73 self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.COMPLETED)
74 except NFLCMException as e:
75 logger.error(e.message)
76 self.vnf_heal_failed_handle(e.message)
77 except Exception as e:
78 logger.error(e.message)
79 logger.error(traceback.format_exc())
80 self.vnf_heal_failed_handle(e.message)
83 if self.action not in (HEAL_ACTION_TYPE.START, HEAL_ACTION_TYPE.RESTART):
84 raise NFLCMException("Action should be %s or %s" % (HEAL_ACTION_TYPE.START, HEAL_ACTION_TYPE.RESTART))
86 self.vm_id = ignore_case_get(self.affectedvm, "vmid")
87 self.vdu_id = ignore_case_get(self.affectedvm, "vduid")
88 self.vm_name = ignore_case_get(self.affectedvm, "vmname")
89 if not (self.vm_id and self.vdu_id and self.vm_name):
90 raise NFLCMException("VM identifiers is not present in request.")
92 self.vnf_insts = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
93 self.vnfd_info = json.loads(self.vnf_insts[0].vnfd_model)
95 def apply_grant(self):
96 if self.action == HEAL_ACTION_TYPE.RESTART:
97 self.vdu = VmInstModel.objects.filter(instid=self.nf_inst_id, resourceid=self.vm_id)
99 raise NFLCMException("VNF Vm(%s) does not exist." % self.vm_id)
100 self.vimid = self.vdu[0].vimid
101 self.tenant = self.vdu[0].tenant
102 logger.debug("Get heal vnf vm(%s,%s) info successfully.", self.vm_id, self.vm_name)
103 JobUtil.add_job_status(self.job_id, 20, 'Nf Healing get vnf vm info finish')
106 vdus = ignore_case_get(self.vnfd_info, "vdus")
107 self.vdu = [elem for elem in vdus if ignore_case_get(elem, "vdu_id") == self.vdu_id]
109 raise NFLCMException("VNF Vdu(%s) does not exist." % self.vdu_id)
110 apply_result = grant_resource(data=self.data, nf_inst_id=self.nf_inst_id, job_id=self.job_id,
111 grant_type=self.grant_type, vdus=self.vdu)
113 self.vimid = ignore_case_get(apply_result, "vimid"),
114 self.tenant = ignore_case_get(apply_result, "tenant")
115 logger.info("Grant resource, response: %s" % apply_result)
116 JobUtil.add_job_status(self.job_id, 20, 'Nf Healing grant_resource finish')
118 def heal_resource(self):
119 logger.info('Heal resource begin')
120 data = {'action': self.action, 'vimid': self.vimid, 'tenant': self.tenant}
121 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))
122 logger.info('Heal resource complete')
124 def do_notify(self, res_type, ret):
125 logger.info('Creating [%s] resource' % res_type)
126 resource_save_method = getattr(common, res_type + '_save')
127 resource_save_method(self.job_id, self.nf_inst_id, ret)
129 def vnf_heal_failed_handle(self, error_msg):
130 logger.error('VNF Healing failed, detail message: %s' % error_msg)
131 NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(
132 status=VNF_STATUS.FAILED,
133 lastuptime=now_time()
135 self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.FAILED, error_msg)
136 JobUtil.add_job_status(self.job_id, 255, error_msg)
138 def prepareNotificationData(self, status, opState, err=None):
140 if status == LCM_NOTIFICATION_STATUS.RESULT and opState == OPERATION_STATE_TYPE.COMPLETED:
142 if self.action == HEAL_ACTION_TYPE.START:
143 chtype = CHANGE_TYPE.ADDED
145 chtype = CHANGE_TYPE.MODIFIED
146 vnfcs = VNFCInstModel.objects.filter(instid=self.nf_inst_id, vmid=self.vm_id)
148 vm = VmInstModel.objects.filter(instid=self.nf_inst_id, resourceid=self.vm_id)
151 'vimConnectionId': vm[0].vimid,
152 'resourceId': vm[0].resourceid,
153 'vimLevelResourceType': 'vm'
156 affected_vnfcs.append({
157 'id': vnfcs[0].vnfcinstanceid,
158 'vduId': vnfcs[0].vduid,
159 'changeType': chtype,
160 'computeResource': vm_resource
163 notification_content = {
164 "id": str(uuid.uuid4()),
165 "notificationType": "VnfLcmOperationOccurrenceNotification",
166 "subscriptionId": "",
167 "timeStamp": now_time(),
168 "notificationStatus": status,
169 "operationState": opState,
170 "vnfInstanceId": self.nf_inst_id,
171 "operation": OPERATION_TYPE.HEAL,
172 "isAutomaticInvocation": "false",
173 "vnfLcmOpOccId": self.job_id,
174 "affectedVnfcs": affected_vnfcs,
175 "affectedVirtualLinks": [],
176 "affectedVirtualStorages": [],
178 "changedExtConnectivity": [],
179 "_links": {"vnfInstance": {"href": ""},
180 "subscription": {"href": ""},
181 "vnfLcmOpOcc": {"href": ""}}
183 if opState in (OPERATION_STATE_TYPE.FAILED, OPERATION_STATE_TYPE.FAILED_TEMP):
184 notification_content["error"] = {"status": 500, "detail": err}
185 notification_content["_links"]["vnfInstance"]["href"] = "/vnf_instances/%s" % self.nf_inst_id
186 notification_content["_links"]["vnfLcmOpOcc"]["href"] = "/vnf_lc_ops/%s" % self.job_id
187 return notification_content