f5a5d9eb96808b7b650cfa8b5af412d9bb109e99
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
31 from requests
.exceptions
import ConnectionError
, RequestException
33 from osm_policy_module
.common
.common_db_client
import CommonDbClient
34 from osm_policy_module
.common
.lcm_client
import LcmClient
35 from osm_policy_module
.common
.mon_client
import MonClient
36 from osm_policy_module
.core
import database
37 from osm_policy_module
.core
.config
import Config
38 from osm_policy_module
.core
.database
import (
41 AlarmActionRepository
,
43 from osm_policy_module
.core
.exceptions
import VdurNotFound
45 log
= logging
.getLogger(__name__
)
48 class AlarmingService
:
49 def __init__(self
, config
: Config
):
51 self
.db_client
= CommonDbClient(config
)
52 self
.mon_client
= MonClient(config
)
53 self
.lcm_client
= LcmClient(config
)
55 async def configure_vnf_alarms(self
, nsr_id
: str, vnf_member_index
=None):
56 log
.info("Configuring vnf alarms for network service %s", nsr_id
)
60 with database
.db
.atomic():
61 if vnf_member_index
is None:
62 vnfrs
= self
.db_client
.get_vnfrs(nsr_id
)
65 vnfr
= self
.db_client
.get_vnfr(nsr_id
, vnf_member_index
)
67 # vnfrs = self.db_client.get_vnfrs(nsr_id)
69 log
.debug("Processing vnfr: %s", vnfr
)
70 vnfd
= self
.db_client
.get_vnfd(vnfr
["vnfd-id"])
71 for vdur
in vnfr
["vdur"]:
74 lambda vdu
: vdu
["id"] == vdur
["vdu-id-ref"], vnfd
["vdu"]
78 alarm_descriptors
= vdu
["alarm"]
79 for alarm_descriptor
in alarm_descriptors
:
81 VnfAlarmRepository
.get(
83 == alarm_descriptor
["alarm-id"],
84 VnfAlarm
.vnf_member_index
85 == vnfr
["member-vnf-index-ref"],
86 VnfAlarm
.vdu_name
== vdur
["name"],
87 VnfAlarm
.nsr_id
== nsr_id
,
90 "vdu %s already has an alarm configured with same id %s",
92 alarm_descriptor
["alarm-id"],
95 except VnfAlarm
.DoesNotExist
:
97 vnf_monitoring_param
= next(
99 lambda param
: param
["id"]
100 == alarm_descriptor
["vnf-monitoring-param-ref"],
101 vdu
.get("monitoring-parameter", []),
105 metric_name
= self
._get
_metric
_name
(
108 alarm_action
= dict()
109 for action_type
in ["ok", "insufficient-data", "alarm"]:
111 "actions" in alarm_descriptor
112 and action_type
in alarm_descriptor
["actions"]
114 for url
in alarm_descriptor
["actions"][
117 if "webhook" in alarm_action
:
118 alarm_action
["webhook"].append(
122 alarm_action
["webhook"] = [url
["url"]]
123 alarm_uuid
= await self
.mon_client
.create_alarm(
124 metric_name
=metric_name
,
126 vdu_name
=vdur
["name"],
127 vnf_member_index
=vnfr
["member-vnf-index-ref"],
128 threshold
=alarm_descriptor
["value"],
129 operation
=alarm_descriptor
["operation"],
130 action
=str(alarm_action
),
132 alarm
= VnfAlarmRepository
.create(
133 alarm_id
=alarm_descriptor
["alarm-id"],
134 alarm_uuid
=alarm_uuid
,
136 vnf_member_index
=vnfr
["member-vnf-index-ref"],
137 vdu_name
=vdur
["name"],
138 last_action
="insufficient-data",
143 for action_type
in ["ok", "insufficient-data", "alarm"]:
145 "actions" in alarm_descriptor
146 and action_type
in alarm_descriptor
["actions"]
148 for url
in alarm_descriptor
["actions"][
151 AlarmActionRepository
.create(
156 alarms_created
.append(alarm
)
158 except Exception as e
:
159 log
.exception("Error configuring VNF alarms:")
160 if len(alarms_created
) > 0:
161 log
.debug("Cleaning alarm resources in MON")
162 for alarm
in alarms_created
:
164 await self
.mon_client
.delete_alarm(
166 alarm
.vnf_member_index
,
172 "Error deleting alarm in MON %s", alarm
.alarm_uuid
178 async def delete_orphaned_alarms(self
, nsr_id
):
179 # TODO: Review as it seems this code is never called
180 log
.info("Deleting orphaned vnf alarms for network service %s", nsr_id
)
181 database
.db
.connect()
183 with database
.db
.atomic():
184 for alarm
in VnfAlarmRepository
.list(VnfAlarm
.nsr_id
== nsr_id
):
186 self
.db_client
.get_vdur(
187 nsr_id
, alarm
.vnf_member_index
, alarm
.vdu_name
190 log
.debug("Deleting orphaned alarm %s", alarm
.alarm_uuid
)
192 await self
.mon_client
.delete_alarm(
194 alarm
.vnf_member_index
,
200 "Error deleting alarm in MON %s", alarm
.alarm_uuid
202 alarm
.delete_instance()
203 except Exception as e
:
204 log
.exception("Error deleting orphaned alarms:")
209 async def delete_vnf_alarms(self
, nsr_id
, vnf_member_index
=None):
210 log
.info("Deleting vnf alarms for network service %s", nsr_id
)
211 database
.db
.connect()
213 with database
.db
.atomic():
214 if vnf_member_index
is None:
215 alarm_conditions
= VnfAlarm
.nsr_id
== nsr_id
218 VnfAlarm
.nsr_id
== nsr_id
,
219 VnfAlarm
.vnf_member_index
== vnf_member_index
,
221 alarm_conditions
= functools
.reduce(operator
.and_
, query_list
)
222 for alarm
in VnfAlarmRepository
.list(alarm_conditions
):
223 log
.debug("Deleting vnf alarm %s", alarm
.alarm_uuid
)
225 await self
.mon_client
.delete_alarm(
227 alarm
.vnf_member_index
,
233 "Error deleting alarm in MON %s", alarm
.alarm_uuid
235 alarm
.delete_instance()
237 except Exception as e
:
238 log
.exception("Error deleting vnf alarms:")
243 async def handle_alarm(self
, alarm_uuid
: str, status
: str, payload
: dict):
244 alert_timeout
= int(self
.conf
.get("alert", "timeout"))
245 database
.db
.connect()
247 with database
.db
.atomic():
248 alarm
= VnfAlarmRepository
.get(VnfAlarm
.alarm_uuid
== alarm_uuid
)
250 "Handling vnf alarm %s with status %s", alarm
.alarm_id
, status
252 for action
in alarm
.actions
:
254 Compares the current status with the last_action status.
255 If both the status are 'alarm', it avoid sending repetitive alarm notification.
256 If both the status are 'ok', it avoid sending repetitive ok notification.
258 if action
.type == status
:
259 if bool(self
.conf
.get("alert", "enhanced_alarms")):
262 or (status
== "ok" and alarm
.ok_ack
is False)
265 or (status
== "alarm" and alarm
.alarm_ack
is False)
268 "Executing request to url %s for vnf alarm %s with status %s",
274 if status
== "alarm" and alarm
.last_action
== "ok":
277 if status
== "ok" and alarm
.last_action
== "alarm":
278 alarm
.alarm_ack
= False
279 alarm
.last_action
= status
281 except Exception as e
:
284 payload
["notify_details"][
287 headers
= {"content-type": "application/json"}
289 resp
= requests
.post(
291 data
=json
.dumps(payload
),
293 timeout
=alert_timeout
,
295 log
.info("Response %s", resp
)
296 if resp
.status_code
== 200:
300 if status
== "alarm":
301 alarm
.alarm_ack
= True
303 if status
== "insufficient-data":
304 alarm
.alarm_ack
= False
307 except ConnectionError
:
309 "Error connecting to url %s", action
.url
311 except RequestException
as e
:
313 "Error: RequestException while connecting to url %s",
316 log
.debug("RequestException %s", e
)
320 "Executing request to url %s for vnf alarm %s with status %s",
328 json
=json
.dumps(payload
),
329 timeout
=alert_timeout
,
331 except ConnectionError
:
332 log
.exception("Error connecting to url %s", action
.url
)
333 except RequestException
as e
:
335 "Error: RequestException while connecting to url %s",
338 log
.debug("RequestException %s", e
)
340 except VnfAlarm
.DoesNotExist
:
342 "There is no alarming action configured for alarm %s.", alarm_uuid
347 def _get_metric_name(self
, vnf_monitoring_param
: dict):
348 if "performance-metric" in vnf_monitoring_param
:
349 return vnf_monitoring_param
["performance-metric"]
351 "No metric name found for vnf_monitoring_param %s"
352 % vnf_monitoring_param
["id"]