diff --git a/vitrage/evaluator/scenario_repository.py b/vitrage/evaluator/scenario_repository.py index 8eae255e8..056379f9a 100644 --- a/vitrage/evaluator/scenario_repository.py +++ b/vitrage/evaluator/scenario_repository.py @@ -84,9 +84,7 @@ class ScenarioRepository(object): def _add_template_scenarios(self, template): for scenario in template.scenarios: - - condition_vars = self._extract_condition_vars(scenario.condition) - for condition_var in condition_vars: + for condition_var in scenario.condition: if condition_var.type == RELATIONSHIP: edge_desc = condition_var.variable @@ -100,15 +98,6 @@ class ScenarioRepository(object): def _create_scenario_key(properties): return frozenset(properties) - @staticmethod - def _extract_condition_vars(condition): - - condition_vars = [] - for and_condition in condition: - condition_vars = condition_vars + and_condition - - return condition_vars - def _add_relationship(self, scenario, edge_desc): key = self._create_edge_scenario_key(edge_desc) diff --git a/vitrage/evaluator/template.py b/vitrage/evaluator/template.py index 8cf588a29..39e9f5ca0 100644 --- a/vitrage/evaluator/template.py +++ b/vitrage/evaluator/template.py @@ -178,7 +178,7 @@ class Template(object): return self._extract_or_condition(condition_dnf) if isinstance(condition_dnf, And): - return [self._extract_and_condition(condition_dnf)] + return self._extract_and_condition(condition_dnf) if isinstance(condition_dnf, Not): return [(self._extract_condition_var(condition_dnf, False))] diff --git a/vitrage/evaluator/template_syntax_validator.py b/vitrage/evaluator/template_syntax_validator.py index dafa57ad8..489cb33eb 100644 --- a/vitrage/evaluator/template_syntax_validator.py +++ b/vitrage/evaluator/template_syntax_validator.py @@ -126,7 +126,7 @@ def validate_entity(entity): Required(TemplateFields.CATEGORY): Any(str, basestring), TemplateFields.TYPE: Any(str, basestring), Required(TemplateFields.TEMPLATE_ID): Any(str, basestring, int) - }) + }, extra=True) error_msg = SCHEMA_CONTENT_ERROR % ( TemplateFields.ENTITY, '"%s" and "%s"' % (TemplateFields.CATEGORY, TemplateFields.TEMPLATE_ID) diff --git a/vitrage/tests/resources/templates/basic.yaml b/vitrage/tests/resources/templates/basic.yaml new file mode 100644 index 000000000..3bcf2c6ad --- /dev/null +++ b/vitrage/tests/resources/templates/basic.yaml @@ -0,0 +1,29 @@ +metadata: + id: basic_template +definitions: + entities: + - entity: + category: ALARM + type: nagios + name: HOST_HIGH_CPU_LOAD + template_id: 1 + - entity: + category: RESOURCE + type: nova.host + template_id: 2 + relationships: + - relationship: + source: 1 + target: 2 + relationship_type: on + template_id : alarm_on_host +scenarios: + - scenario: + condition: alarm_on_host + actions: + - action: + action_type: SET_STATE + properties: + state: SUBOPTIMAL + action_target: + target: 2 diff --git a/vitrage/tests/unit/evaluator/test_scenario_repository.py b/vitrage/tests/unit/evaluator/test_scenario_repository.py index 945d63daf..ac18d1625 100644 --- a/vitrage/tests/unit/evaluator/test_scenario_repository.py +++ b/vitrage/tests/unit/evaluator/test_scenario_repository.py @@ -51,7 +51,7 @@ class ScenarioRepositoryTest(base.BaseTest): # Test assertions self.assertIsNotNone(scenario_repository) - self.assertEqual(1, len(scenario_repository.templates)) + self.assertEqual(2, len(scenario_repository.templates)) def test_init_scenario_repository(self): @@ -74,6 +74,4 @@ class ScenarioRepositoryTest(base.BaseTest): pass def test_add_template(self): - - # Test Assertions - print('lol') + pass diff --git a/vitrage/tests/unit/evaluator/test_template.py b/vitrage/tests/unit/evaluator/test_template.py index 25c9646eb..1b74ef17c 100644 --- a/vitrage/tests/unit/evaluator/test_template.py +++ b/vitrage/tests/unit/evaluator/test_template.py @@ -13,7 +13,9 @@ # under the License. from oslo_log import log as logging +from vitrage.common.constants import EdgeLabels from vitrage.common import file_utils +from vitrage.evaluator.template import ConditionVar from vitrage.evaluator.template import EdgeDescription from vitrage.evaluator.template import Template from vitrage.evaluator.template_fields import TemplateFields as TFields @@ -24,15 +26,15 @@ from vitrage.tests.mocks import utils LOG = logging.getLogger(__name__) -class TemplateTest(base.BaseTest): +class BasicTemplateTest(base.BaseTest): - VALID_TEMPLATE_NAME = 'host_high_cpu_load_to_instance_cpu_suboptimal.yaml' + BASIC_TEMPLATE = 'basic.yaml' - def test_valid_template(self): + def test_basic_template(self): # Test setup template_path = '%s/templates/%s' % (utils.get_resources_dir(), - self.VALID_TEMPLATE_NAME) + self.BASIC_TEMPLATE) template_definition = file_utils.load_yaml_file(template_path, True) template = Template(template_definition) @@ -47,9 +49,7 @@ class TemplateTest(base.BaseTest): relate_def = definitions[TFields.RELATIONSHIPS] self._validate_relationships(relationships, relate_def, entities) - - scenarios_definition = template_definition[TFields.SCENARIOS] - self._validate_scenarios(scenarios, scenarios_definition) + self._validate_scenarios(scenarios, entities) def _validate_entities(self, entities, entities_def): @@ -102,12 +102,51 @@ class TemplateTest(base.BaseTest): continue self.assertEqual(value, relationship.properties[key]) - def _validate_scenarios(self, scenarios, scenarios_definition): + def _validate_scenarios(self, scenarios, entities): + """Validates scenario parsing + Expects to single scenario: + 1. condition consitsts from one variable (type EdgeDescription) + 2. Actions - set state action + :param scenarios: parsed scenarios + :param scenarios_definition: + """ self.assertIsNotNone(scenarios) - self.assertEqual(len(scenarios), len(scenarios_definition)) + self.assertEqual(len(scenarios), 1) - for scenario in scenarios: + scenario = scenarios[0] - self.assert_is_not_empty(scenario.condition) - self.assert_is_not_empty(scenario.actions) + condition = scenario.condition + self.assertEqual(len(condition), 1) + + condition_var = condition[0] + self.assertTrue(isinstance(condition_var, ConditionVar)) + + variable = condition_var.variable + self.assertTrue(isinstance(variable, EdgeDescription)) + + edge = variable[0] + self.assertEqual(edge.source_id, '1') + self.assertEqual(edge.target_id, '2') + self.assertEqual(edge.label, EdgeLabels.ON) + + source = variable[1] + self.assertEqual(source, entities[source.vertex_id]) + + target = variable[2] + self.assertEqual(target, entities[target.vertex_id]) + + actions = scenario.actions + self.assert_is_not_empty(scenario.actions) + self.assertEqual(len(actions), 1) + + action = actions[0] + self.assertEqual(action.type, 'SET_STATE') + + targets = action.targets + self.assertEqual(len(targets), 1) + self.assertEqual(targets['target'], '2') + + properties = action.properties + self.assertEqual(len(properties), 1) + self.assertEqual(properties['state'], 'SUBOPTIMAL')