Merge "fix bugs: Merging actions by action_spec should be moved after action_tracker"

This commit is contained in:
Jenkins 2017-05-24 14:51:03 +00:00 committed by Gerrit Code Review
commit b1a2ddf0bd
3 changed files with 193 additions and 18 deletions

View File

@ -100,14 +100,14 @@ class ScenarioEvaluator(object):
actions = self._process_and_get_actions(before,
before_scenarios,
ActionMode.UNDO)
actions.update(self._process_and_get_actions(current,
actions.extend(self._process_and_get_actions(current,
current_scenarios,
ActionMode.DO))
if actions:
LOG.debug("Actions to perform: %s", actions.values())
LOG.debug("Actions to perform: %s", actions)
filtered_actions = \
self._analyze_and_filter_actions(actions.values())
self._analyze_and_filter_actions(actions)
LOG.debug("Actions filtered: %s", filtered_actions)
for action in filtered_actions:
self._action_executor.execute(action.specs, action.mode)
@ -139,12 +139,12 @@ class ScenarioEvaluator(object):
return before, current
def _process_and_get_actions(self, element, triggered_scenarios, mode):
actions = {}
actions = []
for triggered_scenario in triggered_scenarios:
LOG.debug("Processing: %s", str(triggered_scenario))
scenario_element = triggered_scenario[0]
scenario = triggered_scenario[1]
actions.update(self._process_scenario(element,
actions.extend(self._process_scenario(element,
scenario,
scenario_element,
mode))
@ -153,7 +153,7 @@ class ScenarioEvaluator(object):
def _process_scenario(self, element, scenario, scenario_elements, mode):
if not isinstance(scenario_elements, list):
scenario_elements = [scenario_elements]
actions = {}
actions = []
for action in scenario.actions:
for scenario_element in scenario_elements:
matches = self._evaluate_subgraphs(scenario.subgraphs,
@ -161,7 +161,7 @@ class ScenarioEvaluator(object):
scenario_element,
action.targets['target'])
actions.update(self._get_actions_from_matches(matches,
actions.extend(self._get_actions_from_matches(matches,
mode,
action,
scenario))
@ -189,7 +189,7 @@ class ScenarioEvaluator(object):
mode,
action_spec,
scenario):
actions = {}
actions = []
for is_switch_mode, matches in combined_matches:
new_mode = mode
if is_switch_mode:
@ -197,11 +197,11 @@ class ScenarioEvaluator(object):
if mode == ActionMode.DO else ActionMode.DO
for match in matches:
spec, action_id = self._get_action_spec(action_spec, match)
spec = self._get_action_spec(action_spec, match)
items_ids = [match[1].vertex_id for match in match.items()]
match_hash = hash(tuple(sorted(items_ids)))
actions[action_id] = ActionInfo(spec, new_mode,
scenario.id, match_hash)
actions.append(ActionInfo(spec, new_mode,
scenario.id, match_hash))
return actions
@ -211,12 +211,9 @@ class ScenarioEvaluator(object):
real_items = {
target: match[target_id] for target, target_id in targets.items()
}
revised_spec = ActionSpecs(action_spec.type,
real_items,
action_spec.properties)
# noinspection PyTypeChecker
action_id = ScenarioEvaluator._generate_action_id(revised_spec)
return revised_spec, action_id
return ActionSpecs(action_spec.type,
real_items,
action_spec.properties)
@staticmethod
def _generate_action_id(action_spec):
@ -248,7 +245,12 @@ class ScenarioEvaluator(object):
actions_to_perform[key] = undo_action
elif new_dominant != prev_dominant:
actions_to_perform[key] = new_dominant
return actions_to_perform.values()
# filter the same action
final_actions = {ScenarioEvaluator._generate_action_id(action.specs):
action for action in actions_to_perform.values()}
return final_actions.values()
def _find_vertex_subgraph_matching(self,
subgraphs,

View File

@ -1145,6 +1145,126 @@ class TestScenarioEvaluator(TestFunctionalBase):
alarms = self._get_alarms_on_host(host_v, processor.entity_graph)
self.assertEqual(0, len(alarms))
def test_both_and_or_operator_for_tracker(self):
"""(alarm_a or alarm_b) and alarm_c use case
We have created the following template:
(alarm_a or alarm_b) and alarm_c cause alarm_d
1. alarm_a is reported
2. alarm_b is reported
3. alarm_c is reported --> alarm_d is raised
4. alarm_b is removed --> alarm_d should not be removed
5. alarm_a is removed --> alarm_d should be removed
"""
event_queue, processor, evaluator = self._init_system()
entity_graph = processor.entity_graph
# constants
num_orig_vertices = entity_graph.num_vertices()
num_orig_edges = entity_graph.num_edges()
host_v = self._get_entity_from_graph(NOVA_HOST_DATASOURCE,
_TARGET_HOST,
_TARGET_HOST,
entity_graph)
self.assertEqual('AVAILABLE', host_v[VProps.AGGREGATED_STATE],
'host should be AVAILABLE when starting')
# generate nagios alarm_a to trigger
test_vals = {'status': 'WARNING',
'service': 'alarm_a'}
test_vals.update(_NAGIOS_TEST_INFO)
generator = mock_driver.simple_nagios_alarm_generators(1, 1, test_vals)
alarm_a_test = mock_driver.generate_random_events_list(generator)[0]
host_v = self.get_host_after_event(event_queue, alarm_a_test,
processor, _TARGET_HOST)
alarms = self._get_alarms_on_host(host_v, entity_graph)
self.assertEqual(1, len(alarms))
self.assertEqual(num_orig_vertices + 1, entity_graph.num_vertices())
self.assertEqual(num_orig_edges + 1, entity_graph.num_edges())
# generate nagios alarm_b to trigger
test_vals = {'status': 'WARNING',
'service': 'alarm_b'}
test_vals.update(_NAGIOS_TEST_INFO)
generator = mock_driver.simple_nagios_alarm_generators(1, 1, test_vals)
alarm_b_test = mock_driver.generate_random_events_list(generator)[0]
host_v = self.get_host_after_event(event_queue, alarm_b_test,
processor, _TARGET_HOST)
alarms = self._get_alarms_on_host(host_v, entity_graph)
self.assertEqual(2, len(alarms))
self.assertEqual(num_orig_vertices + 2, entity_graph.num_vertices())
self.assertEqual(num_orig_edges + 2, entity_graph.num_edges())
# generate nagios alarm_c to trigger, alarm_d is raised
test_vals = {'status': 'WARNING',
'service': 'alarm_c'}
test_vals.update(_NAGIOS_TEST_INFO)
generator = mock_driver.simple_nagios_alarm_generators(1, 1, test_vals)
alarm_c_test = mock_driver.generate_random_events_list(generator)[0]
host_v = self.get_host_after_event(event_queue, alarm_c_test,
processor, _TARGET_HOST)
alarms = self._get_alarms_on_host(host_v, entity_graph)
self.assertEqual(4, len(alarms))
self.assertEqual(num_orig_vertices + 4, entity_graph.num_vertices())
self.assertEqual(num_orig_edges + 4, entity_graph.num_edges())
# remove nagios alarm_b, alarm_d should not be removed
test_vals = {'status': 'OK',
'service': 'alarm_b'}
test_vals.update(_NAGIOS_TEST_INFO)
generator = mock_driver.simple_nagios_alarm_generators(1, 1, test_vals)
alarm_b_ok = mock_driver.generate_random_events_list(generator)[0]
host_v = self.get_host_after_event(event_queue, alarm_b_ok,
processor, _TARGET_HOST)
alarms = self._get_alarms_on_host(host_v, entity_graph)
self.assertEqual(3, len(alarms))
query = {VProps.CATEGORY: EntityCategory.ALARM,
VProps.IS_DELETED: True}
deleted_alarms = entity_graph.neighbors(host_v.vertex_id,
vertex_attr_filter=query)
self.assertEqual(num_orig_vertices + len(deleted_alarms) + 3,
entity_graph.num_vertices())
query = {VProps.IS_DELETED: True}
deleted_edges = entity_graph.neighbors(host_v.vertex_id,
edge_attr_filter=query)
self.assertEqual(num_orig_edges + len(deleted_edges) + 3,
entity_graph.num_edges())
# remove nagios alarm_a, alarm_d should be removed
test_vals = {'status': 'OK',
'service': 'alarm_a'}
test_vals.update(_NAGIOS_TEST_INFO)
generator = mock_driver.simple_nagios_alarm_generators(1, 1, test_vals)
alarm_a_ok = mock_driver.generate_random_events_list(generator)[0]
host_v = self.get_host_after_event(event_queue, alarm_a_ok,
processor, _TARGET_HOST)
alarms = self._get_alarms_on_host(host_v, entity_graph)
self.assertEqual(1, len(alarms))
query = {VProps.CATEGORY: EntityCategory.ALARM,
VProps.IS_DELETED: True}
deleted_alarms = entity_graph.neighbors(host_v.vertex_id,
vertex_attr_filter=query)
self.assertEqual(num_orig_vertices + len(deleted_alarms) + 1,
entity_graph.num_vertices())
query = {VProps.IS_DELETED: True}
deleted_edges = entity_graph.neighbors(host_v.vertex_id,
edge_attr_filter=query)
self.assertEqual(num_orig_edges + len(deleted_edges) + 1,
entity_graph.num_edges())
def get_host_after_event(self, event_queue, nagios_event,
processor, target_host):
processor.process_event(nagios_event)

View File

@ -0,0 +1,53 @@
metadata:
name: complex_and_or_operator_deduced_alarm
definitions:
entities:
- entity:
category: ALARM
type: nagios
name: alarm_a
severity: WARNING
template_id: alarm_a
- entity:
category: ALARM
type: nagios
name: alarm_b
severity: WARNING
template_id: alarm_b
- entity:
category: ALARM
type: nagios
name: alarm_c
severity: WARNING
template_id: alarm_c
- entity:
category: RESOURCE
type: nova.host
template_id: host
relationships:
- relationship:
source: alarm_a
relationship_type: on
target: host
template_id : alarm_a_on_host
- relationship:
source: alarm_b
relationship_type: on
target: host
template_id : alarm_b_on_host
- relationship:
source: alarm_c
relationship_type: on
target: host
template_id : alarm_c_on_host
scenarios:
- scenario:
condition: (alarm_a_on_host or alarm_b_on_host) and alarm_c_on_host
actions:
- action:
action_type: raise_alarm
properties:
alarm_name: alarm_d
severity: WARNING
action_target:
target: host