Merge "Refactor the Vitrage template content validators and their tests."
This commit is contained in:
commit
73bdfc106f
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
15
vitrage/evaluator/template_validation/content/__init__.py
Normal file
15
vitrage/evaluator/template_validation/content/__init__.py
Normal file
@ -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'
|
@ -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()
|
60
vitrage/evaluator/template_validation/content/base.py
Normal file
60
vitrage/evaluator/template_validation/content/base.py
Normal file
@ -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
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
15
vitrage/tests/unit/evaluator/template_validation/__init__.py
Normal file
15
vitrage/tests/unit/evaluator/template_validation/__init__.py
Normal file
@ -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'
|
@ -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'
|
114
vitrage/tests/unit/evaluator/template_validation/content/base.py
Normal file
114
vitrage/tests/unit/evaluator/template_validation/content/base.py
Normal file
@ -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)
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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):
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user