1 # -*- coding: utf-8 -*-
2 # pylint: disable=no-member
4 # Copyright 2018 Whitestack, LLC
5 # *************************************************************
7 # This file is part of OSM Monitoring module
8 # All Rights Reserved to Whitestack, LLC
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
14 # http://www.apache.org/licenses/LICENSE-2.0
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
22 # For those usages not covered by the Apache License, Version 2.0 please
23 # contact: bdiaz@whitestack.com or glavado@whitestack.com
28 from osm_policy_module
.common
.common_db_client
import CommonDbClient
29 from osm_policy_module
.common
.lcm_client
import LcmClient
30 from osm_policy_module
.common
.mon_client
import MonClient
31 from osm_policy_module
.core
import database
32 from osm_policy_module
.core
.config
import Config
33 from osm_policy_module
.core
.database
import (
35 HealingActionRepository
,
37 from osm_policy_module
.core
.exceptions
import VdurNotFound
39 log
= logging
.getLogger(__name__
)
43 def __init__(self
, config
: Config
):
45 Initializing the HealingService
47 log
.info("HealingService Initialized")
49 self
.db_client
= CommonDbClient(config
)
50 self
.mon_client
= MonClient(config
)
51 self
.lcm_client
= LcmClient(config
)
52 log
.info("Constructor created for HealingService")
54 async def configure_healing_alarms(self
, nsr_id
: str):
56 Configuring the Healing alarms
57 :param nsr_id: Network service record id
59 log
.info("Configuring Healing alarm for NS %s", nsr_id
)
63 with database
.db
.atomic():
64 vnfrs
= self
.db_client
.get_vnfrs(nsr_id
)
66 vnfd
= self
.db_client
.get_vnfd(vnfr
["vnfd-id"])
67 df
= vnfd
.get("df", [{}])[0]
68 if "healing-aspect" not in df
:
69 log
.info("No healing configuration present in vnfd")
71 healing_aspects
= df
["healing-aspect"]
72 for healing_aspect
in healing_aspects
:
73 for healing_policy
in healing_aspect
.get("healing-policy", ()):
74 vdu_id
= healing_policy
["vdu-id"]
75 for vdur
in vnfr
["vdur"]:
76 if vdu_id
== vdur
["vdu-id-ref"]:
78 HealingActionRepository
.get(
79 HealingAction
.alarm_id
80 == healing_policy
["event-name"],
81 HealingAction
.vdur_name
== vdur
["name"],
82 HealingAction
.nsr_id
== nsr_id
,
83 HealingAction
.cooldown_time
84 == healing_policy
["cooldown-time"],
85 HealingAction
.recovery_action
86 == healing_policy
["action-on-recovery"],
87 HealingAction
.vnfinstance_id
== vnfr
["id"],
89 == healing_policy
["vdu-id"],
90 HealingAction
.count_index
91 == vdur
["count-index"],
94 "vdu %s already has an alarm configured with same id %s",
95 healing_policy
["vdu-id"],
96 healing_policy
["event-name"],
99 except HealingAction
.DoesNotExist
:
102 metric_name
= "vm_status"
103 alarm_uuid
= await self
.mon_client
.create_alarm(
104 metric_name
=metric_name
,
106 vdu_name
=vdur
["name"],
107 vnf_member_index
=vnfr
["member-vnf-index-ref"],
112 alarm
= HealingActionRepository
.create(
113 alarm_id
=healing_policy
["event-name"],
114 alarm_uuid
=alarm_uuid
,
116 vnf_member_index
=vnfr
["member-vnf-index-ref"],
117 vdur_name
=vdur
["name"],
118 recovery_action
=healing_policy
[
121 cooldown_time
=healing_policy
["cooldown-time"],
122 day1
=healing_policy
["day1"],
123 vdu_id
=healing_policy
["vdu-id"],
124 vnfinstance_id
=vnfr
["id"],
125 count_index
=vdur
["count-index"],
127 alarms_created
.append(alarm
)
129 except Exception as e
:
130 log
.exception("Error configuring VNF alarms:")
131 if len(alarms_created
) > 0:
132 for alarm
in alarms_created
:
134 await self
.mon_client
.delete_alarm(
136 alarm
.vnf_member_index
,
142 "Error deleting alarm in MON %s", alarm
.alarm_uuid
148 async def delete_orphaned_healing_alarms(self
, nsr_id
):
149 log
.info("Deleting orphaned healing alarms for network service %s", nsr_id
)
150 database
.db
.connect()
152 with database
.db
.atomic():
153 for alarm
in HealingActionRepository
.list(
154 HealingAction
.nsr_id
== nsr_id
157 self
.db_client
.get_vdur(
158 nsr_id
, alarm
.vnf_member_index
, alarm
.vdur_name
161 log
.info("Deleting orphaned alarm %s", alarm
.alarm_uuid
)
163 await self
.mon_client
.delete_alarm(
165 alarm
.vnf_member_index
,
171 "Error deleting alarm in MON %s", alarm
.alarm_uuid
173 alarm
.delete_instance()
175 except Exception as e
:
176 log
.exception("Error deleting orphaned alarms:")
181 async def delete_healing_alarms(self
, nsr_id
):
183 Deleting the healing alarms
184 :param nsr_id: Network service record id
186 log
.info("Deleting healing vnf alarms for network service %s", nsr_id
)
187 database
.db
.connect()
189 with database
.db
.atomic():
190 for alarm
in HealingActionRepository
.list(
191 HealingAction
.nsr_id
== nsr_id
194 await self
.mon_client
.delete_alarm(
196 alarm
.vnf_member_index
,
202 "Error deleting alarm in MON %s", alarm
.alarm_uuid
204 alarm
.delete_instance()
206 except Exception as e
:
207 log
.exception("Error deleting vnf alarms:")
212 async def update_alarm_status(self
, alarm_uuid
: str, status
: str):
214 For updating the alarm status
215 :param alarm_uuid: vdu uuid
216 :param status: Status of an alarm
218 database
.db
.connect()
220 with database
.db
.atomic():
221 alarm
= HealingActionRepository
.get(
222 HealingAction
.alarm_uuid
== alarm_uuid
224 alarm
.last_status
= status
226 except HealingAction
.DoesNotExist
:
227 log
.debug("There is no healing action configured for alarm %s.", alarm_uuid
)
231 async def handle_alarm(self
, alarm_uuid
: str, status
: str):
233 For Handling the healing alarms
234 :param alarm_uuid: vdu uuid
235 :param status: Status of an alarm
237 await self
.update_alarm_status(alarm_uuid
, status
)
238 database
.db
.connect()
240 if status
== "alarm":
241 if self
.conf
.get("autoheal", "enabled") == "True":
242 with database
.db
.atomic():
243 alarm
= HealingActionRepository
.get(
244 HealingAction
.alarm_uuid
== alarm_uuid
246 vnf_member_index
= alarm
.vnf_member_index
247 vdur_name
= alarm
.vdur_name
248 vdu_id
= alarm
.vdu_id
249 nsr_id
= alarm
.nsr_id
250 heal_type
= alarm
.recovery_action
251 cooldown_time
= alarm
.cooldown_time
252 count_index
= alarm
.count_index
253 last_heal
= alarm
.last_heal
255 vnfinstance_id
= alarm
.vnfinstance_id
256 alarms
= HealingActionRepository
.list(
257 HealingAction
.vnf_member_index
== vnf_member_index
,
258 HealingAction
.vdur_name
== vdur_name
,
263 statuses
.append(alarm
.last_status
)
264 if (set(statuses
) == {"alarm"}) or ("alarm" in statuses
):
265 delta
= datetime
.datetime
.now() - last_heal
266 if delta
.total_seconds() > cooldown_time
:
267 await self
.lcm_client
.heal(
277 last_heal
= datetime
.datetime
.now()
279 "datetime.datetime.now %s", datetime
.datetime
.now
281 alarm
.last_heal
= last_heal
284 except HealingAction
.DoesNotExist
:
285 log
.info("There is no healing action configured for alarm %s.", alarm_uuid
)