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 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):
|
||||||
|
@ -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()))
|
||||||
|
Loading…
Reference in New Issue
Block a user