diff --git a/vitrage/api_handler/apis/template.py b/vitrage/api_handler/apis/template.py index 00105a2db..7f35e6a4d 100644 --- a/vitrage/api_handler/apis/template.py +++ b/vitrage/api_handler/apis/template.py @@ -17,8 +17,8 @@ from oslo_log import log from vitrage.evaluator.template_fields import TemplateFields from vitrage.evaluator.template_validation.status_messages import status_msgs -from vitrage.evaluator.template_validation.template_content_validator import \ - content_validation +from vitrage.evaluator.template_validation.template_content_validator \ + import content_validation from vitrage.evaluator.template_validation.template_syntax_validator import \ syntax_validation diff --git a/vitrage/evaluator/scenario_repository.py b/vitrage/evaluator/scenario_repository.py index b087a3389..953c42d60 100644 --- a/vitrage/evaluator/scenario_repository.py +++ b/vitrage/evaluator/scenario_repository.py @@ -21,8 +21,8 @@ from oslo_utils import uuidutils from vitrage.evaluator.base import Template from vitrage.evaluator.equivalence_repository import EquivalenceRepository from vitrage.evaluator.template_data import TemplateData -from vitrage.evaluator.template_validation.template_content_validator import \ - content_validation +from vitrage.evaluator.template_validation.template_content_validator \ + import content_validation from vitrage.evaluator.template_validation.template_syntax_validator import \ syntax_validation from vitrage.utils import datetime as datetime_utils diff --git a/vitrage/evaluator/template_validation/content/__init__.py b/vitrage/evaluator/template_validation/content/__init__.py new file mode 100644 index 000000000..bf9f61d74 --- /dev/null +++ b/vitrage/evaluator/template_validation/content/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +__author__ = 'stack' diff --git a/vitrage/evaluator/template_validation/content/add_causal_relationship_validator.py b/vitrage/evaluator/template_validation/content/add_causal_relationship_validator.py new file mode 100644 index 000000000..ba410e342 --- /dev/null +++ b/vitrage/evaluator/template_validation/content/add_causal_relationship_validator.py @@ -0,0 +1,73 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_log import log + +from vitrage.common.constants import EntityCategory +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content.base import \ + ActionValidator +from vitrage.evaluator.template_validation.content.base import \ + get_content_correct_result +from vitrage.evaluator.template_validation.content.base import \ + get_content_fault_result +from vitrage.evaluator.template_validation.content.base import \ + validate_template_id +from vitrage.evaluator.template_validation.status_messages import status_msgs + + +LOG = log.getLogger(__name__) + + +class AddCausalRelationshipValidator(ActionValidator): + + @staticmethod + def validate(action, definitions_index): + if TemplateFields.ACTION_TARGET not in action: + LOG.error('%s status code: %s' % (status_msgs[124], 124)) + return get_content_fault_result(124) + + action_target = action[TemplateFields.ACTION_TARGET] + + for key in [TemplateFields.TARGET, TemplateFields.SOURCE]: + if key not in action_target: + LOG.error('%s status code: %s' % (status_msgs[130], 130)) + return get_content_fault_result(130) + + template_id = action_target[key] + result = validate_template_id(definitions_index, template_id) + + if not result.is_valid_config: + return result + + entity = definitions_index[template_id] + result = AddCausalRelationshipValidator._validate_entity_category( + entity, + EntityCategory.ALARM) + if not result.is_valid_config: + return result + + return get_content_correct_result() + + @staticmethod + def _validate_entity_category(entity_to_check, category): + + if TemplateFields.CATEGORY not in entity_to_check \ + or entity_to_check[TemplateFields.CATEGORY] != category: + msg = status_msgs[132] + ' expect %s to be %s' \ + % (entity_to_check, category) + LOG.error('%s status code: %s' % (msg, 132)) + return get_content_fault_result(132, msg) + + return get_content_correct_result() diff --git a/vitrage/evaluator/template_validation/content/base.py b/vitrage/evaluator/template_validation/content/base.py new file mode 100644 index 000000000..96d0a6a79 --- /dev/null +++ b/vitrage/evaluator/template_validation/content/base.py @@ -0,0 +1,60 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import abc +import six + +from oslo_log import log +from vitrage.evaluator.template_validation.base import get_correct_result +from vitrage.evaluator.template_validation.base import get_fault_result +from vitrage.evaluator.template_validation.status_messages import status_msgs + + +LOG = log.getLogger(__name__) +RESULT_DESCRIPTION = 'Template content validation' + + +def get_content_correct_result(): + return get_correct_result(RESULT_DESCRIPTION) + + +def get_content_fault_result(code, msg=None): + return get_fault_result(RESULT_DESCRIPTION, code, msg) + + +def validate_template_id(definitions_index, id_to_check): + if id_to_check not in definitions_index: + msg = status_msgs[3] + ' template id: %s' % id_to_check + LOG.error('%s status code: %s' % (msg, 3)) + return get_fault_result(RESULT_DESCRIPTION, 3, msg) + + return get_correct_result(RESULT_DESCRIPTION) + + +@six.add_metaclass(abc.ABCMeta) +class ActionValidator(object): + + @staticmethod + @abc.abstractmethod + def validate(action, definitions_index): + """Validate the content of the action. + + :param action: The action to be validated + :type action: dict + + :param definitions_index: Entities and relationships in the template + :type definitions_index: dict + + """ + pass diff --git a/vitrage/evaluator/template_validation/content/mark_down_validator.py b/vitrage/evaluator/template_validation/content/mark_down_validator.py new file mode 100644 index 000000000..67f5d1c73 --- /dev/null +++ b/vitrage/evaluator/template_validation/content/mark_down_validator.py @@ -0,0 +1,44 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_log import log + +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content.base import \ + ActionValidator +from vitrage.evaluator.template_validation.content.base import \ + get_content_fault_result +from vitrage.evaluator.template_validation.content.base import \ + validate_template_id +from vitrage.evaluator.template_validation.status_messages import status_msgs + + +LOG = log.getLogger(__name__) + + +class MarkDownValidator(ActionValidator): + + @staticmethod + def validate(action, definitions_index): + if TemplateFields.ACTION_TARGET not in action: + LOG.error('%s status code: %s' % (status_msgs[124], 124)) + return get_content_fault_result(124) + + action_target = action[TemplateFields.ACTION_TARGET] + if TemplateFields.TARGET not in action_target: + LOG.error('%s status code: %s' % (status_msgs[131], 131)) + return get_content_fault_result(131) + + target = action_target[TemplateFields.TARGET] + return validate_template_id(definitions_index, target) diff --git a/vitrage/evaluator/template_validation/content/raise_alarm_validator.py b/vitrage/evaluator/template_validation/content/raise_alarm_validator.py new file mode 100644 index 000000000..f0247a939 --- /dev/null +++ b/vitrage/evaluator/template_validation/content/raise_alarm_validator.py @@ -0,0 +1,54 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_log import log + +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content.base import \ + ActionValidator +from vitrage.evaluator.template_validation.content.base import \ + get_content_fault_result +from vitrage.evaluator.template_validation.content.base import \ + validate_template_id +from vitrage.evaluator.template_validation.status_messages import status_msgs + + +LOG = log.getLogger(__name__) + + +class RaiseAlarmValidator(ActionValidator): + + @staticmethod + def validate(action, definitions_index): + if TemplateFields.ACTION_TARGET not in action: + LOG.error('%s status code: %s' % (status_msgs[124], 124)) + return get_content_fault_result(124) + + properties = action[TemplateFields.PROPERTIES] + + if TemplateFields.ALARM_NAME not in properties: + LOG.error('%s status code: %s' % (status_msgs[125], 125)) + return get_content_fault_result(125) + + if TemplateFields.SEVERITY not in properties: + LOG.error('%s status code: %s' % (status_msgs[126], 126)) + return get_content_fault_result(126) + + action_target = action[TemplateFields.ACTION_TARGET] + if TemplateFields.TARGET not in action_target: + LOG.error('%s status code: %s' % (status_msgs[127], 127)) + return get_content_fault_result(127) + + target = action_target[TemplateFields.TARGET] + return validate_template_id(definitions_index, target) diff --git a/vitrage/evaluator/template_validation/content/set_state_validator.py b/vitrage/evaluator/template_validation/content/set_state_validator.py new file mode 100644 index 000000000..944dd0084 --- /dev/null +++ b/vitrage/evaluator/template_validation/content/set_state_validator.py @@ -0,0 +1,50 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_log import log + +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content.base import \ + ActionValidator +from vitrage.evaluator.template_validation.content.base import \ + get_content_fault_result +from vitrage.evaluator.template_validation.content.base import \ + validate_template_id +from vitrage.evaluator.template_validation.status_messages import status_msgs + + +LOG = log.getLogger(__name__) + + +class SetStateValidator(ActionValidator): + + @staticmethod + def validate(action, definitions_index): + if TemplateFields.ACTION_TARGET not in action: + LOG.error('%s status code: %s' % (status_msgs[124], 124)) + return get_content_fault_result(124) + + properties = action[TemplateFields.PROPERTIES] + + if TemplateFields.STATE not in properties: + LOG.error('%s status code: %s' % (status_msgs[128], 128)) + return get_content_fault_result(128) + + action_target = action[TemplateFields.ACTION_TARGET] + if TemplateFields.TARGET not in action_target: + LOG.error('%s status code: %s' % (status_msgs[129], 129)) + return get_content_fault_result(129) + + target = action_target[TemplateFields.TARGET] + return validate_template_id(definitions_index, target) diff --git a/vitrage/evaluator/template_validation/template_content_validator.py b/vitrage/evaluator/template_validation/template_content_validator.py index 3fa55d197..cf49698c8 100644 --- a/vitrage/evaluator/template_validation/template_content_validator.py +++ b/vitrage/evaluator/template_validation/template_content_validator.py @@ -19,20 +19,28 @@ from oslo_log import log from six.moves import reduce from vitrage.common.constants import EdgeProperties as EProps -from vitrage.common.constants import EntityCategory from vitrage.evaluator.actions.base import ActionType from vitrage.evaluator.template_data import TemplateData from vitrage.evaluator.template_fields import TemplateFields -from vitrage.evaluator.template_validation.base import get_correct_result -from vitrage.evaluator.template_validation.base import get_fault_result +from vitrage.evaluator.template_validation.content. \ + add_causal_relationship_validator import AddCausalRelationshipValidator +from vitrage.evaluator.template_validation.content.base import \ + get_content_correct_result +from vitrage.evaluator.template_validation.content.base import \ + get_content_fault_result +from vitrage.evaluator.template_validation.content.base import \ + validate_template_id +from vitrage.evaluator.template_validation.content.mark_down_validator \ + import MarkDownValidator +from vitrage.evaluator.template_validation.content.raise_alarm_validator \ + import RaiseAlarmValidator +from vitrage.evaluator.template_validation.content.set_state_validator \ + import SetStateValidator from vitrage.evaluator.template_validation.status_messages import status_msgs LOG = log.getLogger(__name__) -RESULT_DESCRIPTION = 'Template content validation' - - def content_validation(template): template_definitions = template[TemplateFields.DEFINITIONS] @@ -71,7 +79,7 @@ def _validate_entities_definition(entities, entities_index): entities_index[entity_dict[TemplateFields.TEMPLATE_ID]] = entity_dict - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() def _validate_entity_definition(entity_dict, entities_index): @@ -79,9 +87,9 @@ def _validate_entity_definition(entity_dict, entities_index): template_id = entity_dict[TemplateFields.TEMPLATE_ID] if template_id in entities_index: LOG.error('%s status code: %s' % (status_msgs[2], 2)) - return get_fault_result(RESULT_DESCRIPTION, 2) + return get_content_fault_result(2) - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() def _validate_relationships_definitions(relationships, @@ -99,7 +107,7 @@ def _validate_relationships_definitions(relationships, template_id = relationship_dict[TemplateFields.TEMPLATE_ID] relationships_index[template_id] = relationship_dict - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() def _validate_relationship(relationship, relationships_index, entities_index): @@ -107,14 +115,14 @@ def _validate_relationship(relationship, relationships_index, entities_index): template_id = relationship[TemplateFields.TEMPLATE_ID] if template_id in relationships_index or template_id in entities_index: LOG.error('%s status code: %s' % (status_msgs[2], 2)) - return get_fault_result(RESULT_DESCRIPTION, 2) + return get_content_fault_result(2) target = relationship[TemplateFields.TARGET] - result = _validate_template_id(entities_index, target) + result = validate_template_id(entities_index, target) if result.is_valid_config: source = relationship[TemplateFields.SOURCE] - result = _validate_template_id(entities_index, source) + result = validate_template_id(entities_index, source) return result @@ -137,7 +145,7 @@ def _validate_scenarios(scenarios, definitions_index): if not result.is_valid_config: return result - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() def _validate_scenario_condition(condition, definitions_index): @@ -145,7 +153,7 @@ def _validate_scenario_condition(condition, definitions_index): dnf_result = TemplateData.ScenarioData.convert_to_dnf_format(condition) except Exception: LOG.error('%s status code: %s' % (status_msgs[85], 85)) - return get_fault_result(RESULT_DESCRIPTION, 85) + return get_content_fault_result(85) # not condition validation not_condition_result = \ @@ -164,11 +172,11 @@ def _validate_scenario_condition(condition, definitions_index): if len(condition_var.strip()) == 0: continue - result = _validate_template_id(definitions_index, condition_var) + result = validate_template_id(definitions_index, condition_var) if not result.is_valid_config: return result - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() def _validate_not_condition(dnf_result, definitions_index): @@ -189,12 +197,12 @@ def _validate_not_condition(dnf_result, definitions_index): definition.get(EProps.RELATIONSHIP_TYPE)): msg = status_msgs[86] + ' template id: %s' % arg LOG.error('%s status code: %s' % (msg, 86)) - return get_fault_result(RESULT_DESCRIPTION, 86, msg) + return get_content_fault_result(86, msg) else: res = _validate_not_condition(arg, definitions_index) if not res.is_valid_config: return res - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() for arg in dnf_result.args: if not isinstance(arg, Symbol): @@ -202,7 +210,7 @@ def _validate_not_condition(dnf_result, definitions_index): if not res.is_valid_config: return res - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() def _validate_scenario_actions(actions, definitions_index): @@ -213,116 +221,22 @@ def _validate_scenario_actions(actions, definitions_index): if not result.is_valid_config: return result - return get_correct_result(RESULT_DESCRIPTION) + return get_content_correct_result() def _validate_scenario_action(action, definitions_index): action_type = action[TemplateFields.ACTION_TYPE] - actions = { - ActionType.RAISE_ALARM: _validate_raise_alarm_action, - ActionType.SET_STATE: _validate_set_state_action, - ActionType.ADD_CAUSAL_RELATIONSHIP: - _validate_add_causal_relationship_action, - ActionType.MARK_DOWN: _validate_mark_down_action, + + action_validators = { + ActionType.RAISE_ALARM: RaiseAlarmValidator(), + ActionType.SET_STATE: SetStateValidator(), + ActionType.ADD_CAUSAL_RELATIONSHIP: AddCausalRelationshipValidator(), + ActionType.MARK_DOWN: MarkDownValidator(), } - if action_type not in actions.keys(): + if action_type not in action_validators: LOG.error('%s status code: %s' % (status_msgs[120], 120)) - return get_fault_result(RESULT_DESCRIPTION, 120) + return get_content_fault_result(120) - return actions[action_type](action, definitions_index) - - -def _validate_raise_alarm_action(action, definitions_index): - - properties = action[TemplateFields.PROPERTIES] - - if TemplateFields.ALARM_NAME not in properties: - LOG.error('%s status code: %s' % (status_msgs[125], 125)) - return get_fault_result(RESULT_DESCRIPTION, 125) - - if TemplateFields.SEVERITY not in properties: - LOG.error('%s status code: %s' % (status_msgs[126], 126)) - return get_fault_result(RESULT_DESCRIPTION, 126) - - action_target = action[TemplateFields.ACTION_TARGET] - if TemplateFields.TARGET not in action_target: - LOG.error('%s status code: %s' % (status_msgs[127], 127)) - return get_fault_result(RESULT_DESCRIPTION, 127) - - target = action_target[TemplateFields.TARGET] - return _validate_template_id(definitions_index, target) - - -def _validate_set_state_action(action, definitions_index): - - properties = action[TemplateFields.PROPERTIES] - - if TemplateFields.STATE not in properties: - LOG.error('%s status code: %s' % (status_msgs[128], 128)) - return get_fault_result(RESULT_DESCRIPTION, 128) - - action_target = action[TemplateFields.ACTION_TARGET] - if TemplateFields.TARGET not in action_target: - LOG.error('%s status code: %s' % (status_msgs[129], 129)) - return get_fault_result(RESULT_DESCRIPTION, 129) - - target = action_target[TemplateFields.TARGET] - return _validate_template_id(definitions_index, target) - - -def _validate_add_causal_relationship_action(action, definitions_index): - - action_target = action[TemplateFields.ACTION_TARGET] - - for key in [TemplateFields.TARGET, TemplateFields.SOURCE]: - if key not in action_target: - LOG.error('%s status code: %s' % (status_msgs[130], 130)) - return get_fault_result(RESULT_DESCRIPTION, 130) - - template_id = action_target[key] - result = _validate_template_id(definitions_index, template_id) - - if not result.is_valid_config: - return result - - entity = definitions_index[template_id] - result = _validate_entity_category(entity, EntityCategory.ALARM) - if not result.is_valid_config: - return result - - return get_correct_result(RESULT_DESCRIPTION) - - -def _validate_mark_down_action(action, definitions_index): - - action_target = action[TemplateFields.ACTION_TARGET] - if TemplateFields.TARGET not in action_target: - LOG.error('%s status code: %s' % (status_msgs[131], 131)) - return get_fault_result(RESULT_DESCRIPTION, 131) - - target = action_target[TemplateFields.TARGET] - return _validate_template_id(definitions_index, target) - - -def _validate_template_id(definitions_index, id_to_check): - - if id_to_check not in definitions_index: - msg = status_msgs[3] + ' template id: %s' % id_to_check - LOG.error('%s status code: %s' % (msg, 3)) - return get_fault_result(RESULT_DESCRIPTION, 3, msg) - - return get_correct_result(RESULT_DESCRIPTION) - - -def _validate_entity_category(entity_to_check, vitrage_category): - - if TemplateFields.CATEGORY not in entity_to_check \ - or entity_to_check[TemplateFields.CATEGORY] != vitrage_category: - msg = status_msgs[132] + ' expect %s to be %s' \ - % (entity_to_check, vitrage_category) - LOG.error('%s status code: %s' % (msg, 132)) - return get_fault_result(RESULT_DESCRIPTION, 132, msg) - - return get_correct_result(RESULT_DESCRIPTION) + return action_validators[action_type].validate(action, definitions_index) diff --git a/vitrage/evaluator/template_validation/template_syntax_validator.py b/vitrage/evaluator/template_validation/template_syntax_validator.py index 21a5d4852..8df45e157 100644 --- a/vitrage/evaluator/template_validation/template_syntax_validator.py +++ b/vitrage/evaluator/template_validation/template_syntax_validator.py @@ -230,7 +230,7 @@ def _validate_action_schema(action): Required(TemplateFields.ACTION_TYPE, msg=123): _validate_action_type_field(), TemplateFields.PROPERTIES: dict, - Required(TemplateFields.ACTION_TARGET, msg=124): dict + TemplateFields.ACTION_TARGET: dict }) return _validate_dict_schema(schema, action) diff --git a/vitrage/tests/unit/evaluator/template_validation/__init__.py b/vitrage/tests/unit/evaluator/template_validation/__init__.py new file mode 100644 index 000000000..bf9f61d74 --- /dev/null +++ b/vitrage/tests/unit/evaluator/template_validation/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +__author__ = 'stack' diff --git a/vitrage/tests/unit/evaluator/template_validation/content/__init__.py b/vitrage/tests/unit/evaluator/template_validation/content/__init__.py new file mode 100644 index 000000000..dd32b852f --- /dev/null +++ b/vitrage/tests/unit/evaluator/template_validation/content/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2016 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +__author__ = 'stack' diff --git a/vitrage/tests/unit/evaluator/template_validation/content/base.py b/vitrage/tests/unit/evaluator/template_validation/content/base.py new file mode 100644 index 000000000..3afaa1b20 --- /dev/null +++ b/vitrage/tests/unit/evaluator/template_validation/content/base.py @@ -0,0 +1,114 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from vitrage.common.constants import EntityCategory +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.status_messages import status_msgs +from vitrage.tests import base + + +DEFINITIONS_INDEX_MOCK = { + '123': {}, + '456': {}, + '789': {}, + 'a1': { + TemplateFields.CATEGORY: EntityCategory.ALARM + }, + 'a2': { + TemplateFields.CATEGORY: EntityCategory.ALARM + } +} + + +class ValidatorTest(base.BaseTest): + + def _assert_correct_result(self, result): + + self.assertTrue(result.is_valid_config) + self.assertEqual(result.comment, status_msgs[0]) + self.assertEqual(result.status_code, 0) + + def _assert_fault_result(self, result, status_code): + + self.assertFalse(result.is_valid_config) + self.assertTrue(result.comment.startswith(status_msgs[status_code])) + self.assertEqual(result.status_code, status_code) + + @staticmethod + def _hide_useless_logging_messages(): + + validator_path = 'vitrage.evaluator.template_validation.' \ + 'template_content_validator' + content_validator_log = logging.getLogger(validator_path) + content_validator_log.setLevel(logging.FATAL) + + +class ActionValidatorTest(ValidatorTest): + + # noinspection PyPep8Naming + @classmethod + def setUpClass(cls): + + cls._hide_useless_logging_messages() + + def _validate_action(self, action, validation_func): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + + # Test action and assertions + result = validation_func(action, idx) + + # Test Assertions + self._assert_correct_result(result) + + def _validate_action_without_action_target(self, action, validation_func): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action.pop(TemplateFields.ACTION_TARGET) + + # Test action + result = validation_func(action, idx) + + # Test assertions + self._assert_fault_result(result, 124) + + def _validate_action_with_invalid_target_id(self, action, validation_func): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + + # Test action + result = validation_func(action, idx) + + # Test assertions + self._assert_fault_result(result, 3) + + def _validate_action_without_target_id(self, + action, + validation_func, + expected_status_code): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action[TemplateFields.ACTION_TARGET].pop(TemplateFields.TARGET) + + # Test action + result = validation_func(action, idx) + + # Test assertions + self._assert_fault_result(result, expected_status_code) diff --git a/vitrage/tests/unit/evaluator/template_validation/content/test_add_causal_relationship_validator.py b/vitrage/tests/unit/evaluator/template_validation/content/test_add_causal_relationship_validator.py new file mode 100644 index 000000000..7aa943623 --- /dev/null +++ b/vitrage/tests/unit/evaluator/template_validation/content/test_add_causal_relationship_validator.py @@ -0,0 +1,111 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from vitrage.evaluator.actions.base import ActionType +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content. \ + add_causal_relationship_validator import AddCausalRelationshipValidator +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + ActionValidatorTest +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + DEFINITIONS_INDEX_MOCK + + +class AddCausalRelationshipValidatorTest(ActionValidatorTest): + + def test_validate_add_causal_relationship_action(self): + + self._validate_action( + self._create_add_causal_relationship_action('a1', 'a2'), + AddCausalRelationshipValidator.validate + ) + + def test_validate_add_causal_relation_action_without_action_target(self): + + self._validate_action_without_action_target( + self._create_add_causal_relationship_action('a1', 'a2'), + AddCausalRelationshipValidator.validate + ) + + def test_validate_add_causal_relationship_action_with_invalid_target(self): + + self._validate_action_with_invalid_target_id( + self._create_add_causal_relationship_action('unknown', 'a2'), + AddCausalRelationshipValidator.validate + ) + + def test_validate_add_causal_relationship_action_with_invalid_source(self): + + self._validate_action_with_invalid_target_id( + self._create_add_causal_relationship_action('a1', 'unknown'), + AddCausalRelationshipValidator.validate + ) + + def test_validate_add_causal_relationship_action_without_target(self): + + self._validate_action_without_target_id( + self._create_add_causal_relationship_action('a1', 'a2'), + AddCausalRelationshipValidator.validate, + 130 + ) + + def test_validate_add_causal_relationship_action_without_source(self): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action = self._create_add_causal_relationship_action('a1', 'a2') + action[TemplateFields.ACTION_TARGET].pop(TemplateFields.SOURCE, None) + + # Test action + result = AddCausalRelationshipValidator.validate(action, idx) + + # Test assertion + self._assert_fault_result(result, 130) + + def test_validate_add_causal_relationship_action_wrong_src_category(self): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action = self._create_add_causal_relationship_action('a1', '123') + + # Test action + result = AddCausalRelationshipValidator.validate(action, idx) + + # Test assertion + self._assert_fault_result(result, 132) + + def test_validate_add_causal_relationship_action_wrong_tgt_category(self): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action = self._create_add_causal_relationship_action('123', 'a1') + + # Test action + result = AddCausalRelationshipValidator.validate(action, idx) + + # Test assertion + self._assert_fault_result(result, 132) + + @staticmethod + def _create_add_causal_relationship_action(target, source): + + action_target = { + TemplateFields.TARGET: target, + TemplateFields.SOURCE: source + } + action = { + TemplateFields.ACTION_TYPE: ActionType.ADD_CAUSAL_RELATIONSHIP, + TemplateFields.ACTION_TARGET: action_target} + + return action diff --git a/vitrage/tests/unit/evaluator/template_validation/content/test_mark_down_validator.py b/vitrage/tests/unit/evaluator/template_validation/content/test_mark_down_validator.py new file mode 100644 index 000000000..c2c910ca2 --- /dev/null +++ b/vitrage/tests/unit/evaluator/template_validation/content/test_mark_down_validator.py @@ -0,0 +1,61 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from vitrage.evaluator.actions.base import ActionType +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content.mark_down_validator import \ + MarkDownValidator +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + ActionValidatorTest + + +class MarkDownValidatorTest(ActionValidatorTest): + def test_validate_mark_down_action(self): + + self._validate_action(self._create_mark_down_action('123'), + MarkDownValidator.validate) + + def test_validate_mark_down_action_without_action_target(self): + + self._validate_action_without_action_target( + self._create_mark_down_action('123'), + MarkDownValidator.validate + ) + + def test_validate_mark_down_action_with_invalid_target_id(self): + + self._validate_action_with_invalid_target_id( + self._create_mark_down_action('unknown'), + MarkDownValidator.validate + ) + + def test_validate_mark_down_action_without_target_id(self): + + self._validate_action_without_target_id( + self._create_mark_down_action('123'), + MarkDownValidator.validate, + 131 + ) + + @staticmethod + def _create_mark_down_action(target): + + action_target = { + TemplateFields.TARGET: target + } + action = { + TemplateFields.ACTION_TYPE: ActionType.MARK_DOWN, + TemplateFields.ACTION_TARGET: action_target, + } + return action diff --git a/vitrage/tests/unit/evaluator/template_validation/content/test_raise_alarm_validator.py b/vitrage/tests/unit/evaluator/template_validation/content/test_raise_alarm_validator.py new file mode 100644 index 000000000..18e6e650f --- /dev/null +++ b/vitrage/tests/unit/evaluator/template_validation/content/test_raise_alarm_validator.py @@ -0,0 +1,95 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from vitrage.evaluator.actions.base import ActionType +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content.raise_alarm_validator \ + import RaiseAlarmValidator +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + ActionValidatorTest +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + DEFINITIONS_INDEX_MOCK + + +class RaiseAlarmValidatorTest(ActionValidatorTest): + + def test_validate_raise_alarm_action(self): + + self._validate_action(self._create_raise_alarm_action('123'), + RaiseAlarmValidator.validate) + + def test_validate_raise_alarm_action_without_action_target(self): + + self._validate_action_without_action_target( + self._create_raise_alarm_action('123'), + RaiseAlarmValidator.validate + ) + + def test_raise_alarm_action_validate_invalid_target_id(self): + + self._validate_action_with_invalid_target_id( + self._create_raise_alarm_action('unknown'), + RaiseAlarmValidator.validate + ) + + def test_validate_raise_alarm_action_without_target_id(self): + + self._validate_action_without_target_id( + self._create_raise_alarm_action('123'), + RaiseAlarmValidator.validate, + 127 + ) + + def test_validate_raise_alarm_action_without_severity(self): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action = self._create_raise_alarm_action('abc') + action[TemplateFields.PROPERTIES].pop(TemplateFields.SEVERITY) + + # Test action + result = RaiseAlarmValidator.validate(action, idx) + + # Test assertions + self._assert_fault_result(result, 126) + + def test_validate_raise_alarm_action_without_alarm_name(self): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action = self._create_raise_alarm_action('abc') + action[TemplateFields.PROPERTIES].pop(TemplateFields.ALARM_NAME) + + # Test action + result = RaiseAlarmValidator.validate(action, idx) + + # Test assertions + self._assert_fault_result(result, 125) + + @staticmethod + def _create_raise_alarm_action(target): + + action_target = { + TemplateFields.TARGET: target + } + properties = { + TemplateFields.ALARM_NAME: 'VM_CPU_SUBOPTIMAL_PERFORMANCE', + TemplateFields.SEVERITY: 'critical' + } + action = { + TemplateFields.ACTION_TYPE: ActionType.RAISE_ALARM, + TemplateFields.ACTION_TARGET: action_target, + TemplateFields.PROPERTIES: properties + } + return action diff --git a/vitrage/tests/unit/evaluator/template_validation/content/test_set_state_validator.py b/vitrage/tests/unit/evaluator/template_validation/content/test_set_state_validator.py new file mode 100644 index 000000000..e9818e055 --- /dev/null +++ b/vitrage/tests/unit/evaluator/template_validation/content/test_set_state_validator.py @@ -0,0 +1,83 @@ +# Copyright 2017 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from vitrage.entity_graph.mappings.operational_resource_state import \ + OperationalResourceState +from vitrage.evaluator.actions.base import ActionType +from vitrage.evaluator.template_fields import TemplateFields +from vitrage.evaluator.template_validation.content.set_state_validator \ + import SetStateValidator +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + ActionValidatorTest +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + DEFINITIONS_INDEX_MOCK + + +class SetStateValidatorTest(ActionValidatorTest): + + def test_validate_set_state_action(self): + + self._validate_action(self._create_set_state_action('123'), + SetStateValidator.validate) + + def test_validate_set_state_action_without_action_target(self): + + self._validate_action_without_action_target( + self._create_set_state_action('123'), + SetStateValidator.validate + ) + + def test_validate_set_state_action_with_invalid_target_id(self): + + self._validate_action_with_invalid_target_id( + self._create_set_state_action('unknown'), + SetStateValidator.validate + ) + + def test_validate_set_state_action_without_target_id(self): + + self._validate_action_without_target_id( + self._create_set_state_action('123'), + SetStateValidator.validate, + 129 + ) + + def test_validate_set_state_action_without_state_property(self): + + # Test setup + idx = DEFINITIONS_INDEX_MOCK.copy() + action = self._create_set_state_action('123') + action[TemplateFields.PROPERTIES].pop(TemplateFields.STATE, None) + + # Test action + result = SetStateValidator.validate(action, idx) + + # Test assertions + self._assert_fault_result(result, 128) + + @staticmethod + def _create_set_state_action(target): + + action_target = { + TemplateFields.TARGET: target + } + properties = { + TemplateFields.STATE: OperationalResourceState.SUBOPTIMAL + } + action = { + TemplateFields.ACTION_TYPE: ActionType.SET_STATE, + TemplateFields.ACTION_TARGET: action_target, + TemplateFields.PROPERTIES: properties + } + return action diff --git a/vitrage/tests/unit/evaluator/test_template_syntax_validator.py b/vitrage/tests/unit/evaluator/template_validation/test_template_syntax_validator.py similarity index 98% rename from vitrage/tests/unit/evaluator/test_template_syntax_validator.py rename to vitrage/tests/unit/evaluator/template_validation/test_template_syntax_validator.py index c9199728f..ee0f8b822 100644 --- a/vitrage/tests/unit/evaluator/test_template_syntax_validator.py +++ b/vitrage/tests/unit/evaluator/template_validation/test_template_syntax_validator.py @@ -195,10 +195,6 @@ class TemplateSyntaxValidatorTest(base.BaseTest): TemplateFields.ACTION_TYPE, status_msgs[123]) - self._test_validate_action_without_required_field( - TemplateFields.ACTION_TARGET, - status_msgs[124]) - def _test_validate_action_without_required_field(self, field_name, expected_comment): diff --git a/vitrage/tests/unit/evaluator/test_template_content_validator.py b/vitrage/tests/unit/evaluator/test_template_content_validator.py index f56d5eb23..e839534d7 100644 --- a/vitrage/tests/unit/evaluator/test_template_content_validator.py +++ b/vitrage/tests/unit/evaluator/test_template_content_validator.py @@ -13,34 +13,17 @@ # under the License. import copy -import logging -from vitrage.entity_graph.mappings.operational_resource_state import \ - OperationalResourceState -from vitrage.common.constants import EntityCategory -from vitrage.evaluator.actions.base import ActionType from vitrage.evaluator.template_fields import TemplateFields -from vitrage.evaluator.template_validation.status_messages import status_msgs -from vitrage.evaluator.template_validation import template_content_validator \ - as validator -from vitrage.tests import base +from vitrage.evaluator.template_validation import \ + template_content_validator as validator from vitrage.tests.mocks import utils +from vitrage.tests.unit.evaluator.template_validation.content.base import \ + ValidatorTest from vitrage.utils import file as file_utils -DEFINITIONS_INDEX_MOCK = { - '123': {}, - '456': {}, - '789': {}, - 'a1': { - TemplateFields.CATEGORY: EntityCategory.ALARM - }, - 'a2': { - TemplateFields.CATEGORY: EntityCategory.ALARM - } -} - -class TemplateContentValidatorTest(base.BaseTest): +class TemplateContentValidatorTest(ValidatorTest): # noinspection PyPep8Naming @classmethod @@ -58,7 +41,7 @@ class TemplateContentValidatorTest(base.BaseTest): def test_template_validator(self): for template in self.templates: - self._test_execute_and_assert_with_correct_result(template) + self._execute_and_assert_with_correct_result(template) def test_not_operator(self): basic_correct_not_condition_path = \ @@ -66,7 +49,7 @@ class TemplateContentValidatorTest(base.BaseTest): utils.get_resources_dir() basic_correct_not_condition_template = \ file_utils.load_yaml_file(basic_correct_not_condition_path) - self._test_execute_and_assert_with_correct_result( + self._execute_and_assert_with_correct_result( basic_correct_not_condition_template) basic_incorrect_not_condition_path = \ @@ -74,7 +57,7 @@ class TemplateContentValidatorTest(base.BaseTest): utils.get_resources_dir() basic_incorrect_not_condition_template = \ file_utils.load_yaml_file(basic_incorrect_not_condition_path) - self._test_execute_and_assert_with_fault_result( + self._execute_and_assert_with_fault_result( basic_incorrect_not_condition_template, 86) @@ -84,7 +67,7 @@ class TemplateContentValidatorTest(base.BaseTest): utils.get_resources_dir() complicated_correct_not_condition_template = \ file_utils.load_yaml_file(complicated_correct_not_condition_path) - self._test_execute_and_assert_with_correct_result( + self._execute_and_assert_with_correct_result( complicated_correct_not_condition_template) complicated_incorrect_not_condition_path = \ @@ -93,7 +76,7 @@ class TemplateContentValidatorTest(base.BaseTest): utils.get_resources_dir() complicated_incorrect_not_condition_template = \ file_utils.load_yaml_file(complicated_incorrect_not_condition_path) - self._test_execute_and_assert_with_fault_result( + self._execute_and_assert_with_fault_result( complicated_incorrect_not_condition_template, 86) @@ -106,7 +89,7 @@ class TemplateContentValidatorTest(base.BaseTest): entity_dict = entity[TemplateFields.ENTITY] entity_dict[TemplateFields.TEMPLATE_ID] = 'aaa' - self._test_execute_and_assert_with_fault_result(template, 2) + self._execute_and_assert_with_fault_result(template, 2) def test_validate_relationship_with_no_unique_template_id(self): @@ -118,7 +101,7 @@ class TemplateContentValidatorTest(base.BaseTest): relationship_dict = relationship[TemplateFields.RELATIONSHIP] relationship_dict[TemplateFields.TEMPLATE_ID] = entity_id - self._test_execute_and_assert_with_fault_result(template, 2) + self._execute_and_assert_with_fault_result(template, 2) def test_validate_relationship_with_invalid_target(self): @@ -128,7 +111,7 @@ class TemplateContentValidatorTest(base.BaseTest): relationship_dict = relationship[TemplateFields.RELATIONSHIP] relationship_dict[TemplateFields.TARGET] = 'unknown' - self._test_execute_and_assert_with_fault_result(template, 3) + self._execute_and_assert_with_fault_result(template, 3) def test_validate_relationship_with_invalid_source(self): @@ -138,7 +121,7 @@ class TemplateContentValidatorTest(base.BaseTest): relationship_dict = relationship[TemplateFields.RELATIONSHIP] relationship_dict[TemplateFields.SOURCE] = 'unknown' - self._test_execute_and_assert_with_fault_result(template, 3) + self._execute_and_assert_with_fault_result(template, 3) def test_validate_scenario_invalid_condition(self): @@ -147,289 +130,33 @@ class TemplateContentValidatorTest(base.BaseTest): scenario_dict = scenario[TemplateFields.SCENARIO] scenario_dict[TemplateFields.CONDITION] = 'and resource' - self._test_execute_and_assert_with_fault_result(template, 85) + self._execute_and_assert_with_fault_result(template, 85) scenario_dict[TemplateFields.CONDITION] = 'resource or' - self._test_execute_and_assert_with_fault_result(template, 85) + self._execute_and_assert_with_fault_result(template, 85) scenario_dict[TemplateFields.CONDITION] = 'not or resource' - self._test_execute_and_assert_with_fault_result(template, 85) + self._execute_and_assert_with_fault_result(template, 85) scenario_dict[TemplateFields.CONDITION] = \ 'alarm_on_host (alarm or resource' - self._test_execute_and_assert_with_fault_result(template, 85) + self._execute_and_assert_with_fault_result(template, 85) scenario_dict[TemplateFields.CONDITION] = 'aaa' - self._test_execute_and_assert_with_fault_result(template, 3) + self._execute_and_assert_with_fault_result(template, 3) scenario_dict[TemplateFields.CONDITION] = 'resource and aaa' - self._test_execute_and_assert_with_fault_result(template, 3) + self._execute_and_assert_with_fault_result(template, 3) - def test_validate_raise_alarm_action(self): - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_raise_alarm_action('123') - - # Test action and assertions - result = validator._validate_raise_alarm_action(action, idx) - - # Test Assertions - self._test_assert_with_correct_result(result) - - def test_raise_alarm_action_validate_invalid_target_id(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_raise_alarm_action('unknown') - - # Test action - result = validator._validate_raise_alarm_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 3) - - def test_validate_raise_alarm_action_without_target_id(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_raise_alarm_action('123') - action[TemplateFields.ACTION_TARGET].pop(TemplateFields.TARGET) - - # Test action - result = validator._validate_raise_alarm_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 127) - - def test_validate_raise_alarm_action_without_severity(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_raise_alarm_action('abc') - action[TemplateFields.PROPERTIES].pop(TemplateFields.SEVERITY) - - # Test action - result = validator._validate_raise_alarm_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 126) - - def test_validate_raise_alarm_action_without_alarm_name(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_raise_alarm_action('abc') - action[TemplateFields.PROPERTIES].pop(TemplateFields.ALARM_NAME) - - # Test action - result = validator._validate_raise_alarm_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 125) - - def test_validate_set_state_action(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_set_state_action('123') - - # Test action and assertions - result = validator._validate_set_state_action(action, idx) - - # Test Assertions - self._test_assert_with_correct_result(result) - - def test_validate_set_state_action_with_invalid_target_id(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_set_state_action('unknown') - - # Test action - result = validator._validate_set_state_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 3) - - def test_validate_set_state_action_without_target_id(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_set_state_action('123') - action[TemplateFields.ACTION_TARGET].pop(TemplateFields.TARGET) - - # Test action - result = validator._validate_set_state_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 129) - - def test_validate_set_state_action_without_state_property(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_set_state_action('123') - action[TemplateFields.PROPERTIES].pop(TemplateFields.STATE, None) - - # Test action - result = validator._validate_set_state_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 128) - - def test_validate_mark_down_action(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_mark_down_action('123') - - # Test action and assertions - result = validator._validate_mark_down_action(action, idx) - - # Test Assertions - self._test_assert_with_correct_result(result) - - def test_validate_mark_down_action_with_invalid_target_id(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_mark_down_action('unknown') - - # Test action - result = validator._validate_mark_down_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 3) - - def test_validate_mark_down_action_without_target_id(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_mark_down_action('123') - action[TemplateFields.ACTION_TARGET].pop(TemplateFields.TARGET) - - # Test action - result = validator._validate_mark_down_action(action, idx) - - # Test assertions - self._test_assert_with_fault_result(result, 131) - - def test_validate_add_causal_relationship_action(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_add_causal_relationship_action('a1', 'a2') - - # Test action and assertions - result = \ - validator._validate_add_causal_relationship_action(action, idx) - - # Test action and assertions - self._test_assert_with_correct_result(result) - - def test_validate_add_causal_relationship_action_with_invalid_target(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_add_causal_relationship_action('unknown', 'a1') - - # Test action - result = \ - validator._validate_add_causal_relationship_action(action, idx) - - # Test assertion - self._test_assert_with_fault_result(result, 3) - - def test_validate_add_causal_relationship_action_without_target(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_add_causal_relationship_action('a1', 'a2') - action[TemplateFields.ACTION_TARGET].pop(TemplateFields.TARGET, None) - - # Test action - result = \ - validator._validate_add_causal_relationship_action(action, idx) - - # Test assertion - self._test_assert_with_fault_result(result, 130) - - def test_validate_add_causal_relationship_action_with_invalid_source(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_add_causal_relationship_action('a1', 'unknown') - - # Test action - result = \ - validator._validate_add_causal_relationship_action(action, idx) - - # Test assertion - self._test_assert_with_fault_result(result, 3) - - def test_validate_add_causal_relationship_action_without_source(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_add_causal_relationship_action('a1', 'a2') - action[TemplateFields.ACTION_TARGET].pop(TemplateFields.SOURCE, None) - - # Test action - result = \ - validator._validate_add_causal_relationship_action(action, idx) - - # Test assertion - self._test_assert_with_fault_result(result, 130) - - def test_validate_add_causal_relationship_action_wrong_src_category(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_add_causal_relationship_action('a1', '123') - - # Test action - result = \ - validator._validate_add_causal_relationship_action(action, idx) - - # Test assertion - self._test_assert_with_fault_result(result, 132) - - def test_validate_add_causal_relationship_action_wrong_tgt_category(self): - - # Test setup - idx = DEFINITIONS_INDEX_MOCK.copy() - action = self._create_add_causal_relationship_action('123', 'a1') - - # Test action - result = \ - validator._validate_add_causal_relationship_action(action, idx) - - # Test assertion - self._test_assert_with_fault_result(result, 132) - - def _test_execute_and_assert_with_fault_result(self, - template, - status_code): + def _execute_and_assert_with_fault_result(self, template, status_code): result = validator.content_validation(template) - self._test_assert_with_fault_result(result, status_code) + self._assert_fault_result(result, status_code) - def _test_assert_with_fault_result(self, result, status_code): - - self.assertFalse(result.is_valid_config) - self.assertTrue(result.comment.startswith(status_msgs[status_code])) - self.assertEqual(result.status_code, status_code) - - def _test_execute_and_assert_with_correct_result(self, template): + def _execute_and_assert_with_correct_result(self, template): result = validator.content_validation(template) - self._test_assert_with_correct_result(result) - - def _test_assert_with_correct_result(self, result): - - self.assertTrue(result.is_valid_config) - self.assertEqual(result.comment, status_msgs[0]) - self.assertEqual(result.status_code, 0) + self._assert_correct_result(result) def _create_scenario_actions(self, target, source): @@ -448,70 +175,3 @@ class TemplateContentValidatorTest(base.BaseTest): actions.append({TemplateFields.ACTION: causal_action}) return actions - - # Static methods: - @staticmethod - def _create_add_causal_relationship_action(target, source): - - action_target = { - TemplateFields.TARGET: target, - TemplateFields.SOURCE: source - } - action = { - TemplateFields.ACTION_TYPE: ActionType.ADD_CAUSAL_RELATIONSHIP, - TemplateFields.ACTION_TARGET: action_target} - - return action - - @staticmethod - def _create_mark_down_action(target): - - action_target = { - TemplateFields.TARGET: target - } - action = { - TemplateFields.ACTION_TYPE: ActionType.MARK_DOWN, - TemplateFields.ACTION_TARGET: action_target, - } - return action - - @staticmethod - def _create_set_state_action(target): - - action_target = { - TemplateFields.TARGET: target - } - properties = { - TemplateFields.STATE: OperationalResourceState.SUBOPTIMAL - } - action = { - TemplateFields.ACTION_TYPE: ActionType.SET_STATE, - TemplateFields.ACTION_TARGET: action_target, - TemplateFields.PROPERTIES: properties - } - return action - - @staticmethod - def _create_raise_alarm_action(target): - - action_target = { - TemplateFields.TARGET: target - } - properties = { - TemplateFields.ALARM_NAME: 'VM_CPU_SUBOPTIMAL_PERFORMANCE', - TemplateFields.SEVERITY: 'critical' - } - action = { - TemplateFields.ACTION_TYPE: ActionType.RAISE_ALARM, - TemplateFields.ACTION_TARGET: action_target, - TemplateFields.PROPERTIES: properties - } - return action - - @staticmethod - def _hide_useless_logging_messages(): - - validator_path = 'vitrage.evaluator.template_validation.' \ - 'template_content_validator' - content_validator_log = logging.getLogger(validator_path) - content_validator_log.setLevel(logging.FATAL)