Merge "Add Alarm DB API and models"
This commit is contained in:
commit
1667ded277
@ -137,6 +137,22 @@ class Connection(object):
|
||||
The filter must have a meter value set.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_alarms(self, name=None, user=None,
|
||||
project=None, enabled=True, alarm_id=None):
|
||||
"""Yields a lists of alarms that match filters
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_alarm(self, alarm):
|
||||
"""update alarm
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_alarm(self, alarm_id):
|
||||
"""Delete a alarm
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def clear(self):
|
||||
"""Clear database."""
|
||||
|
@ -494,6 +494,23 @@ class Connection(base.Connection):
|
||||
self._update_meter_stats(results[-1], meter)
|
||||
return results
|
||||
|
||||
def get_alarms(self, name=None, user=None,
|
||||
project=None, enabled=True, alarm_id=None):
|
||||
"""Yields a lists of alarms that match filters
|
||||
raise NotImplementedError('metaquery not implemented')
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
def update_alarm(self, alarm):
|
||||
"""update alarm
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
def delete_alarm(self, alarm_id):
|
||||
"""Delete a alarm
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
|
||||
###############
|
||||
# This is a very crude version of "in-memory HBase", which implements just
|
||||
|
@ -145,3 +145,18 @@ class Connection(base.Connection):
|
||||
|
||||
"""
|
||||
return []
|
||||
|
||||
def get_alarms(self, name=None, user=None,
|
||||
project=None, enabled=True, alarm_id=None):
|
||||
"""Yields a lists of alarms that match filters
|
||||
"""
|
||||
return []
|
||||
|
||||
def update_alarm(self, alarm):
|
||||
"""update alarm
|
||||
"""
|
||||
return alarm
|
||||
|
||||
def delete_alarm(self, alarm_id):
|
||||
"""Delete a alarm
|
||||
"""
|
||||
|
@ -506,6 +506,22 @@ class Connection(base.Connection):
|
||||
a_max.valueOf() // 1000)
|
||||
return (a_min, a_max)
|
||||
|
||||
def get_alarms(self, name=None, user=None,
|
||||
project=None, enabled=True, alarm_id=None):
|
||||
"""Yields a lists of alarms that match filters
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
def update_alarm(self, alarm):
|
||||
"""update alarm
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
def delete_alarm(self, alarm_id):
|
||||
"""Delete a alarm
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
|
||||
def require_map_reduce(conn):
|
||||
"""Raises SkipTest if the connection is using mim.
|
||||
|
@ -411,3 +411,19 @@ class Connection(base.Connection):
|
||||
period_start=period_start,
|
||||
period_end=period_end,
|
||||
)
|
||||
|
||||
def get_alarms(self, name=None, user=None,
|
||||
project=None, enabled=True, alarm_id=None):
|
||||
"""Yields a lists of alarms that match filters
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
def update_alarm(self, alarm):
|
||||
"""update alarm
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
||||
def delete_alarm(self, alarm_id):
|
||||
"""Delete a alarm
|
||||
"""
|
||||
raise NotImplementedError('Alarms not implemented')
|
||||
|
@ -174,3 +174,78 @@ class Statistics(Model):
|
||||
period_end=period_end, duration=duration,
|
||||
duration_start=duration_start,
|
||||
duration_end=duration_end)
|
||||
|
||||
|
||||
class Alarm(Model):
|
||||
ALARM_INSUFFICIENT_DATA = 'insufficient data'
|
||||
ALARM_OK = 'ok'
|
||||
ALARM_ALARM = 'alarm'
|
||||
"""
|
||||
An alarm to monitor.
|
||||
|
||||
:param alarm_id: UUID of the alarm
|
||||
:param name: The Alarm name
|
||||
:param description: User friendly description of the alarm
|
||||
:param enabled: Is the alarm enabled
|
||||
:param state: Alarm state (alarm/nodata/ok)
|
||||
:param counter_name: The counter that the alarm is based on
|
||||
:param comparison_operator: How to compare the samples and the threshold
|
||||
:param threshold: the value to compare to the samples
|
||||
:param statistic: the function from Statistic (min/max/avg/count)
|
||||
:param user_id: the owner/creator of the alarm
|
||||
:param project_id: the project_id of the creator
|
||||
:param evaluation_periods: the number of periods
|
||||
:param period: the time period in seconds
|
||||
:param timestamp: the timestamp when the alarm was last updated
|
||||
:param state_timestamp: the timestamp of the last state change
|
||||
:param ok_actions: the list of webhooks to call when entering the ok state
|
||||
:param alarm_actions: the list of webhooks to call when entering the
|
||||
alarm state
|
||||
:param insufficient_data_actions: the list of webhooks to call when
|
||||
entering the insufficient data state
|
||||
:param matching_metadata: the key/values of metadata to match on.
|
||||
"""
|
||||
def __init__(self, name, counter_name,
|
||||
comparison_operator, threshold, statistic,
|
||||
user_id, project_id,
|
||||
evaluation_periods=1,
|
||||
period=60,
|
||||
alarm_id=None,
|
||||
enabled=True,
|
||||
description='',
|
||||
timestamp=None,
|
||||
state=ALARM_INSUFFICIENT_DATA,
|
||||
state_timestamp=None,
|
||||
ok_actions=[],
|
||||
alarm_actions=[],
|
||||
insufficient_data_actions=[],
|
||||
matching_metadata={}
|
||||
):
|
||||
if not description:
|
||||
# make a nice user friendly description by default
|
||||
description = 'Alarm when %s is %s a %s of %s over %s seconds' % (
|
||||
counter_name, comparison_operator,
|
||||
statistic, threshold, period)
|
||||
|
||||
Model.__init__(
|
||||
self,
|
||||
alarm_id=alarm_id,
|
||||
enabled=enabled,
|
||||
name=name,
|
||||
description=description,
|
||||
timestamp=timestamp,
|
||||
counter_name=counter_name,
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
comparison_operator=comparison_operator,
|
||||
threshold=threshold,
|
||||
statistic=statistic,
|
||||
evaluation_periods=evaluation_periods,
|
||||
period=period,
|
||||
state=state,
|
||||
state_timestamp=state_timestamp,
|
||||
ok_actions=ok_actions,
|
||||
alarm_actions=alarm_actions,
|
||||
insufficient_data_actions=
|
||||
insufficient_data_actions,
|
||||
matching_metadata=matching_metadata)
|
||||
|
@ -583,3 +583,66 @@ class CounterDataTypeTest(DBTestBase):
|
||||
)
|
||||
results = list(self.conn.get_samples(f))
|
||||
self.assertEqual(results[0].counter_volume, 1938495037.53697)
|
||||
|
||||
|
||||
class AlarmTest(DBTestBase):
|
||||
|
||||
def test_empty(self):
|
||||
alarms = list(self.conn.get_alarms())
|
||||
self.assertEquals([], alarms)
|
||||
|
||||
def add_some_alarms(self):
|
||||
alarms = [models.Alarm('red-alert',
|
||||
'test.one', 'eq', 36, 'count',
|
||||
'me', 'and-da-boys',
|
||||
evaluation_periods=1,
|
||||
period=60,
|
||||
alarm_actions=['http://nowhere/alarms']),
|
||||
models.Alarm('orange-alert',
|
||||
'test.fourty', 'gt', 75, 'avg',
|
||||
'me', 'and-da-boys',
|
||||
period=60,
|
||||
alarm_actions=['http://nowhere/alarms']),
|
||||
models.Alarm('yellow-alert',
|
||||
'test.five', 'lt', 10, 'min',
|
||||
'me', 'and-da-boys',
|
||||
alarm_actions=['http://nowhere/alarms'])]
|
||||
for a in alarms:
|
||||
self.conn.update_alarm(a)
|
||||
|
||||
def test_add(self):
|
||||
self.add_some_alarms()
|
||||
alarms = list(self.conn.get_alarms())
|
||||
self.assertEquals(len(alarms), 3)
|
||||
|
||||
def test_defaults(self):
|
||||
self.add_some_alarms()
|
||||
yellow = list(self.conn.get_alarms(name='yellow-alert'))[0]
|
||||
|
||||
self.assertEquals(yellow.evaluation_periods, 1)
|
||||
self.assertEquals(yellow.period, 60)
|
||||
self.assertEquals(yellow.enabled, True)
|
||||
self.assertEquals(yellow.description,
|
||||
'Alarm when test.five is lt %s' %
|
||||
'a min of 10 over 60 seconds')
|
||||
self.assertEquals(yellow.state, models.Alarm.ALARM_INSUFFICIENT_DATA)
|
||||
self.assertEquals(yellow.ok_actions, [])
|
||||
self.assertEquals(yellow.insufficient_data_actions, [])
|
||||
|
||||
def test_update(self):
|
||||
self.add_some_alarms()
|
||||
orange = list(self.conn.get_alarms(name='orange-alert'))[0]
|
||||
orange.enabled = False
|
||||
orange.state = models.Alarm.ALARM_INSUFFICIENT_DATA
|
||||
updated = self.conn.update_alarm(orange)
|
||||
self.assertEquals(updated.enabled, False)
|
||||
self.assertEquals(updated.state, models.Alarm.ALARM_INSUFFICIENT_DATA)
|
||||
|
||||
def test_delete(self):
|
||||
self.add_some_alarms()
|
||||
victim = list(self.conn.get_alarms(name='orange-alert'))[0]
|
||||
self.conn.delete_alarm(victim.alarm_id)
|
||||
survivors = list(self.conn.get_alarms())
|
||||
self.assertEquals(len(survivors), 2)
|
||||
for s in survivors:
|
||||
self.assertNotEquals(victim.name, s.name)
|
||||
|
Loading…
Reference in New Issue
Block a user