Merge "Add notifications for alarm changes"
This commit is contained in:
commit
a7ae16365f
@ -41,6 +41,7 @@ from wsme import types as wtypes
|
||||
from ceilometer.openstack.common import context
|
||||
from ceilometer.openstack.common.gettextutils import _
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer.openstack.common.notifier import api as notify
|
||||
from ceilometer.openstack.common import strutils
|
||||
from ceilometer.openstack.common import timeutils
|
||||
from ceilometer import sample
|
||||
@ -449,6 +450,13 @@ def _make_link(rel_name, url, type, type_arg, query=None):
|
||||
rel=rel_name)
|
||||
|
||||
|
||||
def _send_notification(event, payload):
|
||||
notification = event.replace(" ", "_")
|
||||
notification = "alarm.%s" % notification
|
||||
notify.notify(None, notify.publisher_id("ceilometer.api"),
|
||||
notification, notify.INFO, payload)
|
||||
|
||||
|
||||
class Sample(_Base):
|
||||
"""A single measurement for a given meter and resource.
|
||||
"""
|
||||
@ -1228,22 +1236,29 @@ class AlarmController(rest.RestController):
|
||||
if not cfg.CONF.alarm.record_history:
|
||||
return
|
||||
type = type or storage.models.AlarmChange.RULE_CHANGE
|
||||
detail = json.dumps(utils.stringify_timestamps(data))
|
||||
scrubbed_data = utils.stringify_timestamps(data)
|
||||
detail = json.dumps(scrubbed_data)
|
||||
user_id = pecan.request.headers.get('X-User-Id')
|
||||
project_id = pecan.request.headers.get('X-Project-Id')
|
||||
on_behalf_of = on_behalf_of or project_id
|
||||
payload = dict(event_id=str(uuid.uuid4()),
|
||||
alarm_id=self._id,
|
||||
type=type,
|
||||
detail=detail,
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
on_behalf_of=on_behalf_of,
|
||||
timestamp=now)
|
||||
|
||||
try:
|
||||
self.conn.record_alarm_change(dict(event_id=str(uuid.uuid4()),
|
||||
alarm_id=self._id,
|
||||
type=type,
|
||||
detail=detail,
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
on_behalf_of=on_behalf_of,
|
||||
timestamp=now))
|
||||
self.conn.record_alarm_change(payload)
|
||||
except NotImplementedError:
|
||||
pass
|
||||
|
||||
# Revert to the pre-json'ed details ...
|
||||
payload['detail'] = scrubbed_data
|
||||
_send_notification(type, payload)
|
||||
|
||||
@wsme_pecan.wsexpose(Alarm, wtypes.text)
|
||||
def get(self):
|
||||
"""Return this alarm."""
|
||||
@ -1356,21 +1371,28 @@ class AlarmsController(rest.RestController):
|
||||
if not cfg.CONF.alarm.record_history:
|
||||
return
|
||||
type = storage.models.AlarmChange.CREATION
|
||||
detail = json.dumps(utils.stringify_timestamps(data))
|
||||
scrubbed_data = utils.stringify_timestamps(data)
|
||||
detail = json.dumps(scrubbed_data)
|
||||
user_id = pecan.request.headers.get('X-User-Id')
|
||||
project_id = pecan.request.headers.get('X-Project-Id')
|
||||
payload = dict(event_id=str(uuid.uuid4()),
|
||||
alarm_id=alarm_id,
|
||||
type=type,
|
||||
detail=detail,
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
on_behalf_of=project_id,
|
||||
timestamp=now)
|
||||
|
||||
try:
|
||||
conn.record_alarm_change(dict(event_id=str(uuid.uuid4()),
|
||||
alarm_id=alarm_id,
|
||||
type=type,
|
||||
detail=detail,
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
on_behalf_of=project_id,
|
||||
timestamp=now))
|
||||
conn.record_alarm_change(payload)
|
||||
except NotImplementedError:
|
||||
pass
|
||||
|
||||
# Revert to the pre-json'ed details ...
|
||||
payload['detail'] = scrubbed_data
|
||||
_send_notification(type, payload)
|
||||
|
||||
@wsme.validate(Alarm)
|
||||
@wsme_pecan.wsexpose(Alarm, body=Alarm, status_code=201)
|
||||
def post(self, data):
|
||||
|
@ -23,6 +23,7 @@
|
||||
import datetime
|
||||
import json as jsonutils
|
||||
import logging
|
||||
import mock
|
||||
import uuid
|
||||
import testscenarios
|
||||
|
||||
@ -1106,3 +1107,52 @@ class TestAlarms(FunctionalTest,
|
||||
# continued existence of the alarm itself
|
||||
history = self._get_alarm_history(dict(alarm_id='foobar'))
|
||||
self.assertEqual([], history)
|
||||
|
||||
def test_alarms_sends_notification(self):
|
||||
# Hit the AlarmsController ...
|
||||
json = {
|
||||
'name': 'sent_notification',
|
||||
'type': 'threshold',
|
||||
'threshold_rule': {
|
||||
'meter_name': 'ameter',
|
||||
'comparison_operator': 'gt',
|
||||
'threshold': 2.0,
|
||||
'statistic': 'avg',
|
||||
}
|
||||
|
||||
}
|
||||
with mock.patch('ceilometer.openstack.common.notifier.api.notify') \
|
||||
as notifier:
|
||||
self.post_json('/alarms', params=json, headers=self.auth_headers)
|
||||
|
||||
calls = notifier.call_args_list
|
||||
self.assertEqual(len(calls), 1)
|
||||
args, _ = calls[0]
|
||||
context, publisher, event_type, priority, payload = args
|
||||
self.assertTrue(publisher.startswith('ceilometer.api'))
|
||||
self.assertEqual(event_type, 'alarm.creation')
|
||||
self.assertEqual(priority, 'INFO')
|
||||
self.assertEqual(payload['detail']['name'], 'sent_notification')
|
||||
self.assertTrue(set(['alarm_id', 'detail', 'event_id', 'on_behalf_of',
|
||||
'project_id', 'timestamp', 'type',
|
||||
'user_id']).issubset(payload.keys()))
|
||||
|
||||
def test_alarm_sends_notification(self):
|
||||
# Hit the AlarmController (with alarm_id supplied) ...
|
||||
data = self.get_json('/alarms')
|
||||
with mock.patch('ceilometer.openstack.common.notifier.api.notify') \
|
||||
as notifier:
|
||||
self.delete('/alarms/%s' % data[0]['alarm_id'],
|
||||
headers=self.auth_headers, status=204)
|
||||
|
||||
calls = notifier.call_args_list
|
||||
self.assertEqual(len(calls), 1)
|
||||
args, _ = calls[0]
|
||||
context, publisher, event_type, priority, payload = args
|
||||
self.assertTrue(publisher.startswith('ceilometer.api'))
|
||||
self.assertEqual(event_type, 'alarm.deletion')
|
||||
self.assertEqual(priority, 'INFO')
|
||||
self.assertEqual(payload['detail']['name'], 'name1')
|
||||
self.assertTrue(set(['alarm_id', 'detail', 'event_id', 'on_behalf_of',
|
||||
'project_id', 'timestamp', 'type',
|
||||
'user_id']).issubset(payload.keys()))
|
||||
|
Loading…
Reference in New Issue
Block a user