blob: 13433ba5b763f3862a0743743acf32a03c835345 [file] [log] [blame]
Benjamin Diazf7451f82019-04-01 14:56:26 -03001# -*- coding: utf-8 -*-
Atul Agarwaldb8c1052020-04-28 15:42:28 +05302# pylint: disable=no-member
Benjamin Diazf7451f82019-04-01 14:56:26 -03003
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 json
27import logging
28
29import requests
Atul Agarwal46e7efd2021-10-18 17:22:58 +000030from requests.exceptions import ConnectionError, RequestException
Benjamin Diazf7451f82019-04-01 14:56:26 -030031
32from osm_policy_module.common.common_db_client import CommonDbClient
33from osm_policy_module.common.lcm_client import LcmClient
34from osm_policy_module.common.mon_client import MonClient
35from osm_policy_module.core import database
36from osm_policy_module.core.config import Config
garciadeblas4584f8e2021-05-14 16:50:06 +020037from osm_policy_module.core.database import (
38 VnfAlarm,
39 VnfAlarmRepository,
40 AlarmActionRepository,
41)
Benjamin Diazf7451f82019-04-01 14:56:26 -030042from osm_policy_module.core.exceptions import VdurNotFound
43
44log = logging.getLogger(__name__)
45
46
47class AlarmingService:
Benjamin Diazf7451f82019-04-01 14:56:26 -030048 def __init__(self, config: Config, loop=None):
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
57 async def configure_vnf_alarms(self, nsr_id: str):
58 log.info("Configuring vnf alarms for network service %s", nsr_id)
59 alarms_created = []
Benjamin Diazacac7552019-05-23 14:19:06 -030060 database.db.connect()
61 try:
62 with database.db.atomic():
Benjamin Diazf7451f82019-04-01 14:56:26 -030063 vnfrs = self.db_client.get_vnfrs(nsr_id)
64 for vnfr in vnfrs:
65 log.debug("Processing vnfr: %s", vnfr)
garciadeblas4584f8e2021-05-14 16:50:06 +020066 vnfd = self.db_client.get_vnfd(vnfr["vnfd-id"])
67 for vdur in vnfr["vdur"]:
Benjamin Diazf7451f82019-04-01 14:56:26 -030068 vdu = next(
69 filter(
garciadeblas4584f8e2021-05-14 16:50:06 +020070 lambda vdu: vdu["id"] == vdur["vdu-id-ref"], vnfd["vdu"]
Benjamin Diazf7451f82019-04-01 14:56:26 -030071 )
72 )
garciadeblas4584f8e2021-05-14 16:50:06 +020073 if "alarm" in vdu:
74 alarm_descriptors = vdu["alarm"]
Benjamin Diazf7451f82019-04-01 14:56:26 -030075 for alarm_descriptor in alarm_descriptors:
76 try:
77 VnfAlarmRepository.get(
garciadeblas4584f8e2021-05-14 16:50:06 +020078 VnfAlarm.alarm_id
79 == alarm_descriptor["alarm-id"],
80 VnfAlarm.vnf_member_index
81 == vnfr["member-vnf-index-ref"],
82 VnfAlarm.vdu_name == vdur["name"],
83 VnfAlarm.nsr_id == nsr_id,
Benjamin Diazf7451f82019-04-01 14:56:26 -030084 )
garciadeblas4584f8e2021-05-14 16:50:06 +020085 log.debug(
86 "vdu %s already has an alarm configured with same id %s",
87 vdur["name"],
88 alarm_descriptor["alarm-id"],
89 )
Benjamin Diazf7451f82019-04-01 14:56:26 -030090 continue
91 except VnfAlarm.DoesNotExist:
92 pass
93 vnf_monitoring_param = next(
94 filter(
garciadeblas4584f8e2021-05-14 16:50:06 +020095 lambda param: param["id"]
96 == alarm_descriptor["vnf-monitoring-param-ref"],
97 vdu.get("monitoring-parameter", []),
garciaale7ce998f2020-12-03 18:05:24 -030098 ),
garciadeblas4584f8e2021-05-14 16:50:06 +020099 {},
Benjamin Diazf7451f82019-04-01 14:56:26 -0300100 )
garciadeblas4584f8e2021-05-14 16:50:06 +0200101 metric_name = self._get_metric_name(
102 vnf_monitoring_param
103 )
Atul Agarwale9228cf2021-03-19 10:11:38 +0000104 alarm_action = dict()
105 for action_type in ["ok", "insufficient-data", "alarm"]:
106 if "actions" in alarm_descriptor and action_type in alarm_descriptor["actions"]:
107 for url in alarm_descriptor["actions"][action_type]:
108 if "webhook" in alarm_action:
109 alarm_action["webhook"].append(url["url"])
110 else:
111 alarm_action["webhook"] = [url["url"]]
Benjamin Diazf7451f82019-04-01 14:56:26 -0300112 alarm_uuid = await self.mon_client.create_alarm(
Gianpietro Lavado41610192019-12-06 15:46:23 +0000113 metric_name=metric_name,
Benjamin Diazf7451f82019-04-01 14:56:26 -0300114 ns_id=nsr_id,
garciadeblas4584f8e2021-05-14 16:50:06 +0200115 vdu_name=vdur["name"],
116 vnf_member_index=vnfr["member-vnf-index-ref"],
117 threshold=alarm_descriptor["value"],
118 operation=alarm_descriptor["operation"],
Atul Agarwale9228cf2021-03-19 10:11:38 +0000119 action=str(alarm_action),
Benjamin Diazf7451f82019-04-01 14:56:26 -0300120 )
121 alarm = VnfAlarmRepository.create(
garciadeblas4584f8e2021-05-14 16:50:06 +0200122 alarm_id=alarm_descriptor["alarm-id"],
Benjamin Diazf7451f82019-04-01 14:56:26 -0300123 alarm_uuid=alarm_uuid,
124 nsr_id=nsr_id,
garciadeblas4584f8e2021-05-14 16:50:06 +0200125 vnf_member_index=vnfr["member-vnf-index-ref"],
126 vdu_name=vdur["name"],
Benjamin Diazf7451f82019-04-01 14:56:26 -0300127 )
garciadeblas4584f8e2021-05-14 16:50:06 +0200128 for action_type in ["ok", "insufficient-data", "alarm"]:
129 if (
130 "actions" in alarm_descriptor
131 and action_type in alarm_descriptor["actions"]
132 ):
133 for url in alarm_descriptor["actions"][
134 action_type
135 ]:
Benjamin Diazf7451f82019-04-01 14:56:26 -0300136 AlarmActionRepository.create(
137 type=action_type,
garciadeblas4584f8e2021-05-14 16:50:06 +0200138 url=url["url"],
139 alarm=alarm,
Benjamin Diazf7451f82019-04-01 14:56:26 -0300140 )
141 alarms_created.append(alarm)
142
Benjamin Diazacac7552019-05-23 14:19:06 -0300143 except Exception as e:
144 log.exception("Error configuring VNF alarms:")
145 if len(alarms_created) > 0:
146 log.debug("Cleaning alarm resources in MON")
147 for alarm in alarms_created:
148 try:
garciadeblas4584f8e2021-05-14 16:50:06 +0200149 await self.mon_client.delete_alarm(
150 alarm.nsr_id,
151 alarm.vnf_member_index,
152 alarm.vdu_name,
153 alarm.alarm_uuid,
154 )
Benjamin Diazacac7552019-05-23 14:19:06 -0300155 except ValueError:
garciadeblas4584f8e2021-05-14 16:50:06 +0200156 log.exception(
157 "Error deleting alarm in MON %s", alarm.alarm_uuid
158 )
Benjamin Diazacac7552019-05-23 14:19:06 -0300159 raise e
160 finally:
161 database.db.close()
Benjamin Diazf7451f82019-04-01 14:56:26 -0300162
163 async def delete_orphaned_alarms(self, nsr_id):
garciaale7ce998f2020-12-03 18:05:24 -0300164 # TODO: Review as it seems this code is never called
Benjamin Diazf7451f82019-04-01 14:56:26 -0300165 log.info("Deleting orphaned vnf alarms for network service %s", nsr_id)
166 database.db.connect()
Benjamin Diazacac7552019-05-23 14:19:06 -0300167 try:
168 with database.db.atomic():
Benjamin Diazf7451f82019-04-01 14:56:26 -0300169 for alarm in VnfAlarmRepository.list(VnfAlarm.nsr_id == nsr_id):
170 try:
garciadeblas4584f8e2021-05-14 16:50:06 +0200171 self.db_client.get_vdur(
172 nsr_id, alarm.vnf_member_index, alarm.vdu_name
173 )
Benjamin Diazf7451f82019-04-01 14:56:26 -0300174 except VdurNotFound:
175 log.debug("Deleting orphaned alarm %s", alarm.alarm_uuid)
176 try:
177 await self.mon_client.delete_alarm(
178 alarm.nsr_id,
179 alarm.vnf_member_index,
180 alarm.vdu_name,
garciadeblas4584f8e2021-05-14 16:50:06 +0200181 alarm.alarm_uuid,
182 )
Benjamin Diazf7451f82019-04-01 14:56:26 -0300183 except ValueError:
garciadeblas4584f8e2021-05-14 16:50:06 +0200184 log.exception(
185 "Error deleting alarm in MON %s", alarm.alarm_uuid
186 )
Benjamin Diazf7451f82019-04-01 14:56:26 -0300187 alarm.delete_instance()
Benjamin Diazacac7552019-05-23 14:19:06 -0300188 except Exception as e:
189 log.exception("Error deleting orphaned alarms:")
190 raise e
191 finally:
192 database.db.close()
Benjamin Diazf7451f82019-04-01 14:56:26 -0300193
194 async def delete_vnf_alarms(self, nsr_id):
195 log.info("Deleting vnf alarms for network service %s", nsr_id)
196 database.db.connect()
Benjamin Diazacac7552019-05-23 14:19:06 -0300197 try:
198 with database.db.atomic():
Benjamin Diazf7451f82019-04-01 14:56:26 -0300199 for alarm in VnfAlarmRepository.list(VnfAlarm.nsr_id == nsr_id):
200 log.debug("Deleting vnf alarm %s", alarm.alarm_uuid)
201 try:
202 await self.mon_client.delete_alarm(
203 alarm.nsr_id,
204 alarm.vnf_member_index,
205 alarm.vdu_name,
garciadeblas4584f8e2021-05-14 16:50:06 +0200206 alarm.alarm_uuid,
207 )
Benjamin Diazf7451f82019-04-01 14:56:26 -0300208 except ValueError:
garciadeblas4584f8e2021-05-14 16:50:06 +0200209 log.exception(
210 "Error deleting alarm in MON %s", alarm.alarm_uuid
211 )
Benjamin Diazf7451f82019-04-01 14:56:26 -0300212 alarm.delete_instance()
213
Benjamin Diazacac7552019-05-23 14:19:06 -0300214 except Exception as e:
215 log.exception("Error deleting vnf alarms:")
216 raise e
217 finally:
218 database.db.close()
Benjamin Diazf7451f82019-04-01 14:56:26 -0300219
220 async def handle_alarm(self, alarm_uuid: str, status: str, payload: dict):
221 database.db.connect()
222 try:
223 with database.db.atomic():
224 alarm = VnfAlarmRepository.get(VnfAlarm.alarm_uuid == alarm_uuid)
garciadeblas4584f8e2021-05-14 16:50:06 +0200225 log.debug(
226 "Handling vnf alarm %s with status %s", alarm.alarm_id, status
227 )
Benjamin Diazf7451f82019-04-01 14:56:26 -0300228 for action in alarm.actions:
229 if action.type == status:
garciadeblas4584f8e2021-05-14 16:50:06 +0200230 log.info(
231 "Executing request to url %s for vnf alarm %s with status %s",
232 action.url,
233 alarm.alarm_id,
234 status,
235 )
Atul Agarwaldb8c1052020-04-28 15:42:28 +0530236 try:
237 requests.post(url=action.url, json=json.dumps(payload))
Atul Agarwal46e7efd2021-10-18 17:22:58 +0000238 except RequestException as e:
239 log.info("Error connecting to url %s", action.url)
240 log.debug("RequestException %s", e)
Atul Agarwaldb8c1052020-04-28 15:42:28 +0530241 except ConnectionError:
242 log.exception("Error connecting to url %s", action.url)
243
Benjamin Diazf7451f82019-04-01 14:56:26 -0300244 except VnfAlarm.DoesNotExist:
garciadeblas4584f8e2021-05-14 16:50:06 +0200245 log.debug(
246 "There is no alarming action configured for alarm %s.", alarm_uuid
247 )
Benjamin Diazf7451f82019-04-01 14:56:26 -0300248 finally:
249 database.db.close()
Gianpietro Lavado41610192019-12-06 15:46:23 +0000250
garciaale7ce998f2020-12-03 18:05:24 -0300251 def _get_metric_name(self, vnf_monitoring_param: dict):
garciadeblas4584f8e2021-05-14 16:50:06 +0200252 if "performance-metric" in vnf_monitoring_param:
253 return vnf_monitoring_param["performance-metric"]
254 raise ValueError(
255 "No metric name found for vnf_monitoring_param %s"
256 % vnf_monitoring_param["id"]
257 )