import asyncio
import json
import logging
+import operator
+import functools
import requests
-from requests.exceptions import ConnectionError
+from requests.exceptions import ConnectionError, RequestException
from osm_policy_module.common.common_db_client import CommonDbClient
from osm_policy_module.common.lcm_client import LcmClient
self.mon_client = MonClient(config, loop=self.loop)
self.lcm_client = LcmClient(config, loop=self.loop)
- async def configure_vnf_alarms(self, nsr_id: str):
+ async def configure_vnf_alarms(self, nsr_id: str, vnf_member_index=None):
log.info("Configuring vnf alarms for network service %s", nsr_id)
alarms_created = []
database.db.connect()
try:
with database.db.atomic():
- vnfrs = self.db_client.get_vnfrs(nsr_id)
+ if vnf_member_index is None:
+ vnfrs = self.db_client.get_vnfrs(nsr_id)
+ else:
+ vnfrs = []
+ vnfr = self.db_client.get_vnfr(nsr_id, vnf_member_index)
+ vnfrs.append(vnfr)
+ # vnfrs = self.db_client.get_vnfrs(nsr_id)
for vnfr in vnfrs:
log.debug("Processing vnfr: %s", vnfr)
vnfd = self.db_client.get_vnfd(vnfr["vnfd-id"])
metric_name = self._get_metric_name(
vnf_monitoring_param
)
+ alarm_action = dict()
+ for action_type in ["ok", "insufficient-data", "alarm"]:
+ if "actions" in alarm_descriptor and action_type in alarm_descriptor["actions"]:
+ for url in alarm_descriptor["actions"][action_type]:
+ if "webhook" in alarm_action:
+ alarm_action["webhook"].append(url["url"])
+ else:
+ alarm_action["webhook"] = [url["url"]]
alarm_uuid = await self.mon_client.create_alarm(
metric_name=metric_name,
ns_id=nsr_id,
vnf_member_index=vnfr["member-vnf-index-ref"],
threshold=alarm_descriptor["value"],
operation=alarm_descriptor["operation"],
+ action=str(alarm_action),
)
alarm = VnfAlarmRepository.create(
alarm_id=alarm_descriptor["alarm-id"],
nsr_id=nsr_id,
vnf_member_index=vnfr["member-vnf-index-ref"],
vdu_name=vdur["name"],
+ last_action='insufficient-data',
+ id_suffix=0,
+ ok_ack=False,
+ alarm_ack=False
)
for action_type in ["ok", "insufficient-data", "alarm"]:
if (
finally:
database.db.close()
- async def delete_vnf_alarms(self, nsr_id):
+ async def delete_vnf_alarms(self, nsr_id, vnf_member_index=None):
log.info("Deleting vnf alarms for network service %s", nsr_id)
database.db.connect()
try:
with database.db.atomic():
- for alarm in VnfAlarmRepository.list(VnfAlarm.nsr_id == nsr_id):
+ if vnf_member_index is None:
+ alarm_conditions = VnfAlarm.nsr_id == nsr_id
+ else:
+ query_list = [VnfAlarm.nsr_id == nsr_id,
+ VnfAlarm.vnf_member_index == vnf_member_index]
+ alarm_conditions = functools.reduce(operator.and_, query_list)
+ for alarm in VnfAlarmRepository.list(alarm_conditions):
log.debug("Deleting vnf alarm %s", alarm.alarm_uuid)
try:
await self.mon_client.delete_alarm(
database.db.close()
async def handle_alarm(self, alarm_uuid: str, status: str, payload: dict):
+ alert_timeout = int(self.conf.get('alert', 'timeout'))
database.db.connect()
try:
with database.db.atomic():
"Handling vnf alarm %s with status %s", alarm.alarm_id, status
)
for action in alarm.actions:
+ """
+ Compares the current status with the last_action status.
+ If both the status are 'alarm', it avoid sending repetitive alarm notification.
+ If both the status are 'ok', it avoid sending repetitive ok notification.
+ """
if action.type == status:
- log.info(
- "Executing request to url %s for vnf alarm %s with status %s",
- action.url,
- alarm.alarm_id,
- status,
- )
- try:
- requests.post(url=action.url, json=json.dumps(payload))
- except ConnectionError:
- log.exception("Error connecting to url %s", action.url)
+ if bool(self.conf.get('alert', 'enhanced_alarms')):
+ if ((status != "ok" or (status == "ok" and alarm.ok_ack is False)) and
+ (status != "alarm" or (status == "alarm" and alarm.alarm_ack is False))):
+ log.info(
+ "Executing request to url %s for vnf alarm %s with status %s",
+ action.url,
+ alarm.alarm_id,
+ status
+ )
+ try:
+ if status == "alarm" and alarm.last_action == "ok":
+ alarm.id_suffix += 1
+ alarm.ok_ack = False
+ if status == "ok" and alarm.last_action == "alarm":
+ alarm.alarm_ack = False
+ alarm.last_action = status
+ alarm.save()
+ except Exception as e:
+ log.exception(e)
+
+ payload["notify_details"]["alarm_number"] = alarm.id_suffix
+ headers = {"content-type": "application/json"}
+ try:
+ resp = requests.post(url=action.url, data=json.dumps(payload),
+ headers=headers, verify=False, timeout=alert_timeout)
+ log.info("Response %s", resp)
+ if resp.status_code == 200:
+ if status == "ok":
+ alarm.ok_ack = True
+ alarm.save()
+ if status == "alarm":
+ alarm.alarm_ack = True
+ alarm.save()
+ if status == "insufficient-data":
+ alarm.alarm_ack = False
+ alarm.ok_ack = False
+ alarm.save()
+ except RequestException as e:
+ log.info("Error: RequestException while connecting to url %s", action.url)
+ log.debug("RequestException %s", e)
+
+ except ConnectionError:
+ log.exception("Error connecting to url %s", action.url)
+ else:
+ log.info(
+ "Executing request to url %s for vnf alarm %s with status %s",
+ action.url,
+ alarm.alarm_id,
+ status
+ )
+ try:
+ requests.post(url=action.url, json=json.dumps(payload), timeout=alert_timeout)
+ except RequestException as e:
+ log.info("Error: RequestException while connecting to url %s", action.url)
+ log.debug("RequestException %s", e)
+ except ConnectionError:
+ log.exception("Error connecting to url %s", action.url)
except VnfAlarm.DoesNotExist:
log.debug(