blob: 1885d05efbacbb97d381cf54590347fc4543dbc2 [file] [log] [blame]
sritharan7ef2b882022-04-25 12:37:55 +00001# -*- coding: utf-8 -*-
2# pylint: disable=no-member
3
4# Copyright 2018 Whitestack, LLC
5# *************************************************************
6
7# This file is part of OSM Monitoring module
8# All Rights Reserved to Whitestack, LLC
9
10# Licensed under the Apache License, Version 2.0 (the "License"); you may
11# not use this file except in compliance with the License. You may obtain
12# a copy of the License at
13
14# http://www.apache.org/licenses/LICENSE-2.0
15
16# Unless required by applicable law or agreed to in writing, software
17# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19# License for the specific language governing permissions and limitations
20# under the License.
21
22# For those usages not covered by the Apache License, Version 2.0 please
23# contact: bdiaz@whitestack.com or glavado@whitestack.com
24##
25import asyncio
26import logging
27import datetime
28
29from osm_policy_module.common.common_db_client import CommonDbClient
30from osm_policy_module.common.lcm_client import LcmClient
31from osm_policy_module.common.mon_client import MonClient
32from osm_policy_module.core import database
33from osm_policy_module.core.config import Config
34from osm_policy_module.core.database import (
35 HealingAction,
36 HealingActionRepository,
37)
38from osm_policy_module.core.exceptions import VdurNotFound
39
40log = logging.getLogger(__name__)
41
42
43class HealingService:
44 def __init__(self, config: Config, loop=None):
45 """
garciadeblasbe42d542022-11-14 00:29:47 +010046 Initializing the HealingService
sritharan7ef2b882022-04-25 12:37:55 +000047 """
48 log.info("HealingService Initialized")
49 self.conf = config
50 if not loop:
51 loop = asyncio.get_event_loop()
52 self.loop = loop
53 self.db_client = CommonDbClient(config)
54 self.mon_client = MonClient(config, loop=self.loop)
55 self.lcm_client = LcmClient(config, loop=self.loop)
56 log.info("Constructor created for HealingService")
57
58 async def configure_healing_alarms(self, nsr_id: str):
59 """
garciadeblasbe42d542022-11-14 00:29:47 +010060 Configuring the Healing alarms
61 :param nsr_id: Network service record id
sritharan7ef2b882022-04-25 12:37:55 +000062 """
63 log.info("Configuring Healing alarm for NS %s", nsr_id)
64 alarms_created = []
65 database.db.connect()
66 try:
67 with database.db.atomic():
68 vnfrs = self.db_client.get_vnfrs(nsr_id)
69 for vnfr in vnfrs:
garciadeblasbe42d542022-11-14 00:29:47 +010070 vnfd = self.db_client.get_vnfd(vnfr["vnfd-id"])
sritharan7ef2b882022-04-25 12:37:55 +000071 df = vnfd.get("df", [{}])[0]
72 if "healing-aspect" not in df:
73 log.info("No healing configuration present in vnfd")
74 continue
75 healing_aspects = df["healing-aspect"]
76 for healing_aspect in healing_aspects:
garciadeblasbe42d542022-11-14 00:29:47 +010077 for healing_policy in healing_aspect.get("healing-policy", ()):
78 vdu_id = healing_policy["vdu-id"]
sritharan7ef2b882022-04-25 12:37:55 +000079 for vdur in vnfr["vdur"]:
80 if vdu_id == vdur["vdu-id-ref"]:
81 try:
82 HealingActionRepository.get(
garciadeblasbe42d542022-11-14 00:29:47 +010083 HealingAction.alarm_id
84 == healing_policy["event-name"],
85 HealingAction.vdur_name == vdur["name"],
sritharan7ef2b882022-04-25 12:37:55 +000086 HealingAction.nsr_id == nsr_id,
garciadeblasbe42d542022-11-14 00:29:47 +010087 HealingAction.cooldown_time
88 == healing_policy["cooldown-time"],
89 HealingAction.recovery_action
90 == healing_policy["action-on-recovery"],
91 HealingAction.vnfinstance_id == vnfr["id"],
92 HealingAction.vdu_id
93 == healing_policy["vdu-id"],
94 HealingAction.count_index
95 == vdur["count-index"],
sritharan7ef2b882022-04-25 12:37:55 +000096 )
garciadeblasbe42d542022-11-14 00:29:47 +010097 log.debug(
98 "vdu %s already has an alarm configured with same id %s",
99 healing_policy["vdu-id"],
100 healing_policy["event-name"],
101 )
sritharan7ef2b882022-04-25 12:37:55 +0000102 continue
103 except HealingAction.DoesNotExist:
104 pass
105
106 metric_name = "vm_status"
107 alarm_uuid = await self.mon_client.create_alarm(
108 metric_name=metric_name,
109 ns_id=nsr_id,
garciadeblasbe42d542022-11-14 00:29:47 +0100110 vdu_name=vdur["name"],
111 vnf_member_index=vnfr["member-vnf-index-ref"],
sritharan7ef2b882022-04-25 12:37:55 +0000112 threshold=1,
113 operation="LT",
garciadeblasbe42d542022-11-14 00:29:47 +0100114 statistic="AVERAGE",
sritharan7ef2b882022-04-25 12:37:55 +0000115 )
116 alarm = HealingActionRepository.create(
garciadeblasbe42d542022-11-14 00:29:47 +0100117 alarm_id=healing_policy["event-name"],
sritharan7ef2b882022-04-25 12:37:55 +0000118 alarm_uuid=alarm_uuid,
119 nsr_id=nsr_id,
garciadeblasbe42d542022-11-14 00:29:47 +0100120 vnf_member_index=vnfr["member-vnf-index-ref"],
121 vdur_name=vdur["name"],
122 recovery_action=healing_policy[
123 "action-on-recovery"
sritharan7ef2b882022-04-25 12:37:55 +0000124 ],
garciadeblasbe42d542022-11-14 00:29:47 +0100125 cooldown_time=healing_policy["cooldown-time"],
126 day1=healing_policy["day1"],
127 vdu_id=healing_policy["vdu-id"],
128 vnfinstance_id=vnfr["id"],
129 count_index=vdur["count-index"],
sritharan7ef2b882022-04-25 12:37:55 +0000130 )
131 alarms_created.append(alarm)
132
133 except Exception as e:
134 log.exception("Error configuring VNF alarms:")
135 if len(alarms_created) > 0:
136 for alarm in alarms_created:
137 try:
garciadeblasbe42d542022-11-14 00:29:47 +0100138 await self.mon_client.delete_alarm(
139 alarm.nsr_id,
140 alarm.vnf_member_index,
141 alarm.vdu_name,
142 alarm.alarm_uuid,
143 )
sritharan7ef2b882022-04-25 12:37:55 +0000144 except ValueError:
garciadeblasbe42d542022-11-14 00:29:47 +0100145 log.exception(
146 "Error deleting alarm in MON %s", alarm.alarm_uuid
147 )
sritharan7ef2b882022-04-25 12:37:55 +0000148 raise e
149 finally:
150 database.db.close()
151
152 async def delete_orphaned_healing_alarms(self, nsr_id):
153 log.info("Deleting orphaned healing alarms for network service %s", nsr_id)
154 database.db.connect()
155 try:
156 with database.db.atomic():
157 for alarm in HealingActionRepository.list(
158 HealingAction.nsr_id == nsr_id
159 ):
160 try:
161 self.db_client.get_vdur(
garciadeblasbe42d542022-11-14 00:29:47 +0100162 nsr_id, alarm.vnf_member_index, alarm.vdur_name
sritharan7ef2b882022-04-25 12:37:55 +0000163 )
164 except VdurNotFound:
garciadeblasbe42d542022-11-14 00:29:47 +0100165 log.info("Deleting orphaned alarm %s", alarm.alarm_uuid)
sritharan7ef2b882022-04-25 12:37:55 +0000166 try:
167 await self.mon_client.delete_alarm(
168 alarm.nsr_id,
169 alarm.vnf_member_index,
170 alarm.vdur_name,
garciadeblasbe42d542022-11-14 00:29:47 +0100171 alarm.alarm_uuid,
sritharan7ef2b882022-04-25 12:37:55 +0000172 )
173 except ValueError:
174 log.exception(
garciadeblasbe42d542022-11-14 00:29:47 +0100175 "Error deleting alarm in MON %s", alarm.alarm_uuid
sritharan7ef2b882022-04-25 12:37:55 +0000176 )
177 alarm.delete_instance()
178
179 except Exception as e:
180 log.exception("Error deleting orphaned alarms:")
181 raise e
182 finally:
183 database.db.close()
184
185 async def delete_healing_alarms(self, nsr_id):
186 """
garciadeblasbe42d542022-11-14 00:29:47 +0100187 Deleting the healing alarms
188 :param nsr_id: Network service record id
sritharan7ef2b882022-04-25 12:37:55 +0000189 """
190 log.info("Deleting healing vnf alarms for network service %s", nsr_id)
191 database.db.connect()
192 try:
193 with database.db.atomic():
194 for alarm in HealingActionRepository.list(
195 HealingAction.nsr_id == nsr_id
196 ):
197 try:
198 await self.mon_client.delete_alarm(
199 alarm.nsr_id,
200 alarm.vnf_member_index,
201 alarm.vdur_name,
garciadeblasbe42d542022-11-14 00:29:47 +0100202 alarm.alarm_uuid,
sritharan7ef2b882022-04-25 12:37:55 +0000203 )
204 except ValueError:
205 log.exception(
garciadeblasbe42d542022-11-14 00:29:47 +0100206 "Error deleting alarm in MON %s", alarm.alarm_uuid
sritharan7ef2b882022-04-25 12:37:55 +0000207 )
208 alarm.delete_instance()
209
210 except Exception as e:
211 log.exception("Error deleting vnf alarms:")
212 raise e
213 finally:
214 database.db.close()
215
216 async def update_alarm_status(self, alarm_uuid: str, status: str):
217 """
garciadeblasbe42d542022-11-14 00:29:47 +0100218 For updating the alarm status
219 :param alarm_uuid: vdu uuid
220 :param status: Status of an alarm
sritharan7ef2b882022-04-25 12:37:55 +0000221 """
222 database.db.connect()
223 try:
224 with database.db.atomic():
225 alarm = HealingActionRepository.get(
226 HealingAction.alarm_uuid == alarm_uuid
227 )
228 alarm.last_status = status
229 alarm.save()
230 except HealingAction.DoesNotExist:
garciadeblasbe42d542022-11-14 00:29:47 +0100231 log.debug("There is no healing action configured for alarm %s.", alarm_uuid)
sritharan7ef2b882022-04-25 12:37:55 +0000232 finally:
233 database.db.close()
234
235 async def handle_alarm(self, alarm_uuid: str, status: str):
236 """
garciadeblasbe42d542022-11-14 00:29:47 +0100237 For Handling the healing alarms
238 :param alarm_uuid: vdu uuid
239 :param status: Status of an alarm
sritharan7ef2b882022-04-25 12:37:55 +0000240 """
241 await self.update_alarm_status(alarm_uuid, status)
242 database.db.connect()
243 try:
244 if status == "alarm":
245 with database.db.atomic():
246 alarm = HealingActionRepository.get(
247 HealingAction.alarm_uuid == alarm_uuid
248 )
249 vnf_member_index = alarm.vnf_member_index
250 vdur_name = alarm.vdur_name
251 vdu_id = alarm.vdu_id
252 nsr_id = alarm.nsr_id
253 heal_type = alarm.recovery_action
254 cooldown_time = alarm.cooldown_time
255 count_index = alarm.count_index
256 last_heal = alarm.last_heal
257 day1 = alarm.day1
258 vnfinstance_id = alarm.vnfinstance_id
259 alarms = HealingActionRepository.list(
260 HealingAction.vnf_member_index == vnf_member_index,
garciadeblasbe42d542022-11-14 00:29:47 +0100261 HealingAction.vdur_name == vdur_name,
sritharan7ef2b882022-04-25 12:37:55 +0000262 )
263 statuses = []
264
265 for alarm in alarms:
266 statuses.append(alarm.last_status)
garciadeblasbe42d542022-11-14 00:29:47 +0100267 if (set(statuses) == {"alarm"}) or ("alarm" in statuses):
sritharan7ef2b882022-04-25 12:37:55 +0000268 delta = datetime.datetime.now() - last_heal
269 if delta.total_seconds() > cooldown_time:
270 await self.lcm_client.heal(
271 nsr_id,
272 vnfinstance_id,
273 vdur_name,
274 vdu_id,
275 vnf_member_index,
276 heal_type,
277 day1,
garciadeblasbe42d542022-11-14 00:29:47 +0100278 count_index,
sritharan7ef2b882022-04-25 12:37:55 +0000279 )
280 last_heal = datetime.datetime.now()
281 log.info("datetime.datetime.now %s", datetime.datetime.now)
282 alarm.last_heal = last_heal
283 alarm.save()
284
285 except HealingAction.DoesNotExist:
garciadeblasbe42d542022-11-14 00:29:47 +0100286 log.info("There is no healing action configured for alarm %s.", alarm_uuid)
sritharan7ef2b882022-04-25 12:37:55 +0000287 finally:
288 database.db.close()