Adds support for multiple alarm statuses 22/7322/3
authorBenjamin Diaz <bdiaz@whitestack.com>
Wed, 6 Mar 2019 18:53:56 +0000 (15:53 -0300)
committerBenjamin Diaz <bdiaz@whitestack.com>
Fri, 5 Apr 2019 20:53:25 +0000 (17:53 -0300)
Requirement for Feature 6373

Change-Id: I5440c6cdd8e4b3ad12bcf8949871c67a74f31500
Signed-off-by: Benjamin Diaz <bdiaz@whitestack.com>
osm_mon/collector/vnf_collectors/openstack.py
osm_mon/core/common_db.py
osm_mon/core/database.py
osm_mon/evaluator/evaluator.py

index 4cf798f..33d6299 100644 (file)
@@ -115,7 +115,14 @@ class OpenstackCollector(BaseVimCollector):
                 for param in vdu['monitoring-param']:
                     metric_name = param['nfvi-metric']
                     openstack_metric_name = METRIC_MAPPINGS[metric_name]
-                    resource_id = self._get_resource_uuid(nsr_id, vnf_member_index, vdur['name'])
+                    try:
+                        resource_id = self._get_resource_uuid(nsr_id, vnf_member_index, vdur['name'])
+                    except ValueError:
+                        log.warning(
+                            "Could not find resource_uuid for vdur %s, vnf_member_index %s, nsr_id %s. "
+                            "Was it recently deleted?".format(
+                                vdur['name'], vnf_member_index, nsr_id))
+                        continue
                     if self.backend == 'ceilometer':
                         measures = self.client.samples.list(meter_name=openstack_metric_name, limit=1, q=[
                             {'field': 'resource_id', 'op': 'eq', 'value': resource_id}])
index 2d31f6c..12c15dc 100644 (file)
@@ -74,8 +74,8 @@ class CommonDbClient:
         for vdur in vnfr['vdur']:
             if vdur['name'] == vdur_name:
                 return vdur
-        raise ValueError('vdur not found for nsr-id %s, member_index %s and vdur_name %s', nsr_id, member_index,
-                         vdur_name)
+        raise ValueError('vdur not found for nsr-id {}, member_index {} and vdur_name {}'.format(nsr_id, member_index,
+                         vdur_name))
 
     def decrypt_vim_password(self, vim_password: str, schema_version: str, vim_id: str):
         return self.common_db.decrypt(vim_password, schema_version, vim_id)
index 3b601b2..d1c2e6b 100644 (file)
 # contact: bdiaz@whitestack.com or glavado@whitestack.com
 ##
 
+import json
 import logging
 import os
 import uuid
-import json
 
 from peewee import CharField, TextField, FloatField, Model, AutoField, Proxy
 from peewee_migrate import Router
@@ -83,51 +83,59 @@ class DatabaseManager:
 
     def get_credentials(self, vim_uuid: str = None) -> VimCredentials:
         db.connect()
-        with db.atomic():
-            vim_credentials = VimCredentials.get_or_none(VimCredentials.uuid == vim_uuid)
-        db.close()
-        return vim_credentials
+        try:
+            with db.atomic():
+                vim_credentials = VimCredentials.get_or_none(VimCredentials.uuid == vim_uuid)
+                return vim_credentials
+        finally:
+            db.close()
 
     def save_credentials(self, vim_credentials) -> VimCredentials:
         """Saves vim credentials. If a record with same uuid exists, overwrite it."""
         db.connect()
-        with db.atomic():
-            exists = VimCredentials.get_or_none(VimCredentials.uuid == vim_credentials.uuid)
-            if exists:
-                vim_credentials.id = exists.id
-            vim_credentials.save()
-        db.close()
-        return vim_credentials
+        try:
+            with db.atomic():
+                exists = VimCredentials.get_or_none(VimCredentials.uuid == vim_credentials.uuid)
+                if exists:
+                    vim_credentials.id = exists.id
+                vim_credentials.save()
+                return vim_credentials
+        finally:
+            db.close()
 
     def get_alarm(self, alarm_id) -> Alarm:
         db.connect()
-        with db.atomic():
-            alarm = (Alarm.select()
-                     .where(Alarm.alarm_id == alarm_id)
-                     .get())
-        db.close()
-        return alarm
+        try:
+            with db.atomic():
+                alarm = (Alarm.select()
+                         .where(Alarm.alarm_id == alarm_id)
+                         .get())
+                return alarm
+        finally:
+            db.close()
 
     def save_alarm(self, name, threshold, operation, severity, statistic, metric_name, vdur_name,
                    vnf_member_index, nsr_id) -> Alarm:
         """Saves alarm."""
         # TODO: Add uuid optional param and check if exists to handle updates (see self.save_credentials)
         db.connect()
-        with db.atomic():
-            alarm = Alarm()
-            alarm.uuid = str(uuid.uuid4())
-            alarm.name = name
-            alarm.threshold = threshold
-            alarm.operation = operation
-            alarm.severity = severity
-            alarm.statistic = statistic
-            alarm.monitoring_param = metric_name
-            alarm.vdur_name = vdur_name
-            alarm.vnf_member_index = vnf_member_index
-            alarm.nsr_id = nsr_id
-            alarm.save()
-        db.close()
-        return alarm
+        try:
+            with db.atomic():
+                alarm = Alarm()
+                alarm.uuid = str(uuid.uuid4())
+                alarm.name = name
+                alarm.threshold = threshold
+                alarm.operation = operation
+                alarm.severity = severity
+                alarm.statistic = statistic
+                alarm.monitoring_param = metric_name
+                alarm.vdur_name = vdur_name
+                alarm.vnf_member_index = vnf_member_index
+                alarm.nsr_id = nsr_id
+                alarm.save()
+                return alarm
+        finally:
+            db.close()
 
     def delete_alarm(self, alarm_uuid) -> None:
         db.connect()
@@ -140,7 +148,6 @@ class DatabaseManager:
 
     def get_vim_type(self, vim_account_id) -> str:
         """Get the vim type that is required by the message."""
-        vim_type = None
         credentials = self.get_credentials(vim_account_id)
         config = json.loads(credentials.config)
         if 'vim_type' in config:
index 76881b9..90c0c17 100644 (file)
@@ -24,6 +24,7 @@ import asyncio
 import logging
 import multiprocessing
 import time
+from enum import Enum
 
 import peewee
 import requests
@@ -39,7 +40,14 @@ from osm_mon.core.response import ResponseBuilder
 log = logging.getLogger(__name__)
 
 
+class AlarmStatus(Enum):
+    ALARM = 'alarm'
+    OK = 'ok'
+    INSUFFICIENT = 'insufficient-data'
+
+
 class Evaluator:
+
     def __init__(self, config: Config, loop=None):
         self.conf = config
         if not loop:
@@ -74,12 +82,18 @@ class Evaluator:
                     log.info("Metric value: %s", metric_value)
                     if alarm.operation.upper() == 'GT':
                         if metric_value > alarm.threshold:
-                            self.queue.put(alarm)
+                            self.queue.put((alarm, AlarmStatus.ALARM))
+                        else:
+                            self.queue.put((alarm, AlarmStatus.OK))
                     elif alarm.operation.upper() == 'LT':
                         if metric_value < alarm.threshold:
-                            self.queue.put(alarm)
+                            self.queue.put((alarm, AlarmStatus.ALARM))
+                        else:
+                            self.queue.put((alarm, AlarmStatus.OK))
                 else:
                     log.warning("No metric result for alarm %s", alarm.id)
+                    self.queue.put((alarm, AlarmStatus.INSUFFICIENT))
+
             else:
                 log.warning("Prometheus response is not success. Got status %s", json_response['status'])
         else:
@@ -155,20 +169,24 @@ class Evaluator:
 
         for process in processes:
             process.join(timeout=10)
-        triggered_alarms = []
+        alarms_tuples = []
         while not self.queue.empty():
-            triggered_alarms.append(self.queue.get())
-        for alarm in triggered_alarms:
+            alarms_tuples.append(self.queue.get())
+        for alarm, status in alarms_tuples:
             p = multiprocessing.Process(target=self.notify_alarm,
-                                        args=(alarm,))
+                                        args=(alarm, status))
             p.start()
 
-    def notify_alarm(self, alarm: Alarm):
+    def notify_alarm(self, alarm: Alarm, status: AlarmStatus):
         log.debug("notify_alarm")
+        resp_message = self._build_alarm_response(alarm, status)
+        log.info("Sent alarm notification: %s", resp_message)
+        self.loop.run_until_complete(self.msg_bus.aiowrite('alarm_response', 'notify_alarm', resp_message))
+
+    def _build_alarm_response(self, alarm: Alarm, status: AlarmStatus):
         response = ResponseBuilder()
         now = time.strftime("%d-%m-%Y") + " " + time.strftime("%X")
-        # Generate and send response
-        resp_message = response.generate_response(
+        return response.generate_response(
             'notify_alarm',
             alarm_id=alarm.uuid,
             vdu_name=alarm.vdur_name,
@@ -178,7 +196,5 @@ class Evaluator:
             operation=alarm.operation,
             threshold_value=alarm.threshold,
             sev=alarm.severity,
-            status='alarm',
+            status=status.value,
             date=now)
-        self.loop.run_until_complete(self.msg_bus.aiowrite('alarm_response', 'notify_alarm', resp_message))
-        log.info("Sent alarm notification: %s", resp_message)