Storage: add 'exclude' constraint to get_alarms()

This patch adds a new parameter 'exclude' to get_alarms() as a constraint
by which a caller can filter out uninteresting alarms.

Change-Id: I8ce1481eccfa916cf1fd8921d57ed529d5b5271a
Implements: blueprint event-alarm-evaluator
This commit is contained in:
Ryota MIBU 2015-07-13 10:29:48 +09:00
parent acd541577f
commit c5c6e87aa0
9 changed files with 36 additions and 9 deletions

View File

@ -75,7 +75,7 @@ class Connection(object):
@staticmethod @staticmethod
def get_alarms(name=None, user=None, state=None, meter=None, def get_alarms(name=None, user=None, state=None, meter=None,
project=None, enabled=None, alarm_id=None, project=None, enabled=None, alarm_id=None,
alarm_type=None, severity=None): alarm_type=None, severity=None, exclude=None):
"""Yields a lists of alarms that match filters. """Yields a lists of alarms that match filters.
:param name: Optional name for alarm. :param name: Optional name for alarm.
@ -86,7 +86,8 @@ class Connection(object):
:param enabled: Optional boolean to list disable alarm. :param enabled: Optional boolean to list disable alarm.
:param alarm_id: Optional alarm_id to return one alarm. :param alarm_id: Optional alarm_id to return one alarm.
:param alarm_type: Optional alarm type. :param alarm_type: Optional alarm type.
:parmr severity: Optional alarm severity :param severity: Optional alarm severity.
:param exclude: Optional dict for inequality constraint.
""" """
raise aodh.NotImplementedError('Alarms not implemented') raise aodh.NotImplementedError('Alarms not implemented')

View File

@ -188,6 +188,8 @@ class MTable(object):
""" """
op = args[0] op = args[0]
value = args[1] value = args[1]
if value.startswith('binary:'):
value = value[len('binary:'):]
if value.startswith('regexstring:'): if value.startswith('regexstring:'):
value = value[len('regexstring:'):] value = value[len('regexstring:'):]
r = {} r = {}

View File

@ -117,6 +117,11 @@ def make_query(**kwargs):
q.append("ColumnPrefixFilter('%s')" % value) q.append("ColumnPrefixFilter('%s')" % value)
elif key == 'event_id': elif key == 'event_id':
q.append("RowFilter ( = , 'regexstring:\d*:%s')" % value) q.append("RowFilter ( = , 'regexstring:\d*:%s')" % value)
elif key == 'exclude':
for k, v in six.iteritems(value):
q.append("SingleColumnValueFilter "
"('f', '%(k)s', !=, 'binary:%(v)s', true, true)" %
{'k': quote(k), 'v': dump(v)})
else: else:
q.append("SingleColumnValueFilter " q.append("SingleColumnValueFilter "
"('f', '%s', =, 'binary:%s', true, true)" % "('f', '%s', =, 'binary:%s', true, true)" %

View File

@ -123,7 +123,7 @@ class Connection(hbase_base.Connection, base.Connection):
def get_alarms(self, name=None, user=None, state=None, meter=None, def get_alarms(self, name=None, user=None, state=None, meter=None,
project=None, enabled=None, alarm_id=None, project=None, enabled=None, alarm_id=None,
alarm_type=None, severity=None): alarm_type=None, severity=None, exclude=None):
if meter: if meter:
raise aodh.NotImplementedError( raise aodh.NotImplementedError(
@ -132,7 +132,8 @@ class Connection(hbase_base.Connection, base.Connection):
q = hbase_utils.make_query(alarm_id=alarm_id, name=name, q = hbase_utils.make_query(alarm_id=alarm_id, name=name,
enabled=enabled, user_id=user, enabled=enabled, user_id=user,
project_id=project, state=state, project_id=project, state=state,
type=alarm_type, severity=severity) type=alarm_type, severity=severity,
exclude=exclude)
with self.conn_pool.connection() as conn: with self.conn_pool.connection() as conn:
alarm_table = conn.table(self.ALARM_TABLE) alarm_table = conn.table(self.ALARM_TABLE)

View File

@ -37,7 +37,7 @@ class Connection(base.Connection):
@staticmethod @staticmethod
def get_alarms(name=None, user=None, state=None, meter=None, def get_alarms(name=None, user=None, state=None, meter=None,
project=None, enabled=None, alarm_id=None, project=None, enabled=None, alarm_id=None,
alarm_type=None, severity=None): alarm_type=None, severity=None, exclude=None):
"""Yields a lists of alarms that match filters.""" """Yields a lists of alarms that match filters."""
return [] return []

View File

@ -22,6 +22,7 @@ from alembic import migration
from oslo_db.sqlalchemy import session as db_session from oslo_db.sqlalchemy import session as db_session
from oslo_log import log from oslo_log import log
from oslo_utils import timeutils from oslo_utils import timeutils
import six
from sqlalchemy import desc from sqlalchemy import desc
from aodh.i18n import _LI from aodh.i18n import _LI
@ -141,7 +142,7 @@ class Connection(base.Connection):
def get_alarms(self, name=None, user=None, state=None, meter=None, def get_alarms(self, name=None, user=None, state=None, meter=None,
project=None, enabled=None, alarm_id=None, project=None, enabled=None, alarm_id=None,
alarm_type=None, severity=None): alarm_type=None, severity=None, exclude=None):
"""Yields a lists of alarms that match filters. """Yields a lists of alarms that match filters.
:param name: Optional name for alarm. :param name: Optional name for alarm.
@ -152,7 +153,8 @@ class Connection(base.Connection):
:param enabled: Optional boolean to list disable alarm. :param enabled: Optional boolean to list disable alarm.
:param alarm_id: Optional alarm_id to return one alarm. :param alarm_id: Optional alarm_id to return one alarm.
:param alarm_type: Optional alarm type. :param alarm_type: Optional alarm type.
:param severity: Optional alarm severity :param severity: Optional alarm severity.
:param exclude: Optional dict for inequality constraint.
""" """
session = self._engine_facade.get_session() session = self._engine_facade.get_session()
@ -173,6 +175,9 @@ class Connection(base.Connection):
query = query.filter(models.Alarm.type == alarm_type) query = query.filter(models.Alarm.type == alarm_type)
if severity is not None: if severity is not None:
query = query.filter(models.Alarm.severity == severity) query = query.filter(models.Alarm.severity == severity)
if exclude is not None:
for key, value in six.iteritems(exclude):
query = query.filter(getattr(models.Alarm, key) != value)
query = query.order_by(desc(models.Alarm.timestamp)) query = query.order_by(desc(models.Alarm.timestamp))
alarms = self._retrieve_alarms(query) alarms = self._retrieve_alarms(query)

View File

@ -20,6 +20,7 @@
from oslo_log import log from oslo_log import log
import pymongo import pymongo
import six
from aodh.storage import base from aodh.storage import base
from aodh.storage import models from aodh.storage import models
@ -87,7 +88,7 @@ class Connection(base.Connection):
def get_alarms(self, name=None, user=None, state=None, meter=None, def get_alarms(self, name=None, user=None, state=None, meter=None,
project=None, enabled=None, alarm_id=None, project=None, enabled=None, alarm_id=None,
alarm_type=None, severity=None): alarm_type=None, severity=None, exclude=None):
"""Yields a lists of alarms that match filters. """Yields a lists of alarms that match filters.
:param name: Optional name for alarm. :param name: Optional name for alarm.
@ -99,6 +100,7 @@ class Connection(base.Connection):
:param alarm_id: Optional alarm_id to return one alarm. :param alarm_id: Optional alarm_id to return one alarm.
:param alarm_type: Optional alarm type. :param alarm_type: Optional alarm type.
:param severity: Optional alarm severity. :param severity: Optional alarm severity.
:param exclude: Optional dict for inequality constraint.
""" """
q = {} q = {}
if user is not None: if user is not None:
@ -119,6 +121,9 @@ class Connection(base.Connection):
q['type'] = alarm_type q['type'] = alarm_type
if severity is not None: if severity is not None:
q['severity'] = severity q['severity'] = severity
if exclude is not None:
for key, value in six.iteritems(exclude):
q[key] = {'$ne': value}
return self._retrieve_alarms(q, return self._retrieve_alarms(q,
[("timestamp", [("timestamp",

View File

@ -325,7 +325,7 @@ class TestQueryToKwArgs(tests_base.BaseTestCase):
wsme.exc.UnknownArgument, wsme.exc.UnknownArgument,
utils.query_to_kwargs, q, utils.query_to_kwargs, q,
alarm_storage_base.Connection.get_alarms) alarm_storage_base.Connection.get_alarms)
valid_keys = ['alarm_id', 'enabled', 'meter', 'name', valid_keys = ['alarm_id', 'enabled', 'exclude', 'meter', 'name',
'project', 'severity', 'state', 'type', 'user'] 'project', 'severity', 'state', 'type', 'user']
msg = ("unrecognized field in query: %s, " msg = ("unrecognized field in query: %s, "
"valid keys: %s") % (q, valid_keys) "valid keys: %s") % (q, valid_keys)

View File

@ -177,6 +177,14 @@ class AlarmTest(AlarmTestBase,
alarms = list(self.alarm_conn.get_alarms(alarm_type='combination')) alarms = list(self.alarm_conn.get_alarms(alarm_type='combination'))
self.assertEqual(0, len(alarms)) self.assertEqual(0, len(alarms))
def test_list_excluded_by_name(self):
self.add_some_alarms()
exclude = {'name': 'yellow-alert'}
alarms = list(self.alarm_conn.get_alarms(exclude=exclude))
self.assertEqual(2, len(alarms))
alarm_names = sorted([a.name for a in alarms])
self.assertEqual(['orange-alert', 'red-alert'], alarm_names)
def test_add(self): def test_add(self):
self.add_some_alarms() self.add_some_alarms()
alarms = list(self.alarm_conn.get_alarms()) alarms = list(self.alarm_conn.get_alarms())