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.
|
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
|
@abc.abstractmethod
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""Clear database."""
|
"""Clear database."""
|
||||||
|
@ -494,6 +494,23 @@ class Connection(base.Connection):
|
|||||||
self._update_meter_stats(results[-1], meter)
|
self._update_meter_stats(results[-1], meter)
|
||||||
return results
|
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
|
# This is a very crude version of "in-memory HBase", which implements just
|
||||||
|
@ -145,3 +145,18 @@ class Connection(base.Connection):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
return []
|
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)
|
a_max.valueOf() // 1000)
|
||||||
return (a_min, a_max)
|
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):
|
def require_map_reduce(conn):
|
||||||
"""Raises SkipTest if the connection is using mim.
|
"""Raises SkipTest if the connection is using mim.
|
||||||
|
@ -411,3 +411,19 @@ class Connection(base.Connection):
|
|||||||
period_start=period_start,
|
period_start=period_start,
|
||||||
period_end=period_end,
|
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,
|
period_end=period_end, duration=duration,
|
||||||
duration_start=duration_start,
|
duration_start=duration_start,
|
||||||
duration_end=duration_end)
|
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))
|
results = list(self.conn.get_samples(f))
|
||||||
self.assertEqual(results[0].counter_volume, 1938495037.53697)
|
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