Merge "Add notifications for alarm changes"

This commit is contained in:
Jenkins 2013-10-07 08:29:17 +00:00 committed by Gerrit Code Review
commit a7ae16365f
2 changed files with 90 additions and 18 deletions

View File

@ -41,6 +41,7 @@ from wsme import types as wtypes
from ceilometer.openstack.common import context from ceilometer.openstack.common import context
from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common.gettextutils import _
from ceilometer.openstack.common import log 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 strutils
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer import sample from ceilometer import sample
@ -449,6 +450,13 @@ def _make_link(rel_name, url, type, type_arg, query=None):
rel=rel_name) 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): class Sample(_Base):
"""A single measurement for a given meter and resource. """A single measurement for a given meter and resource.
""" """
@ -1228,22 +1236,29 @@ class AlarmController(rest.RestController):
if not cfg.CONF.alarm.record_history: if not cfg.CONF.alarm.record_history:
return return
type = type or storage.models.AlarmChange.RULE_CHANGE 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') user_id = pecan.request.headers.get('X-User-Id')
project_id = pecan.request.headers.get('X-Project-Id') project_id = pecan.request.headers.get('X-Project-Id')
on_behalf_of = on_behalf_of or 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: try:
self.conn.record_alarm_change(dict(event_id=str(uuid.uuid4()), self.conn.record_alarm_change(payload)
alarm_id=self._id,
type=type,
detail=detail,
user_id=user_id,
project_id=project_id,
on_behalf_of=on_behalf_of,
timestamp=now))
except NotImplementedError: except NotImplementedError:
pass pass
# Revert to the pre-json'ed details ...
payload['detail'] = scrubbed_data
_send_notification(type, payload)
@wsme_pecan.wsexpose(Alarm, wtypes.text) @wsme_pecan.wsexpose(Alarm, wtypes.text)
def get(self): def get(self):
"""Return this alarm.""" """Return this alarm."""
@ -1356,21 +1371,28 @@ class AlarmsController(rest.RestController):
if not cfg.CONF.alarm.record_history: if not cfg.CONF.alarm.record_history:
return return
type = storage.models.AlarmChange.CREATION 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') user_id = pecan.request.headers.get('X-User-Id')
project_id = pecan.request.headers.get('X-Project-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: try:
conn.record_alarm_change(dict(event_id=str(uuid.uuid4()), conn.record_alarm_change(payload)
alarm_id=alarm_id,
type=type,
detail=detail,
user_id=user_id,
project_id=project_id,
on_behalf_of=project_id,
timestamp=now))
except NotImplementedError: except NotImplementedError:
pass pass
# Revert to the pre-json'ed details ...
payload['detail'] = scrubbed_data
_send_notification(type, payload)
@wsme.validate(Alarm) @wsme.validate(Alarm)
@wsme_pecan.wsexpose(Alarm, body=Alarm, status_code=201) @wsme_pecan.wsexpose(Alarm, body=Alarm, status_code=201)
def post(self, data): def post(self, data):

View File

@ -23,6 +23,7 @@
import datetime import datetime
import json as jsonutils import json as jsonutils
import logging import logging
import mock
import uuid import uuid
import testscenarios import testscenarios
@ -1106,3 +1107,52 @@ class TestAlarms(FunctionalTest,
# continued existence of the alarm itself # continued existence of the alarm itself
history = self._get_alarm_history(dict(alarm_id='foobar')) history = self._get_alarm_history(dict(alarm_id='foobar'))
self.assertEqual([], history) 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()))