Provide new API endpoint for alarm state
This patch add a new endpoint to the alarm API to change only the state of an alarm. And modifies the evaluator base to use this new endpoint. Implements blueprint alarming-logical-combination Change-Id: I8bff74f0686ba17103ee63bcbdb0830c8273596f
This commit is contained in:
parent
985f482709
commit
cd96b61099
@ -68,7 +68,7 @@ class Evaluator(object):
|
||||
'state': state,
|
||||
'reason': reason})
|
||||
|
||||
self._client.alarms.update(alarm.alarm_id, **dict(state=state))
|
||||
self._client.alarms.set_state(alarm.alarm_id, state=state)
|
||||
alarm.state = state
|
||||
if self.notifier:
|
||||
self.notifier.notify(alarm, previous, reason)
|
||||
|
@ -70,7 +70,7 @@ ALARM_API_OPTS = [
|
||||
|
||||
cfg.CONF.register_opts(ALARM_API_OPTS, group='alarm')
|
||||
|
||||
|
||||
state_kind = ["ok", "alarm", "insufficient data"]
|
||||
operation_kind = wtypes.Enum(str, 'lt', 'le', 'eq', 'ne', 'ge', 'gt')
|
||||
|
||||
|
||||
@ -1079,10 +1079,7 @@ class Alarm(_Base):
|
||||
timestamp = datetime.datetime
|
||||
"The date of the last alarm definition update"
|
||||
|
||||
#TODO(sileht): Add an explicit "set_state" operation instead of
|
||||
#forcing the caller to PUT the entire definition of the alarm to test it.
|
||||
#(example: POST/PUT? alarms/<alarm_id>/state)
|
||||
state = AdvEnum('state', str, 'ok', 'alarm', 'insufficient data',
|
||||
state = AdvEnum('state', str, *state_kind,
|
||||
default='insufficient data')
|
||||
"The state offset the alarm"
|
||||
|
||||
@ -1186,6 +1183,7 @@ class AlarmController(rest.RestController):
|
||||
|
||||
_custom_actions = {
|
||||
'history': ['GET'],
|
||||
'state': ['PUT', 'GET'],
|
||||
}
|
||||
|
||||
def __init__(self, alarm_id):
|
||||
@ -1299,6 +1297,28 @@ class AlarmController(rest.RestController):
|
||||
for ac in conn.get_alarm_changes(self._id, auth_project,
|
||||
**kwargs)]
|
||||
|
||||
@wsme_pecan.wsexpose(wtypes.text, body=wtypes.text)
|
||||
def put_state(self, state):
|
||||
"""Set the state of this alarm."""
|
||||
if state not in state_kind:
|
||||
error = _("state invalid")
|
||||
pecan.response.translatable_error = error
|
||||
raise wsme.exc.ClientSideError(unicode(error))
|
||||
now = timeutils.utcnow()
|
||||
alarm = self._alarm()
|
||||
alarm.state = state
|
||||
alarm.state_timestamp = now
|
||||
alarm = self.conn.update_alarm(alarm)
|
||||
change = {'state': alarm.state}
|
||||
self._record_change(change, now, on_behalf_of=alarm.project_id,
|
||||
type=storage.models.AlarmChange.STATE_TRANSITION)
|
||||
return alarm.state
|
||||
|
||||
@wsme_pecan.wsexpose(wtypes.text)
|
||||
def get_state(self):
|
||||
alarm = self._alarm()
|
||||
return alarm.state
|
||||
|
||||
|
||||
class AlarmsController(rest.RestController):
|
||||
"""Manages operations on the alarms collection.
|
||||
|
@ -128,7 +128,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._assert_all_alarms('insufficient data')
|
||||
expected = [mock.call(alarm.alarm_id, state='insufficient data')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
expected = [mock.call(alarm,
|
||||
'ok',
|
||||
@ -150,7 +150,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._evaluate_all_alarms()
|
||||
expected = [mock.call(alarm.alarm_id, state='ok')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = self._combination_transition_reason('ok')
|
||||
expected = [mock.call(alarm, 'insufficient data', reason)
|
||||
@ -170,7 +170,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._evaluate_all_alarms()
|
||||
expected = [mock.call(alarm.alarm_id, state='ok')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = self._combination_transition_reason('ok')
|
||||
expected = [mock.call(alarm, 'alarm', reason)
|
||||
@ -190,7 +190,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._evaluate_all_alarms()
|
||||
expected = [mock.call(alarm.alarm_id, state='alarm')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = self._combination_transition_reason('alarm')
|
||||
expected = [mock.call(alarm, 'ok', reason)
|
||||
@ -210,7 +210,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._evaluate_all_alarms()
|
||||
expected = [mock.call(alarm.alarm_id, state='alarm')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = self._combination_transition_reason('alarm')
|
||||
expected = [mock.call(alarm, 'ok', reason)
|
||||
@ -231,7 +231,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._evaluate_all_alarms()
|
||||
expected = [mock.call(alarm.alarm_id, state='insufficient data')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = ['1 alarms in'
|
||||
' 9cfc3e51-2ff1-4b1d-ac01-c1bd4c6d0d1e,'
|
||||
@ -256,7 +256,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._get_alarm('ok'),
|
||||
]
|
||||
self._evaluate_all_alarms()
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, [])
|
||||
self.assertEqual(self.notifier.notify.call_args_list, [])
|
||||
|
||||
@ -273,7 +273,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._get_alarm('ok'),
|
||||
]
|
||||
self._evaluate_all_alarms()
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, [])
|
||||
reasons = self._combination_remaining_reason('ok')
|
||||
expected = [mock.call(alarm, 'ok', reason)
|
||||
|
@ -122,7 +122,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._assert_all_alarms('insufficient data')
|
||||
expected = [mock.call(alarm.alarm_id, state='insufficient data')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
expected = [mock.call(alarm,
|
||||
'ok',
|
||||
@ -144,7 +144,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._assert_all_alarms('alarm')
|
||||
expected = [mock.call(alarm.alarm_id, state='alarm')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = ['Transition to alarm due to 5 samples outside'
|
||||
' threshold, most recent: 85.0',
|
||||
@ -167,7 +167,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._assert_all_alarms('ok')
|
||||
expected = [mock.call(alarm.alarm_id, state='ok')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = ['Transition to ok due to 5 samples inside'
|
||||
' threshold, most recent: 76.0',
|
||||
@ -188,7 +188,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self.api_client.statistics.list.side_effect = [avgs, maxs]
|
||||
self._evaluate_all_alarms()
|
||||
self._assert_all_alarms('ok')
|
||||
self.assertEqual(self.api_client.alarms.update.call_args_list,
|
||||
self.assertEqual(self.api_client.alarms.set_state.call_args_list,
|
||||
[])
|
||||
self.assertEqual(self.notifier.notify.call_args_list, [])
|
||||
|
||||
@ -204,7 +204,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self.api_client.statistics.list.side_effect = [avgs, maxs]
|
||||
self._evaluate_all_alarms()
|
||||
self._assert_all_alarms('ok')
|
||||
self.assertEqual(self.api_client.alarms.update.call_args_list,
|
||||
self.assertEqual(self.api_client.alarms.set_state.call_args_list,
|
||||
[])
|
||||
reason = 'Remaining as ok due to 4 samples inside' \
|
||||
' threshold, most recent: 8.0'
|
||||
@ -223,7 +223,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self.api_client.statistics.list.side_effect = [avgs, maxs]
|
||||
self._evaluate_all_alarms()
|
||||
self._assert_all_alarms('alarm')
|
||||
self.assertEqual(self.api_client.alarms.update.call_args_list,
|
||||
self.assertEqual(self.api_client.alarms.set_state.call_args_list,
|
||||
[])
|
||||
reason = 'Remaining as alarm due to 4 samples outside' \
|
||||
' threshold, most recent: 7.0'
|
||||
@ -245,7 +245,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._assert_all_alarms('alarm')
|
||||
expected = [mock.call(alarm.alarm_id, state='alarm')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = ['Transition to alarm due to 5 samples outside'
|
||||
' threshold, most recent: 85.0',
|
||||
@ -268,7 +268,7 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
self._assert_all_alarms('alarm')
|
||||
expected = [mock.call(alarm.alarm_id, state='alarm')
|
||||
for alarm in self.alarms]
|
||||
update_calls = self.api_client.alarms.update.call_args_list
|
||||
update_calls = self.api_client.alarms.set_state.call_args_list
|
||||
self.assertEqual(update_calls, expected)
|
||||
reasons = ['Transition to alarm due to 5 samples outside'
|
||||
' threshold, most recent: 85.0',
|
||||
|
@ -520,6 +520,35 @@ class TestAlarms(FunctionalTest,
|
||||
alarms = list(self.conn.get_alarms())
|
||||
self.assertEqual(3, len(alarms))
|
||||
|
||||
def test_get_state_alarm(self):
|
||||
data = self.get_json('/alarms')
|
||||
self.assertEqual(4, len(data))
|
||||
|
||||
resp = self.get_json('/alarms/%s/state' % data[0]['alarm_id'],
|
||||
headers=self.auth_headers)
|
||||
self.assertEqual(data[0]['state'], resp)
|
||||
|
||||
def test_set_state_alarm(self):
|
||||
data = self.get_json('/alarms')
|
||||
self.assertEqual(4, len(data))
|
||||
|
||||
resp = self.put_json('/alarms/%s/state' % data[0]['alarm_id'],
|
||||
headers=self.auth_headers,
|
||||
params='alarm')
|
||||
alarms = list(self.conn.get_alarms(alarm_id=data[0]['alarm_id']))
|
||||
self.assertEqual(1, len(alarms))
|
||||
self.assertEqual(alarms[0].state, 'alarm')
|
||||
self.assertEqual(resp.json, 'alarm')
|
||||
|
||||
def test_set_invalid_state_alarm(self):
|
||||
data = self.get_json('/alarms')
|
||||
self.assertEqual(4, len(data))
|
||||
|
||||
self.put_json('/alarms/%s/state' % data[0]['alarm_id'],
|
||||
headers=self.auth_headers,
|
||||
params='not valid',
|
||||
status=400)
|
||||
|
||||
def _get_alarm(self, id):
|
||||
data = self.get_json('/alarms')
|
||||
match = [a for a in data if a['alarm_id'] == id]
|
||||
|
Loading…
x
Reference in New Issue
Block a user