Merge "Add OS::Aodh::EventAlarm resource"

This commit is contained in:
Jenkins 2016-11-01 17:20:35 +00:00 committed by Gerrit Code Review
commit 8bb04edee8
2 changed files with 220 additions and 0 deletions

View File

@ -305,8 +305,111 @@ class CombinationAlarm(alarm_base.BaseAlarm):
self.client().alarms.get(self.resource_id)
class EventAlarm(alarm_base.BaseAlarm):
"""A resource that implements event alarms.
Allows users to define alarms which can be evaluated based on events
passed from other OpenStack services. The events can be emitted when
the resources from other OpenStack services have been updated, created
or deleted, such as 'compute.instance.reboot.end',
'scheduler.select_destinations.end'.
"""
alarm_type = 'event'
support_status = support.SupportStatus(version='8.0.0')
PROPERTIES = (
EVENT_TYPE, QUERY
) = (
'event_type', 'query'
)
QUERY_FACTOR_FIELDS = (
QF_FIELD, QF_OP, QF_VALUE,
) = (
'field', 'op', 'value',
)
QF_OP_VALS = constraints.AllowedValues(['le', 'ge', 'eq',
'lt', 'gt', 'ne'])
properties_schema = {
EVENT_TYPE: properties.Schema(
properties.Schema.STRING,
_('Event type to evaluate against. '
'If not specified will match all events.'),
update_allowed=True,
default='*'
),
QUERY: properties.Schema(
properties.Schema.LIST,
_('A list for filtering events. Query conditions used '
'to filter specific events when evaluating the alarm.'),
update_allowed=True,
schema=properties.Schema(
properties.Schema.MAP,
schema={
QF_FIELD: properties.Schema(
properties.Schema.STRING,
_('Name of attribute to compare.')
),
QF_OP: properties.Schema(
properties.Schema.STRING,
_('Comparison operator.'),
constraints=[QF_OP_VALS]
),
QF_VALUE: properties.Schema(
properties.Schema.STRING,
_('String value with which to compare.')
)
}
)
)
}
properties_schema.update(alarm_base.common_properties_schema)
def get_alarm_props(self, props):
"""Apply all relevant compatibility xforms."""
kwargs = self.actions_to_urls(props)
kwargs['type'] = self.alarm_type
rule = {}
for prop in (self.EVENT_TYPE, self.QUERY):
if prop in kwargs:
del kwargs[prop]
query = props.get(self.QUERY)
if query:
rule[self.QUERY] = query
event_type = props.get(self.EVENT_TYPE)
if event_type:
rule[self.EVENT_TYPE] = event_type
kwargs['event_rule'] = rule
return kwargs
def handle_create(self):
props = self.get_alarm_props(self.properties)
props['name'] = self.physical_resource_name()
alarm = self.client().alarm.create(props)
self.resource_id_set(alarm['alarm_id'])
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if prop_diff:
kwargs = {}
kwargs.update(self.properties)
kwargs.update(prop_diff)
self.client().alarm.update(self.resource_id,
self.get_alarm_props(kwargs))
def _show_resource(self):
return self.client().alarm.get(self.resource_id)
def resource_mapping():
return {
'OS::Aodh::Alarm': AodhAlarm,
'OS::Aodh::CombinationAlarm': CombinationAlarm,
'OS::Aodh::EventAlarm': EventAlarm,
}

View File

@ -139,6 +139,30 @@ combination_alarm_template = '''
}
'''
event_alarm_template = '''
{
"heat_template_version" : "newton",
"description" : "Event alarm test",
"parameters" : {},
"resources" : {
"test_event_alarm": {
"type": "OS::Aodh::EventAlarm",
"properties": {
"description": "Alarm event when an image is updated",
"event_type": "image.update",
"query": [{
"field": 'traits.resource_id',
"op": "eq",
"value": "9a8fec25-1ba6-4170-aa44-5d72f17c07f6"}]
}
},
"signal_handler" : {
"type" : "SignalResourceType"
}
}
}
'''
class FakeCombinationAlarm(object):
alarm_id = 'foo'
@ -772,3 +796,96 @@ class CombinationAlarmTest(common.HeatTestCase):
res.client().alarms.get.return_value = FakeCombinationAlarm()
scheduler.TaskRunner(res.create)()
self.assertEqual({'attr': 'val'}, res.FnGetAtt('show'))
class EventAlarmTest(common.HeatTestCase):
def setUp(self):
super(EventAlarmTest, self).setUp()
self.fa = mock.Mock()
def create_stack(self, template=None):
if template is None:
template = event_alarm_template
temp = template_format.parse(template)
template = tmpl.Template(temp)
ctx = utils.dummy_context()
ctx.tenant = 'test_tenant'
stack = parser.Stack(ctx, utils.random_name(), template,
disable_rollback=True)
stack.store()
self.patchobject(aodh.AodhClientPlugin,
'_create').return_value = self.fa
self.patchobject(self.fa.alarm, 'create').return_value = FakeAodhAlarm
return stack
def test_update(self):
test_stack = self.create_stack()
update_mock = self.patchobject(self.fa.alarm, 'update')
test_stack.create()
rsrc = test_stack['test_event_alarm']
update_props = copy.deepcopy(rsrc.properties.data)
update_props.update({
'enabled': True,
'insufficient_data_actions': [],
'alarm_actions': [],
'ok_actions': ['signal_handler'],
'query': [dict(
field='traits.resource_id',
op='eq',
value='c7405b0f-139f-4fbd-9348-f32dfc5674ac')]
})
snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
update_props)
scheduler.TaskRunner(rsrc.update, snippet)()
self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
self.assertEqual(1, update_mock.call_count)
def test_delete(self):
test_stack = self.create_stack()
rsrc = test_stack['test_event_alarm']
self.patchobject(aodh.AodhClientPlugin, 'client',
return_value=self.fa)
self.patchobject(self.fa.alarm, 'delete')
rsrc.resource_id = '12345'
self.assertEqual('12345', rsrc.handle_delete())
self.assertEqual(1, self.fa.alarm.delete.call_count)
def _prepare_check_resource(self):
snippet = template_format.parse(event_alarm_template)
self.stack = utils.parse_stack(snippet)
res = self.stack['test_event_alarm']
res.client = mock.Mock()
mock_alarm = mock.Mock(enabled=True, state='ok')
res.client().alarm.get.return_value = mock_alarm
return res
def test_check(self):
res = self._prepare_check_resource()
scheduler.TaskRunner(res.check)()
self.assertEqual((res.CHECK, res.COMPLETE), res.state)
def test_check_alarm_failure(self):
res = self._prepare_check_resource()
res.client().alarm.get.side_effect = Exception('Boom')
self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(res.check))
self.assertEqual((res.CHECK, res.FAILED), res.state)
self.assertIn('Boom', res.status_reason)
def test_show_resource(self):
res = self._prepare_check_resource()
res.client().alarm.create.return_value = FakeAodhAlarm
res.client().alarm.get.return_value = FakeAodhAlarm
scheduler.TaskRunner(res.create)()
self.assertEqual(FakeAodhAlarm, res.FnGetAtt('show'))