Update Openstack alarm/metric list functions 90/2290/1
authorHelena McGough <helena.mcgough@intel.com>
Fri, 22 Sep 2017 09:55:22 +0000 (10:55 +0100)
committerHelena McGough <helena.mcgough@intel.com>
Fri, 22 Sep 2017 15:20:43 +0000 (16:20 +0100)
 - Supports multiple imputs for list generation
 - Included resource_id as a mandatory parameter for alarm list

Signed-off-by: Helena McGough <helena.mcgough@intel.com>
plugins/OpenStack/Aodh/alarming.py
plugins/OpenStack/Gnocchi/metrics.py

index c54881a..3c6d4d1 100644 (file)
@@ -116,28 +116,9 @@ class Alarming(object):
                     # Check for a specifed: alarm_name, resource_uuid, severity
                     # and generate the appropriate list
                     list_details = values['alarm_list_request']
-                    try:
-                        name = list_details['alarm_name'].lower()
-                        alarm_list = self.list_alarms(
-                            endpoint, auth_token, alarm_name=name)
-                    except Exception as a_name:
-                        log.debug("No name specified for list:%s", a_name)
-                        try:
-                            resource = list_details['resource_uuid']
-                            alarm_list = self.list_alarms(
-                                endpoint, auth_token, resource_id=resource)
-                        except Exception as r_id:
-                            log.debug("No resource id specified for this list:\
-                                       %s", r_id)
-                            try:
-                                severe = list_details['severity'].lower()
-                                alarm_list = self.list_alarms(
-                                    endpoint, auth_token, severity=severe)
-                            except Exception as exc:
-                                log.info("No severity specified for list: %s.\
-                                           will return full list.", exc)
-                                alarm_list = self.list_alarms(
-                                    endpoint, auth_token)
+
+                    alarm_list = self.list_alarms(
+                        endpoint, auth_token, list_details)
 
                     try:
                         # Generate and send a list response back
@@ -261,34 +242,81 @@ class Alarming(object):
             log.warn("Failed to delete alarm: %s because %s.", alarm_id, exc)
         return False
 
-    def list_alarms(self, endpoint, auth_token,
-                    alarm_name=None, resource_id=None, severity=None):
+    def list_alarms(self, endpoint, auth_token, list_details):
         """Generate the requested list of alarms."""
         url = "{}/v2/alarms/".format(endpoint)
-        alarm_list = []
-
-        result = self._common._perform_request(
-            url, auth_token, req_type="get")
-        if result is not None:
-            # Check for a specified list based on:
-            # alarm_name, severity, resource_id
-            if alarm_name is not None:
-                for alarm in json.loads(result.text):
-                    if alarm_name in str(alarm):
-                        alarm_list.append(str(alarm))
-            elif resource_id is not None:
-                for alarm in json.loads(result.text):
-                    if resource_id in str(alarm):
-                        alarm_list.append(str(alarm))
-            elif severity is not None:
+        a_list, name_list, sev_list, res_list = [], [], [], []
+
+        # TODO(mcgoughh): for now resource_id is a mandatory field
+        resource = list_details['resource_uuid']
+
+        # Checking what fields are specified for a list request
+        try:
+            name = list_details['alarm_name'].lower()
+            if name not in ALARM_NAMES.keys():
+                log.warn("This alarm is not supported, won't be used!")
+                name = None
+        except KeyError as exc:
+            log.info("Alarm name isn't specified.")
+            name = None
+
+        try:
+            severity = list_details['severity'].lower()
+            sev = SEVERITIES[severity]
+        except KeyError as exc:
+            log.info("Severity is unspecified/incorrectly configured")
+            sev = None
+
+        # Perform the request to get the desired list
+        try:
+            result = self._common._perform_request(
+                url, auth_token, req_type="get")
+
+            if result is not None:
+                # Get list based on resource id
                 for alarm in json.loads(result.text):
-                    if severity in str(alarm):
-                        alarm_list.append(str(alarm))
+                    rule = alarm['gnocchi_resources_threshold_rule']
+                    if resource == rule['resource_id']:
+                        res_list.append(str(alarm))
+                    if not res_list:
+                        log.info("No alarms for this resource")
+                        return a_list
+
+                # Generate specified listed if requested
+                if name is not None and sev is not None:
+                    log.info("Return a list of %s alarms with %s severity.",
+                             name, sev)
+                    for alarm in json.loads(result.text):
+                        if name == alarm['name']:
+                            name_list.append(str(alarm))
+                    for alarm in json.loads(result.text):
+                        if sev == alarm['severity']:
+                            sev_list.append(str(alarm))
+                    name_sev_list = list(set(name_list).intersection(sev_list))
+                    a_list = list(set(name_sev_list).intersection(res_list))
+                elif name is not None:
+                    log.info("Returning a %s list of alarms.", name)
+                    for alarm in json.loads(result.text):
+                        if name == alarm['name']:
+                            name_list.append(str(alarm))
+                    a_list = list(set(name_list).intersection(res_list))
+                elif sev is not None:
+                    log.info("Returning %s severity alarm list.", sev)
+                    for alarm in json.loads(result.text):
+                        if sev == alarm['severity']:
+                            sev_list.append(str(alarm))
+                    a_list = list(set(sev_list).intersection(res_list))
+                else:
+                    log.info("Returning an entire list of alarms.")
+                    a_list = res_list
             else:
-                alarm_list = result.text
-        else:
+                log.info("There are no alarms!")
+
+        except Exception as exc:
+            log.info("Failed to generate required list: %s", exc)
             return None
-        return alarm_list
+
+        return a_list
 
     def update_alarm_state(self, endpoint, auth_token, alarm_id):
         """Set the state of an alarm to ok when ack message is received."""
index 2004c38..7b13547 100644 (file)
@@ -283,43 +283,53 @@ class Metrics(object):
         """List all metrics."""
         url = "{}/v1/metric/".format(endpoint)
 
+        # Check for a specified list
         try:
             # Check if the metric_name was specified for the list
-            metric_name = values['metric_name']
-            result = self._common._perform_request(
-                url, auth_token, req_type="get")
-            metric_list = json.loads(result.text)
+            metric_name = values['metric_name'].lower()
+            if metric_name not in METRIC_MAPPINGS.keys():
+                log.warn("This metric is not supported, won't be listed.")
+                metric_name = None
+        except KeyError as exc:
+            log.info("Metric name is not specified: %s", exc)
+            metric_name = None
 
-            # Format the list response
-            metrics = self.response_list(
-                metric_list, metric_name=metric_name)
-            return metrics
-        except KeyError:
-            log.debug("Metric name is not specified for this list.")
+        try:
+            resource = values['resource_uuid']
+        except KeyError as exc:
+            log.info("Resource is not specified:%s", exc)
+            resource = None
 
         try:
-            # Check if a resource_id was specified
-            resource_id = values['resource_uuid']
             result = self._common._perform_request(
                 url, auth_token, req_type="get")
-            metric_list = json.loads(result.text)
-            # Format the list response
-            metrics = self.response_list(
-                metric_list, resource=resource_id)
-            return metrics
-        except KeyError:
-            log.debug("Resource id not specificed either, will return a\
-                       complete list.")
-            try:
-                result = self._common._perform_request(
-                    url, auth_token, req_type="get")
-                metric_list = json.loads(result.text)
+            metrics = json.loads(result.text)
+
+            if metrics is not None:
                 # Format the list response
-                metrics = self.response_list(metric_list)
-                return metrics
+                if metric_name is not None and resource is not None:
+                    metric_list = self.response_list(
+                        metrics, metric_name=metric_name, resource=resource)
+                    log.info("Returning an %s resource list for %s metrics",
+                             metric_name, resource)
+                elif metric_name is not None:
+                    metric_list = self.response_list(
+                        metrics, metric_name=metric_name)
+                    log.info("Returning a list of %s metrics", metric_name)
+                elif resource is not None:
+                    metric_list = self.response_list(
+                        metrics, resource=resource)
+                    log.info("Return a list of %s resource metrics", resource)
+                else:
+                    metric_list = self.response_list(metrics)
+                    log.info("Returning a complete list of metrics")
 
-            except Exception as exc:
-                log.warn("Failed to generate any metric list. %s", exc)
+                return metric_list
+            else:
+                log.info("There are no metrics available")
+                return []
+        except Exception as exc:
+            log.warn("Failed to generate any metric list. %s", exc)
         return None
 
     def get_metric_id(self, endpoint, auth_token, metric_name, resource_id):
@@ -398,27 +408,40 @@ class Metrics(object):
 
     def response_list(self, metric_list, metric_name=None, resource=None):
         """Create the appropriate lists for a list response."""
-        resp_list = []
+        resp_list, name_list, res_list = [], [], []
 
+        # Create required lists
         for row in metric_list:
+            # Only list OSM metrics
+            if row['name'] in METRIC_MAPPINGS.keys():
+                metric = {"metric_name": row['name'],
+                          "metric_uuid": row['id'],
+                          "metric_unit": row['unit'],
+                          "resource_uuid": row['resource_id']}
+                resp_list.append(str(metric))
+            # Generate metric_name specific list
             if metric_name is not None:
                 if row['name'] == metric_name:
                     metric = {"metric_name": row['name'],
                               "metric_uuid": row['id'],
                               "metric_unit": row['unit'],
                               "resource_uuid": row['resource_id']}
-                    resp_list.append(metric)
-            elif resource is not None:
+                    name_list.append(str(metric))
+            # Generate resource specific list
+            if resource is not None:
                 if row['resource_id'] == resource:
                     metric = {"metric_name": row['name'],
                               "metric_uuid": row['id'],
                               "metric_unit": row['unit'],
                               "resource_uuid": row['resource_id']}
-                    resp_list.append(metric)
-            else:
-                metric = {"metric_name": row['name'],
-                          "metric_uuid": row['id'],
-                          "metric_unit": row['unit'],
-                          "resource_uuid": row['resource_id']}
-                resp_list.append(metric)
-        return resp_list
+                    res_list.append(str(metric))
+
+        # Join required lists
+        if metric_name is not None and resource is not None:
+            return list(set(res_list).intersection(name_list))
+        elif metric_name is not None:
+            return name_list
+        elif resource is not None:
+            return list(set(res_list).intersection(resp_list))
+        else:
+            return resp_list