Add support for more aodh alarm types:
- composite - gnocchi_aggregation_by_metrics_threshold - gnocchi_aggregation_by_resources_threshold Task: #22520 Story: #2002693 Depends-On: I65dd102635b1f6c6500a9c34da130aaea33708b2 Depends-On: Id5dbd165a1e0220e4e24207e8d237f94415fc490 Change-Id: Ifb966f5a47f469f729ef9e99f1f53a2d733a110b
This commit is contained in:
parent
b85fae2db9
commit
7803cc5202
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add support for more aodh alarm types - composite,
|
||||||
|
gnocchi_aggregation_by_metrics_threshold and
|
||||||
|
gnocchi_aggregation_by_resources_threshold.
|
@ -103,8 +103,7 @@ class AlarmDriverBase(DriverBase):
|
|||||||
for alarm in alarms:
|
for alarm in alarms:
|
||||||
alarm_key = self._alarm_key(alarm)
|
alarm_key = self._alarm_key(alarm)
|
||||||
old_alarm = self.cache.get(alarm_key, (None, None))[0]
|
old_alarm = self.cache.get(alarm_key, (None, None))[0]
|
||||||
if self._filter_and_cache_alarm(
|
if self._filter_and_cache_alarm(alarm, old_alarm, filter_, now):
|
||||||
alarm, old_alarm, filter_, now):
|
|
||||||
alarms_to_update.append(alarm)
|
alarms_to_update.append(alarm)
|
||||||
|
|
||||||
# add alarms that were deleted
|
# add alarms that were deleted
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import json
|
||||||
|
import six
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
@ -57,7 +59,14 @@ class AodhDriver(AlarmDriverBase):
|
|||||||
AodhExtendedAlarmType.THRESHOLD:
|
AodhExtendedAlarmType.THRESHOLD:
|
||||||
self._convert_threshold_alarm_rule,
|
self._convert_threshold_alarm_rule,
|
||||||
AodhExtendedAlarmType.GNOCCHI_RESOURCES_THRESHOLD:
|
AodhExtendedAlarmType.GNOCCHI_RESOURCES_THRESHOLD:
|
||||||
self._convert_gnocchi_resources_threshold_alarm_rule
|
self._convert_gnocchi_resources_threshold_alarm_rule,
|
||||||
|
AodhExtendedAlarmType.GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD:
|
||||||
|
self._convert_gnocchi_aggregation_by_metrics_threshold_rule,
|
||||||
|
AodhExtendedAlarmType.GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD:
|
||||||
|
self._convert_gnocchi_aggregation_by_resources_threshold_rule,
|
||||||
|
AodhExtendedAlarmType.COMPOSITE:
|
||||||
|
self._convert_composite_alarm_rule
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _init_alarm_type_to_rule(self):
|
def _init_alarm_type_to_rule(self):
|
||||||
@ -66,7 +75,12 @@ class AodhDriver(AlarmDriverBase):
|
|||||||
AodhExtendedAlarmType.EVENT: AodhProps.EVENT_RULE,
|
AodhExtendedAlarmType.EVENT: AodhProps.EVENT_RULE,
|
||||||
AodhExtendedAlarmType.THRESHOLD: AodhProps.THRESHOLD_RULE,
|
AodhExtendedAlarmType.THRESHOLD: AodhProps.THRESHOLD_RULE,
|
||||||
AodhExtendedAlarmType.GNOCCHI_RESOURCES_THRESHOLD:
|
AodhExtendedAlarmType.GNOCCHI_RESOURCES_THRESHOLD:
|
||||||
AodhProps.GNOCCHI_RESOURCES_THRESHOLD_RULE
|
AodhProps.GNOCCHI_RESOURCES_THRESHOLD_RULE,
|
||||||
|
AodhExtendedAlarmType.COMPOSITE: AodhProps.COMPOSITE_RULE,
|
||||||
|
AodhExtendedAlarmType.GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD:
|
||||||
|
AodhProps.GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD_RULE,
|
||||||
|
AodhExtendedAlarmType.GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD:
|
||||||
|
AodhProps.GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD_RULE
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -109,7 +123,12 @@ class AodhDriver(AlarmDriverBase):
|
|||||||
|
|
||||||
Aodh_type = [AodhExtendedAlarmType.EVENT,
|
Aodh_type = [AodhExtendedAlarmType.EVENT,
|
||||||
AodhExtendedAlarmType.THRESHOLD,
|
AodhExtendedAlarmType.THRESHOLD,
|
||||||
AodhExtendedAlarmType.GNOCCHI_RESOURCES_THRESHOLD]
|
AodhExtendedAlarmType.GNOCCHI_RESOURCES_THRESHOLD,
|
||||||
|
AodhExtendedAlarmType.
|
||||||
|
GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD,
|
||||||
|
AodhExtendedAlarmType.
|
||||||
|
GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD,
|
||||||
|
AodhExtendedAlarmType.COMPOSITE]
|
||||||
|
|
||||||
alarm_type = alarm[AodhProps.TYPE]
|
alarm_type = alarm[AodhProps.TYPE]
|
||||||
if alarm_type == AodhProps.EVENT and \
|
if alarm_type == AodhProps.EVENT and \
|
||||||
@ -171,12 +190,26 @@ class AodhDriver(AlarmDriverBase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _convert_threshold_alarm_rule(cls, rule):
|
def _convert_threshold_alarm_rule(cls, rule):
|
||||||
return {
|
return cls._alarm_rule_common(rule)
|
||||||
AodhProps.RESOURCE_ID: _parse_query(rule, AodhProps.RESOURCE_ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _convert_gnocchi_resources_threshold_alarm_rule(cls, rule):
|
def _convert_gnocchi_resources_threshold_alarm_rule(cls, rule):
|
||||||
|
return cls._alarm_rule_common(rule)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _convert_gnocchi_aggregation_by_metrics_threshold_rule(cls, rule):
|
||||||
|
return cls._alarm_rule_common(rule)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _convert_gnocchi_aggregation_by_resources_threshold_rule(cls, rule):
|
||||||
|
return cls._alarm_rule_common(rule)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _convert_composite_alarm_rule(cls, rule):
|
||||||
|
return cls._alarm_rule_common(rule)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _alarm_rule_common(cls, rule):
|
||||||
return {
|
return {
|
||||||
AodhProps.RESOURCE_ID: _parse_query(rule, AodhProps.RESOURCE_ID)
|
AodhProps.RESOURCE_ID: _parse_query(rule, AodhProps.RESOURCE_ID)
|
||||||
}
|
}
|
||||||
@ -268,7 +301,6 @@ class AodhDriver(AlarmDriverBase):
|
|||||||
"""
|
"""
|
||||||
old_alarm = self._old_alarm(event)
|
old_alarm = self._old_alarm(event)
|
||||||
entity = old_alarm.copy()
|
entity = old_alarm.copy()
|
||||||
|
|
||||||
changed_rule = event[AodhProps.DETAIL]
|
changed_rule = event[AodhProps.DETAIL]
|
||||||
for (changed_type, changed_info) in changed_rule.items():
|
for (changed_type, changed_info) in changed_rule.items():
|
||||||
# handle changed rule which may effect the neighbor
|
# handle changed rule which may effect the neighbor
|
||||||
@ -303,12 +335,41 @@ class AodhDriver(AlarmDriverBase):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_query(data, key):
|
def _parse_query(data, key):
|
||||||
|
"""Find the relevant key in a given alarm detail query.
|
||||||
|
|
||||||
|
:param data: A query is either a list of this form:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
field: resource_id,
|
||||||
|
value: 54132
|
||||||
|
}
|
||||||
|
]
|
||||||
|
or a string-represented dict of this form:
|
||||||
|
'{
|
||||||
|
=: { resource_id : 1235423 }
|
||||||
|
}'
|
||||||
|
"""
|
||||||
|
|
||||||
query_fields = data.get(AodhProps.QUERY, {})
|
query_fields = data.get(AodhProps.QUERY, {})
|
||||||
for query in query_fields:
|
try:
|
||||||
field = query['field']
|
if isinstance(query_fields, six.text_type):
|
||||||
if field == key:
|
query_fields = json.loads(query_fields)
|
||||||
return query['value']
|
if not isinstance(query_fields, list):
|
||||||
return None
|
query_fields = [query_fields]
|
||||||
|
for query in query_fields:
|
||||||
|
field = query.get('field')
|
||||||
|
if field and field == key:
|
||||||
|
return query['value']
|
||||||
|
elif not field:
|
||||||
|
field = query.get('=', {})
|
||||||
|
for k in field:
|
||||||
|
if k == key:
|
||||||
|
return field[key]
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
LOG.exception("Failed to parse AODH alarm query")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _is_vitrage_alarm(rule):
|
def _is_vitrage_alarm(rule):
|
||||||
|
@ -38,8 +38,14 @@ class AodhProperties(object):
|
|||||||
DETAIL = 'detail'
|
DETAIL = 'detail'
|
||||||
RULE = 'rule'
|
RULE = 'rule'
|
||||||
GNOCCHI_RESOURCES_THRESHOLD_RULE = 'gnocchi_resources_threshold_rule'
|
GNOCCHI_RESOURCES_THRESHOLD_RULE = 'gnocchi_resources_threshold_rule'
|
||||||
|
COMPOSITE_RULE = 'composite_rule'
|
||||||
|
GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD_RULE = \
|
||||||
|
'gnocchi_aggregation_by_resources_threshold_rule'
|
||||||
|
GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD_RULE = \
|
||||||
|
'gnocchi_aggregation_by_metrics_threshold_rule'
|
||||||
USER_ID = 'user_id'
|
USER_ID = 'user_id'
|
||||||
STATE_REASON = 'state_reason'
|
STATE_REASON = 'state_reason'
|
||||||
|
METRICS = 'metrics'
|
||||||
|
|
||||||
|
|
||||||
class AodhState(object):
|
class AodhState(object):
|
||||||
@ -60,3 +66,8 @@ class AodhExtendedAlarmType(object):
|
|||||||
VITRAGE = 'vitrage'
|
VITRAGE = 'vitrage'
|
||||||
THRESHOLD = 'threshold'
|
THRESHOLD = 'threshold'
|
||||||
GNOCCHI_RESOURCES_THRESHOLD = 'gnocchi_resources_threshold'
|
GNOCCHI_RESOURCES_THRESHOLD = 'gnocchi_resources_threshold'
|
||||||
|
COMPOSITE = 'composite'
|
||||||
|
GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD = \
|
||||||
|
'gnocchi_aggregation_by_metrics_threshold'
|
||||||
|
GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD = \
|
||||||
|
'gnocchi_aggregation_by_resources_threshold'
|
||||||
|
@ -19,6 +19,7 @@ from vitrage.common.constants import DatasourceProperties as DSProps
|
|||||||
from vitrage.common.constants import UpdateMethod
|
from vitrage.common.constants import UpdateMethod
|
||||||
from vitrage.datasources.aodh import AODH_DATASOURCE
|
from vitrage.datasources.aodh import AODH_DATASOURCE
|
||||||
from vitrage.datasources.aodh.properties import AodhEventType
|
from vitrage.datasources.aodh.properties import AodhEventType
|
||||||
|
from vitrage.datasources.aodh.properties import AodhExtendedAlarmType as AType
|
||||||
from vitrage.datasources.aodh.properties import AodhProperties as AodhProps
|
from vitrage.datasources.aodh.properties import AodhProperties as AodhProps
|
||||||
from vitrage.tests import base
|
from vitrage.tests import base
|
||||||
from vitrage.tests.mocks import mock_driver
|
from vitrage.tests.mocks import mock_driver
|
||||||
@ -312,6 +313,500 @@ class AodhDriverTest(base.BaseTest):
|
|||||||
# Test assertions
|
# Test assertions
|
||||||
self.assertIsNone(entity)
|
self.assertIsNone(entity)
|
||||||
|
|
||||||
|
def test_gnocchi_aggregation_by_metrics_alarm_notifications(self):
|
||||||
|
aodh_driver = MockAodhDriver(self.conf)
|
||||||
|
|
||||||
|
# 1. alarm creation with 'ok' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {
|
||||||
|
"type": AType.GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD,
|
||||||
|
AodhProps.DETAIL: self._create_alarm_data_metrics()
|
||||||
|
}
|
||||||
|
generators = \
|
||||||
|
mock_driver.simple_aodh_alarm_notification_generators(
|
||||||
|
alarm_num=1,
|
||||||
|
update_events=1,
|
||||||
|
update_vals=detail_data)
|
||||||
|
alarm = mock_driver.generate_sequential_events_list(generators)[0]
|
||||||
|
alarm_info = alarm.copy()
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm with status OK should not be handled
|
||||||
|
self.assertIsNone(entity)
|
||||||
|
|
||||||
|
# 2.alarm state transition from 'ok' to 'alarm'
|
||||||
|
detail_data = {"type": "state transition",
|
||||||
|
AodhProps.DETAIL: {AodhProps.STATE: "alarm"}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm state change: ok->alarm, need to be added
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.STATE],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.STATE])
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.SEVERITY])
|
||||||
|
|
||||||
|
# 3. delete alarm which is 'alarm' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "deletion"}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# 4. alarm creation with 'alarm' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {
|
||||||
|
"type": AType.GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD,
|
||||||
|
AodhProps.DETAIL: self._create_alarm_data_metrics(state="alarm")
|
||||||
|
}
|
||||||
|
generators = \
|
||||||
|
mock_driver.simple_aodh_alarm_notification_generators(
|
||||||
|
alarm_num=1,
|
||||||
|
update_events=1,
|
||||||
|
update_vals=detail_data)
|
||||||
|
alarm = mock_driver.generate_sequential_events_list(generators)[0]
|
||||||
|
alarm_info = alarm.copy()
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm with status 'alarm' need to be added
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.STATE],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.STATE])
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.SEVERITY])
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# 5. alarm rule change
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "rule change",
|
||||||
|
AodhProps.DETAIL: {
|
||||||
|
"severity": "critical",
|
||||||
|
AodhProps.RULE:
|
||||||
|
{"granularity": "300",
|
||||||
|
"threshold": "0.0123",
|
||||||
|
"comparison_operator": "eq"}}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.RULE_CHANGE)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm rule change: need to be update
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.SEVERITY])
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.RULE_CHANGE)
|
||||||
|
|
||||||
|
# 6. alarm state change from 'alarm' to 'ok'
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "state transition",
|
||||||
|
AodhProps.DETAIL: {AodhProps.STATE: "ok"}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm state change: alarm->OK, need to be deleted
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# 7. delete alarm which is 'ok' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "deletion"}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertIsNone(entity)
|
||||||
|
|
||||||
|
def test_gnocchi_aggregation_by_resource_alarm_notifications(self):
|
||||||
|
aodh_driver = MockAodhDriver(self.conf)
|
||||||
|
|
||||||
|
# 1. alarm creation with 'ok' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {
|
||||||
|
"type": AType.GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD,
|
||||||
|
AodhProps.DETAIL: self._create_alarm_data_resource()
|
||||||
|
}
|
||||||
|
generators = \
|
||||||
|
mock_driver.simple_aodh_alarm_notification_generators(
|
||||||
|
alarm_num=1,
|
||||||
|
update_events=1,
|
||||||
|
update_vals=detail_data)
|
||||||
|
alarm = mock_driver.generate_sequential_events_list(generators)[0]
|
||||||
|
alarm_info = alarm.copy()
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm with status OK should not be handled
|
||||||
|
self.assertIsNone(entity)
|
||||||
|
|
||||||
|
# 2.alarm state transition from 'ok' to 'alarm'
|
||||||
|
detail_data = {"type": "state transition",
|
||||||
|
AodhProps.DETAIL: {AodhProps.STATE: "alarm"}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm state change: ok->alarm, need to be added
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.STATE],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.STATE])
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.SEVERITY])
|
||||||
|
|
||||||
|
# 3. delete alarm which is 'alarm' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "deletion"}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# 4. alarm creation with 'alarm' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {
|
||||||
|
"type": AType.GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD,
|
||||||
|
AodhProps.DETAIL:
|
||||||
|
self._create_alarm_data_gnocchi(state="alarm")
|
||||||
|
}
|
||||||
|
generators = \
|
||||||
|
mock_driver.simple_aodh_alarm_notification_generators(
|
||||||
|
alarm_num=1,
|
||||||
|
update_events=1,
|
||||||
|
update_vals=detail_data)
|
||||||
|
alarm = mock_driver.generate_sequential_events_list(generators)[0]
|
||||||
|
alarm_info = alarm.copy()
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm with status 'alarm' need to be added
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.STATE],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.STATE])
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.SEVERITY])
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# 5. alarm rule change
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "rule change",
|
||||||
|
AodhProps.DETAIL: {
|
||||||
|
"severity": "critical",
|
||||||
|
AodhProps.RULE:
|
||||||
|
{"granularity": "300",
|
||||||
|
"threshold": "0.0123",
|
||||||
|
"comparison_operator": "eq"}}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.RULE_CHANGE)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm rule change: need to be update
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.SEVERITY])
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.RULE_CHANGE)
|
||||||
|
|
||||||
|
# 6. alarm state change from 'alarm' to 'ok'
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "state transition",
|
||||||
|
AodhProps.DETAIL: {AodhProps.STATE: "ok"}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm state change: alarm->OK, need to be deleted
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# 7. delete alarm which is 'ok' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "deletion"}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertIsNone(entity)
|
||||||
|
|
||||||
|
def test_composite_alarm_notifications(self):
|
||||||
|
aodh_driver = MockAodhDriver(self.conf)
|
||||||
|
|
||||||
|
# 1. alarm creation with 'ok' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "composite",
|
||||||
|
AodhProps.DETAIL: self._create_alarm_data_composite()}
|
||||||
|
generators = \
|
||||||
|
mock_driver.simple_aodh_alarm_notification_generators(
|
||||||
|
alarm_num=1,
|
||||||
|
update_events=1,
|
||||||
|
update_vals=detail_data)
|
||||||
|
alarm = mock_driver.generate_sequential_events_list(generators)[0]
|
||||||
|
alarm_info = alarm.copy()
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm with status OK should not be handled
|
||||||
|
self.assertIsNone(entity)
|
||||||
|
|
||||||
|
# 2.alarm state transition from 'ok' to 'alarm'
|
||||||
|
detail_data = {"type": "state transition",
|
||||||
|
AodhProps.DETAIL: {AodhProps.STATE: "alarm"}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm state change: ok->alarm, need to be added
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.STATE],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.STATE])
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.SEVERITY])
|
||||||
|
|
||||||
|
# 3. delete alarm which is 'alarm' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "deletion"}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# 4. alarm creation with 'alarm' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "composite",
|
||||||
|
AodhProps.DETAIL:
|
||||||
|
self._create_alarm_data_composite(state="alarm")}
|
||||||
|
generators = \
|
||||||
|
mock_driver.simple_aodh_alarm_notification_generators(
|
||||||
|
alarm_num=1,
|
||||||
|
update_events=1,
|
||||||
|
update_vals=detail_data)
|
||||||
|
alarm = mock_driver.generate_sequential_events_list(generators)[0]
|
||||||
|
alarm_info = alarm.copy()
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm with status 'alarm' need to be added
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.STATE],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.STATE])
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.SEVERITY])
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.CREATION)
|
||||||
|
|
||||||
|
# 5. alarm rule change
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "rule change",
|
||||||
|
AodhProps.DETAIL: {
|
||||||
|
"severity": "critical",
|
||||||
|
AodhProps.RULE:
|
||||||
|
{"granularity": "300",
|
||||||
|
"threshold": "0.0123",
|
||||||
|
"comparison_operator": "eq"}}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.RULE_CHANGE)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm rule change: need to be update
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[AodhProps.SEVERITY],
|
||||||
|
alarm[AodhProps.DETAIL][AodhProps.SEVERITY])
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.RULE_CHANGE)
|
||||||
|
|
||||||
|
# 6. alarm state change from 'alarm' to 'ok'
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "state transition",
|
||||||
|
AodhProps.DETAIL: {AodhProps.STATE: "ok"}}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm,
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
# alarm state change: alarm->OK, need to be deleted
|
||||||
|
self.assertIsNotNone(entity)
|
||||||
|
self._validate_aodh_entity_comm_props(entity, alarm_info)
|
||||||
|
self.assertEqual(entity[DSProps.EVENT_TYPE],
|
||||||
|
AodhEventType.STATE_TRANSITION)
|
||||||
|
|
||||||
|
# 7. delete alarm which is 'ok' state
|
||||||
|
# prepare data
|
||||||
|
detail_data = {"type": "deletion"}
|
||||||
|
alarm.update(detail_data)
|
||||||
|
|
||||||
|
# action
|
||||||
|
entity = aodh_driver.enrich_event(alarm, AodhEventType.DELETION)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertIsNone(entity)
|
||||||
|
|
||||||
|
def _create_alarm_data_composite(self,
|
||||||
|
state='ok',
|
||||||
|
type='composite',
|
||||||
|
rule=None):
|
||||||
|
if rule is None:
|
||||||
|
rule = {"or":
|
||||||
|
[{"evaluation_periods": 1,
|
||||||
|
"metrics": ["6ade05e5-f98b-4b7d-a0b3-9d330c4c3c41"],
|
||||||
|
"aggregation_method": "mean",
|
||||||
|
"granularity": 60,
|
||||||
|
"threshold": 100.0,
|
||||||
|
"type": "gnocchi_aggregation_by_metrics_threshold",
|
||||||
|
"comparison_operator": "lt"},
|
||||||
|
{"evaluation_periods": 3,
|
||||||
|
"metrics": ["89vde0e5-k3rb-4b7d-a0b3-9d330c4c3c41"],
|
||||||
|
"aggregation_method": "mean",
|
||||||
|
"granularity": 2,
|
||||||
|
"threshold": 80.0,
|
||||||
|
"type": "gnocchi_aggregation_by_metrics_threshold",
|
||||||
|
"comparison_operator": "ge"}
|
||||||
|
]}
|
||||||
|
return {AodhProps.DESCRIPTION: "test",
|
||||||
|
AodhProps.TIMESTAMP: "2016-11-09T01:39:13.839584",
|
||||||
|
AodhProps.ENABLED: True,
|
||||||
|
AodhProps.STATE_TIMESTAMP: "2016-11-09T01:39:13.839584",
|
||||||
|
AodhProps.ALARM_ID: "7e5c3754-e2eb-4782-ae00-7da5ded8568b",
|
||||||
|
AodhProps.REPEAT_ACTIONS: False,
|
||||||
|
AodhProps.PROJECT_ID: "c365d18fcc03493187016ae743f0cc4d",
|
||||||
|
AodhProps.NAME: "test",
|
||||||
|
AodhProps.SEVERITY: "low",
|
||||||
|
AodhProps.RESOURCE_ID: "88cd2d1d-8af4-4d00-9b5e-f82f8c8b0f8d",
|
||||||
|
AodhProps.TYPE: type,
|
||||||
|
AodhProps.STATE: state,
|
||||||
|
AodhProps.RULE: rule}
|
||||||
|
|
||||||
|
def _create_alarm_data_metrics(
|
||||||
|
self,
|
||||||
|
state='ok',
|
||||||
|
type=AType.GNOCCHI_AGGREGATION_BY_METRICS_THRESHOLD,
|
||||||
|
rule=None
|
||||||
|
):
|
||||||
|
if rule is None:
|
||||||
|
rule = {"threshold": '100',
|
||||||
|
"aggregation_method": "mean",
|
||||||
|
"comparison_operator": "lt"
|
||||||
|
}
|
||||||
|
|
||||||
|
return {AodhProps.DESCRIPTION: "metric test",
|
||||||
|
AodhProps.TIMESTAMP: "2017-04-03T01:39:13.839584",
|
||||||
|
AodhProps.ENABLED: True,
|
||||||
|
AodhProps.STATE_TIMESTAMP: "2017-04-03T01:39:13.839584",
|
||||||
|
AodhProps.ALARM_ID: "7e5c3754-e2eb-4782-ae00-7da5ded8568b",
|
||||||
|
AodhProps.REPEAT_ACTIONS: False,
|
||||||
|
AodhProps.PROJECT_ID: "c365d18fcc03493187016ae743f0cc4d",
|
||||||
|
AodhProps.NAME: "test",
|
||||||
|
AodhProps.SEVERITY: "low",
|
||||||
|
AodhProps.RESOURCE_ID: "88cd2d1d-8af4-4d00-9b5e-f82f8c8b0f8d",
|
||||||
|
AodhProps.METRICS: "6ade05e5-f98b-4b7d-a0b3-9d330c4c3c41",
|
||||||
|
AodhProps.TYPE: type,
|
||||||
|
AodhProps.STATE: state,
|
||||||
|
AodhProps.RULE: rule}
|
||||||
|
|
||||||
|
def _create_alarm_data_resource(
|
||||||
|
self,
|
||||||
|
state='ok',
|
||||||
|
type=AType.GNOCCHI_AGGREGATION_BY_RESOURCES_THRESHOLD,
|
||||||
|
rule=None):
|
||||||
|
if rule is None:
|
||||||
|
rule = {"evaluation_periods": 3,
|
||||||
|
"metric": "cpu_util",
|
||||||
|
"aggregation_method": "mean",
|
||||||
|
"granularity": 300,
|
||||||
|
"threshold": 50.0,
|
||||||
|
"query": [{"=":
|
||||||
|
{"resource_id":
|
||||||
|
"6df1747a-ef31-4897-854e-ffa2ae568e45"}}],
|
||||||
|
"comparison_operator": "ge",
|
||||||
|
"resource_type": "instance"
|
||||||
|
}
|
||||||
|
|
||||||
|
return {AodhProps.DESCRIPTION: "test",
|
||||||
|
AodhProps.TIMESTAMP: "2016-11-09T01:39:13.839584",
|
||||||
|
AodhProps.ENABLED: True,
|
||||||
|
AodhProps.STATE_TIMESTAMP: "2016-11-09T01:39:13.839584",
|
||||||
|
AodhProps.ALARM_ID: "7e5c3754-e2eb-4782-ae00-7da5ded8568b",
|
||||||
|
AodhProps.REPEAT_ACTIONS: False,
|
||||||
|
AodhProps.PROJECT_ID: "c365d18fcc03493187016ae743f0cc4d",
|
||||||
|
AodhProps.NAME: "test",
|
||||||
|
AodhProps.SEVERITY: "low",
|
||||||
|
AodhProps.RESOURCE_ID: "88cd2d1d-8af4-4d00-9b5e-f82f8c8b0f8d",
|
||||||
|
AodhProps.TYPE: type,
|
||||||
|
AodhProps.STATE: state,
|
||||||
|
AodhProps.RULE: rule}
|
||||||
|
|
||||||
def _create_alarm_data_gnocchi(self,
|
def _create_alarm_data_gnocchi(self,
|
||||||
state="ok",
|
state="ok",
|
||||||
type="gnocchi_resources_threshold",
|
type="gnocchi_resources_threshold",
|
||||||
|
Loading…
Reference in New Issue
Block a user