Merge "Refactor template_content_validator"
This commit is contained in:
commit
1e526b7c48
@ -24,10 +24,10 @@ from vitrage.evaluator.base import Template
|
||||
from vitrage.evaluator.equivalence_repository import EquivalenceRepository
|
||||
from vitrage.evaluator.template_data import TemplateData
|
||||
from vitrage.evaluator.template_fields import TemplateFields
|
||||
from vitrage.evaluator.template_validation.content.definitions_validator \
|
||||
import DefinitionsValidator as DefValidator
|
||||
from vitrage.evaluator.template_validation.content.template_content_validator \
|
||||
import content_validation
|
||||
from vitrage.evaluator.template_validation.content.template_content_validator \
|
||||
import def_template_content_validation
|
||||
from vitrage.evaluator.template_validation.template_syntax_validator import \
|
||||
def_template_syntax_validation
|
||||
from vitrage.evaluator.template_validation.template_syntax_validator import \
|
||||
@ -139,7 +139,7 @@ class ScenarioRepository(object):
|
||||
LOG.info('Unable to load definition template, syntax err: %s'
|
||||
% result.comment)
|
||||
else:
|
||||
result = def_template_content_validation(def_template)
|
||||
result = DefValidator.def_template_content_validation(def_template)
|
||||
if not result.is_valid_config:
|
||||
LOG.info('Unable to load definition template, content err: %s'
|
||||
% result.comment)
|
||||
|
@ -0,0 +1,214 @@
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
import re
|
||||
|
||||
from vitrage.evaluator.template_fields import TemplateFields
|
||||
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
|
||||
from vitrage.utils import evaluator as evaluator_utils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class DefinitionsValidator(object):
|
||||
|
||||
@classmethod
|
||||
def def_template_content_validation(cls, def_template):
|
||||
def_template_definitions = def_template[TemplateFields.DEFINITIONS]
|
||||
|
||||
entities_index = {}
|
||||
entities = def_template_definitions[TemplateFields.ENTITIES]
|
||||
result = cls.validate_entities_definition(entities, entities_index)
|
||||
|
||||
relationships_index = {}
|
||||
|
||||
if result.is_valid_config \
|
||||
and TemplateFields.RELATIONSHIPS in def_template_definitions:
|
||||
relationships = \
|
||||
def_template_definitions[TemplateFields.RELATIONSHIPS]
|
||||
result = \
|
||||
cls.validate_relationships_definitions(relationships,
|
||||
relationships_index,
|
||||
entities_index)
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def validate_entities_definition(cls, entities, entities_index):
|
||||
for entity in entities:
|
||||
entity_dict = entity[TemplateFields.ENTITY]
|
||||
result = \
|
||||
cls._validate_entity_definition(entity_dict, entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
entities_index[entity_dict[TemplateFields.TEMPLATE_ID]] = \
|
||||
entity_dict
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
@classmethod
|
||||
def validate_definitions_with_includes(
|
||||
cls, template_includes, def_templates, entities_index):
|
||||
|
||||
for include in template_includes:
|
||||
|
||||
name = include[TemplateFields.NAME]
|
||||
def_template = \
|
||||
evaluator_utils.find_def_template(name, def_templates)
|
||||
|
||||
if not def_template:
|
||||
|
||||
LOG.error('%s status code: %s' % (status_msgs[142], 142))
|
||||
return get_content_fault_result(142)
|
||||
|
||||
def_template_definitions = def_template[TemplateFields.DEFINITIONS]
|
||||
def_template_entities = \
|
||||
def_template_definitions[TemplateFields.ENTITIES]
|
||||
result = cls._validate_include_entities_definition(
|
||||
def_template_entities, entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
@classmethod
|
||||
def validate_relationships_definitions(cls,
|
||||
relationships,
|
||||
relationships_index,
|
||||
entities_index):
|
||||
for relationship in relationships:
|
||||
|
||||
relationship_dict = relationship[TemplateFields.RELATIONSHIP]
|
||||
result = cls._validate_relationship(relationship_dict,
|
||||
relationships_index,
|
||||
entities_index)
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
template_id = relationship_dict[TemplateFields.TEMPLATE_ID]
|
||||
relationships_index[template_id] = relationship_dict
|
||||
return get_content_correct_result()
|
||||
|
||||
@classmethod
|
||||
def validate_relationships_definitions_with_includes(cls,
|
||||
template_includes,
|
||||
def_templates,
|
||||
entities_index,
|
||||
relationships_index):
|
||||
|
||||
for include in template_includes:
|
||||
|
||||
name = include[TemplateFields.NAME]
|
||||
def_template = \
|
||||
evaluator_utils.find_def_template(name, def_templates)
|
||||
|
||||
if def_template:
|
||||
defs = def_template[TemplateFields.DEFINITIONS]
|
||||
relationships = defs[TemplateFields.RELATIONSHIPS]
|
||||
|
||||
for relationship in relationships:
|
||||
relationship_dict = \
|
||||
relationship[TemplateFields.RELATIONSHIP]
|
||||
template_id = relationship_dict[TemplateFields.TEMPLATE_ID]
|
||||
if template_id not in relationships_index:
|
||||
result = cls._validate_def_template_relationship(
|
||||
relationship_dict,
|
||||
entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
relationships_index[template_id] = relationship_dict
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
@classmethod
|
||||
def _validate_entity_definition(cls, 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_content_fault_result(2)
|
||||
|
||||
for key, value in entity_dict.items():
|
||||
|
||||
if key.lower().endswith(TemplateFields.REGEX):
|
||||
try:
|
||||
re.compile(value)
|
||||
except Exception:
|
||||
LOG.error('%s %s status code: %s' % (status_msgs[47],
|
||||
str(key), 47))
|
||||
return get_content_fault_result(47)
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
@classmethod
|
||||
def _validate_include_entities_definition(
|
||||
cls,
|
||||
def_template_entities,
|
||||
entities_index):
|
||||
|
||||
for entity in def_template_entities:
|
||||
entity_dict = entity[TemplateFields.ENTITY]
|
||||
result = \
|
||||
cls._validate_entity_definition(entity_dict, entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
if entity_dict[TemplateFields.TEMPLATE_ID] not in entities_index:
|
||||
template_id = entity_dict[TemplateFields.TEMPLATE_ID]
|
||||
entities_index[template_id] = entity_dict
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
@classmethod
|
||||
def _validate_def_template_relationship(cls, relationship, entities_index):
|
||||
target = relationship[TemplateFields.TARGET]
|
||||
result = validate_template_id(entities_index, target)
|
||||
|
||||
if result.is_valid_config:
|
||||
source = relationship[TemplateFields.SOURCE]
|
||||
result = validate_template_id(entities_index, source)
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def _validate_relationship(cls,
|
||||
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_content_fault_result(2)
|
||||
|
||||
target = relationship[TemplateFields.TARGET]
|
||||
result = validate_template_id(entities_index, target)
|
||||
|
||||
if result.is_valid_config:
|
||||
source = relationship[TemplateFields.SOURCE]
|
||||
result = validate_template_id(entities_index, source)
|
||||
|
||||
return result
|
@ -0,0 +1,203 @@
|
||||
# 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.
|
||||
|
||||
from sympy.logic.boolalg import Not
|
||||
from sympy import Symbol
|
||||
|
||||
from oslo_log import log
|
||||
from six.moves import reduce
|
||||
|
||||
from vitrage.common.constants import EdgeProperties as EProps
|
||||
from vitrage.evaluator.actions.base import ActionType
|
||||
from vitrage.evaluator.condition import convert_to_dnf_format
|
||||
from vitrage.evaluator.condition import get_condition_common_targets
|
||||
from vitrage.evaluator.condition import is_condition_include_positive_clause
|
||||
from vitrage.evaluator.condition import parse_condition
|
||||
from vitrage.evaluator.condition import SymbolResolver
|
||||
from vitrage.evaluator.template_fields import TemplateFields
|
||||
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.execute_mistral_validator \
|
||||
import ExecuteMistralValidator
|
||||
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__)
|
||||
|
||||
|
||||
class ScenarioValidator(object):
|
||||
|
||||
class TemplateSymbolResolver(SymbolResolver):
|
||||
def is_relationship(self, symbol):
|
||||
return TemplateFields.RELATIONSHIP_TYPE in symbol
|
||||
|
||||
def get_relationship_source_id(self, relationship):
|
||||
return relationship[TemplateFields.SOURCE]
|
||||
|
||||
def get_relationship_target_id(self, relationship):
|
||||
return relationship[TemplateFields.TARGET]
|
||||
|
||||
def get_entity_id(self, entity):
|
||||
return entity[TemplateFields.TEMPLATE_ID]
|
||||
|
||||
def __init__(self, definitions_index):
|
||||
self.definitions_index = definitions_index
|
||||
|
||||
def validate(self, scenarios):
|
||||
for scenario in scenarios:
|
||||
scenario_values = scenario[TemplateFields.SCENARIO]
|
||||
|
||||
condition = scenario_values[TemplateFields.CONDITION]
|
||||
result = self._validate_scenario_condition(condition)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
actions = scenario_values[TemplateFields.ACTIONS]
|
||||
result = self._validate_scenario_actions(actions)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
def _validate_scenario_condition(self, condition):
|
||||
try:
|
||||
dnf_result = convert_to_dnf_format(condition)
|
||||
except Exception:
|
||||
LOG.error('%s status code: %s' % (status_msgs[85], 85))
|
||||
return get_content_fault_result(85)
|
||||
|
||||
# not condition validation
|
||||
not_condition_result = self._validate_not_condition(dnf_result)
|
||||
if not not_condition_result.is_valid_config:
|
||||
return not_condition_result
|
||||
|
||||
# template id validation
|
||||
values_to_replace = ' and ', ' or ', ' not ', 'not ', '(', ')'
|
||||
condition_vars = reduce(lambda cond, v: cond.replace(v, ' '),
|
||||
values_to_replace,
|
||||
condition)
|
||||
|
||||
for condition_var in condition_vars.split(' '):
|
||||
|
||||
if len(condition_var.strip()) == 0:
|
||||
continue
|
||||
|
||||
result = \
|
||||
validate_template_id(self.definitions_index, condition_var)
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
# condition structure validation
|
||||
condition_structure_result = \
|
||||
self._validate_condition_structure(parse_condition(condition))
|
||||
if not condition_structure_result.is_valid_config:
|
||||
return condition_structure_result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
def _validate_condition_structure(self, condition_dnf):
|
||||
result = \
|
||||
self._validate_condition_includes_positive_clause(condition_dnf)
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
common_targets = \
|
||||
get_condition_common_targets(condition_dnf,
|
||||
self.definitions_index,
|
||||
self.TemplateSymbolResolver())
|
||||
|
||||
return get_content_correct_result() if common_targets \
|
||||
else get_content_fault_result(135)
|
||||
|
||||
@staticmethod
|
||||
def _validate_condition_includes_positive_clause(condition):
|
||||
return get_content_correct_result() if \
|
||||
is_condition_include_positive_clause(condition) \
|
||||
else get_content_fault_result(134)
|
||||
|
||||
def _validate_not_condition(self, dnf_result):
|
||||
"""Not operator validation
|
||||
|
||||
Not operator can appear only on edges.
|
||||
|
||||
:param dnf_result:
|
||||
:param definitions_index:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if isinstance(dnf_result, Not):
|
||||
for arg in dnf_result.args:
|
||||
if isinstance(arg, Symbol):
|
||||
definition = self.definitions_index.get(str(arg), None)
|
||||
if not (definition and
|
||||
definition.get(EProps.RELATIONSHIP_TYPE)):
|
||||
msg = status_msgs[86] + ' template id: %s' % arg
|
||||
LOG.error('%s status code: %s' % (msg, 86))
|
||||
return get_content_fault_result(86, msg)
|
||||
else:
|
||||
res = self._validate_not_condition(arg)
|
||||
if not res.is_valid_config:
|
||||
return res
|
||||
return get_content_correct_result()
|
||||
|
||||
for arg in dnf_result.args:
|
||||
if not isinstance(arg, Symbol):
|
||||
res = self._validate_not_condition(arg)
|
||||
if not res.is_valid_config:
|
||||
return res
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
def _validate_scenario_actions(self, actions):
|
||||
|
||||
for action in actions:
|
||||
result = \
|
||||
self._validate_scenario_action(action[TemplateFields.ACTION])
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
def _validate_scenario_action(self, action):
|
||||
|
||||
action_type = action[TemplateFields.ACTION_TYPE]
|
||||
|
||||
action_validators = {
|
||||
ActionType.RAISE_ALARM: RaiseAlarmValidator(),
|
||||
ActionType.SET_STATE: SetStateValidator(),
|
||||
ActionType.ADD_CAUSAL_RELATIONSHIP:
|
||||
AddCausalRelationshipValidator(),
|
||||
ActionType.MARK_DOWN: MarkDownValidator(),
|
||||
ActionType.EXECUTE_MISTRAL: ExecuteMistralValidator(),
|
||||
}
|
||||
|
||||
if action_type not in action_validators:
|
||||
LOG.error('%s status code: %s' % (status_msgs[120], 120))
|
||||
return get_content_fault_result(120)
|
||||
|
||||
return action_validators[action_type].validate(action,
|
||||
self.definitions_index)
|
@ -12,39 +12,15 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sympy.logic.boolalg import Not
|
||||
from sympy import Symbol
|
||||
|
||||
from oslo_log import log
|
||||
import re
|
||||
from six.moves import reduce
|
||||
|
||||
from vitrage.common.constants import EdgeProperties as EProps
|
||||
from vitrage.evaluator.actions.base import ActionType
|
||||
from vitrage.evaluator.condition import convert_to_dnf_format
|
||||
from vitrage.evaluator.condition import get_condition_common_targets
|
||||
from vitrage.evaluator.condition import is_condition_include_positive_clause
|
||||
from vitrage.evaluator.condition import parse_condition
|
||||
from vitrage.evaluator.condition import SymbolResolver
|
||||
from vitrage.evaluator.template_fields import TemplateFields
|
||||
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.execute_mistral_validator \
|
||||
import ExecuteMistralValidator
|
||||
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
|
||||
from vitrage.utils import evaluator as evaluator_utils
|
||||
from vitrage.evaluator.template_validation.content.definitions_validator \
|
||||
import DefinitionsValidator as DefValidator
|
||||
from vitrage.evaluator.template_validation.content.scenario_validator import \
|
||||
ScenarioValidator
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
@ -63,370 +39,40 @@ def content_validation(template, def_templates=None):
|
||||
|
||||
if TemplateFields.ENTITIES in template_definitions:
|
||||
entities = template_definitions[TemplateFields.ENTITIES]
|
||||
result = _validate_entities_definition(entities, entities_index)
|
||||
result = DefValidator.validate_entities_definition(entities,
|
||||
entities_index)
|
||||
|
||||
# If there are duplicate definitions in several includes under the same
|
||||
# name, will regard the first one
|
||||
if result.is_valid_config and TemplateFields.INCLUDES in template:
|
||||
|
||||
template_includes = template[TemplateFields.INCLUDES]
|
||||
result = _validate_definitions_with_includes(template_includes,
|
||||
result = \
|
||||
DefValidator.validate_definitions_with_includes(template_includes,
|
||||
def_templates,
|
||||
entities_index)
|
||||
|
||||
relationships_index = {}
|
||||
relationship_index = {}
|
||||
|
||||
if result.is_valid_config and \
|
||||
TemplateFields.RELATIONSHIPS in template_definitions:
|
||||
|
||||
relationships = template_definitions[TemplateFields.RELATIONSHIPS]
|
||||
result = _validate_relationships_definitions(relationships,
|
||||
relationships_index,
|
||||
result = \
|
||||
DefValidator.validate_relationships_definitions(relationships,
|
||||
relationship_index,
|
||||
entities_index)
|
||||
|
||||
if result.is_valid_config and TemplateFields.INCLUDES in template:
|
||||
template_includes = template[TemplateFields.INCLUDES]
|
||||
result = _validate_relationships_definitions_with_includes(
|
||||
result = DefValidator.validate_relationships_definitions_with_includes(
|
||||
template_includes,
|
||||
def_templates,
|
||||
entities_index,
|
||||
relationships_index)
|
||||
relationship_index)
|
||||
|
||||
if result.is_valid_config:
|
||||
scenarios = template[TemplateFields.SCENARIOS]
|
||||
definitions_index = entities_index.copy()
|
||||
definitions_index.update(relationships_index)
|
||||
result = _validate_scenarios(scenarios, definitions_index)
|
||||
definitions_index.update(relationship_index)
|
||||
result = ScenarioValidator(definitions_index).validate(scenarios)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def def_template_content_validation(def_template):
|
||||
def_template_definitions = def_template[TemplateFields.DEFINITIONS]
|
||||
|
||||
entities_index = {}
|
||||
entities = def_template_definitions[TemplateFields.ENTITIES]
|
||||
result = _validate_entities_definition(entities, entities_index)
|
||||
|
||||
relationships_index = {}
|
||||
|
||||
if result.is_valid_config \
|
||||
and TemplateFields.RELATIONSHIPS in def_template_definitions:
|
||||
relationships = def_template_definitions[TemplateFields.RELATIONSHIPS]
|
||||
result = _validate_relationships_definitions(relationships,
|
||||
relationships_index,
|
||||
entities_index)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _validate_entities_definition(entities, entities_index):
|
||||
|
||||
for entity in entities:
|
||||
|
||||
entity_dict = entity[TemplateFields.ENTITY]
|
||||
result = _validate_entity_definition(entity_dict, entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
entities_index[entity_dict[TemplateFields.TEMPLATE_ID]] = entity_dict
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
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_content_fault_result(2)
|
||||
|
||||
for key, value in entity_dict.items():
|
||||
|
||||
if key.lower().endswith(TemplateFields.REGEX):
|
||||
try:
|
||||
re.compile(value)
|
||||
except Exception:
|
||||
LOG.error('%s %s status code: %s' % (status_msgs[47],
|
||||
str(key), 47))
|
||||
return get_content_fault_result(47)
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_definitions_with_includes(
|
||||
template_includes, def_templates, entities_index):
|
||||
|
||||
for include in template_includes:
|
||||
|
||||
name = include[TemplateFields.NAME]
|
||||
def_template = evaluator_utils.find_def_template(name, def_templates)
|
||||
|
||||
if not def_template:
|
||||
|
||||
LOG.error('%s status code: %s' % (status_msgs[142], 142))
|
||||
return get_content_fault_result(142)
|
||||
|
||||
def_template_definitions = def_template[TemplateFields.DEFINITIONS]
|
||||
def_template_entities = \
|
||||
def_template_definitions[TemplateFields.ENTITIES]
|
||||
result = _validate_include_entities_definition(
|
||||
def_template_entities, entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_include_entities_definition(
|
||||
def_template_entities,
|
||||
entities_index):
|
||||
|
||||
for entity in def_template_entities:
|
||||
entity_dict = entity[TemplateFields.ENTITY]
|
||||
result = _validate_entity_definition(entity_dict, entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
if entity_dict[TemplateFields.TEMPLATE_ID] not in entities_index:
|
||||
id = entity_dict[TemplateFields.TEMPLATE_ID]
|
||||
entities_index[id] = entity_dict
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_relationships_definitions(relationships,
|
||||
relationships_index,
|
||||
entities_index):
|
||||
|
||||
for relationship in relationships:
|
||||
|
||||
relationship_dict = relationship[TemplateFields.RELATIONSHIP]
|
||||
result = _validate_relationship(relationship_dict,
|
||||
relationships_index,
|
||||
entities_index)
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
template_id = relationship_dict[TemplateFields.TEMPLATE_ID]
|
||||
relationships_index[template_id] = relationship_dict
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_relationships_definitions_with_includes(template_includes,
|
||||
def_templates,
|
||||
entities_index,
|
||||
relationships_index):
|
||||
|
||||
for include in template_includes:
|
||||
|
||||
name = include[TemplateFields.NAME]
|
||||
def_template = evaluator_utils.find_def_template(name, def_templates)
|
||||
|
||||
if def_template:
|
||||
defs = def_template[TemplateFields.DEFINITIONS]
|
||||
relationships = defs[TemplateFields.RELATIONSHIPS]
|
||||
|
||||
for relationship in relationships:
|
||||
relationship_dict = relationship[TemplateFields.RELATIONSHIP]
|
||||
template_id = relationship_dict[TemplateFields.TEMPLATE_ID]
|
||||
if template_id not in relationships_index:
|
||||
result = _validate_def_template_relationship(
|
||||
relationship_dict,
|
||||
entities_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
relationships_index[template_id] = relationship_dict
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_def_template_relationship(relationship,
|
||||
entities_index):
|
||||
|
||||
target = relationship[TemplateFields.TARGET]
|
||||
result = validate_template_id(entities_index, target)
|
||||
|
||||
if result.is_valid_config:
|
||||
source = relationship[TemplateFields.SOURCE]
|
||||
result = validate_template_id(entities_index, source)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
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_content_fault_result(2)
|
||||
|
||||
target = relationship[TemplateFields.TARGET]
|
||||
result = validate_template_id(entities_index, target)
|
||||
|
||||
if result.is_valid_config:
|
||||
source = relationship[TemplateFields.SOURCE]
|
||||
result = validate_template_id(entities_index, source)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _validate_scenarios(scenarios, definitions_index):
|
||||
|
||||
for scenario in scenarios:
|
||||
|
||||
scenario_values = scenario[TemplateFields.SCENARIO]
|
||||
|
||||
condition = scenario_values[TemplateFields.CONDITION]
|
||||
result = _validate_scenario_condition(condition, definitions_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
actions = scenario_values[TemplateFields.ACTIONS]
|
||||
result = _validate_scenario_actions(actions, definitions_index)
|
||||
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_scenario_condition(condition, definitions_index):
|
||||
try:
|
||||
dnf_result = convert_to_dnf_format(condition)
|
||||
except Exception:
|
||||
LOG.error('%s status code: %s' % (status_msgs[85], 85))
|
||||
return get_content_fault_result(85)
|
||||
|
||||
# not condition validation
|
||||
not_condition_result = \
|
||||
_validate_not_condition(dnf_result, definitions_index)
|
||||
if not not_condition_result.is_valid_config:
|
||||
return not_condition_result
|
||||
|
||||
# template id validation
|
||||
values_to_replace = ' and ', ' or ', ' not ', 'not ', '(', ')'
|
||||
condition_vars = reduce(lambda cond, v: cond.replace(v, ' '),
|
||||
values_to_replace,
|
||||
condition)
|
||||
|
||||
for condition_var in condition_vars.split(' '):
|
||||
|
||||
if len(condition_var.strip()) == 0:
|
||||
continue
|
||||
|
||||
result = validate_template_id(definitions_index, condition_var)
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
# condition structure validation
|
||||
condition_structure_result = \
|
||||
validate_condition_structure(parse_condition(condition),
|
||||
definitions_index)
|
||||
if not condition_structure_result.is_valid_config:
|
||||
return condition_structure_result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def validate_condition_structure(condition_dnf, definitions_index):
|
||||
result = validate_condition_includes_positive_clause(condition_dnf)
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
common_targets = get_condition_common_targets(condition_dnf,
|
||||
definitions_index,
|
||||
TemplateSymbolResolver())
|
||||
|
||||
return get_content_correct_result() if common_targets \
|
||||
else get_content_fault_result(135)
|
||||
|
||||
|
||||
def validate_condition_includes_positive_clause(condition):
|
||||
return get_content_correct_result() if \
|
||||
is_condition_include_positive_clause(condition) \
|
||||
else get_content_fault_result(134)
|
||||
|
||||
|
||||
class TemplateSymbolResolver(SymbolResolver):
|
||||
def is_relationship(self, symbol):
|
||||
return TemplateFields.RELATIONSHIP_TYPE in symbol
|
||||
|
||||
def get_relationship_source_id(self, relationship):
|
||||
return relationship[TemplateFields.SOURCE]
|
||||
|
||||
def get_relationship_target_id(self, relationship):
|
||||
return relationship[TemplateFields.TARGET]
|
||||
|
||||
def get_entity_id(self, entity):
|
||||
return entity[TemplateFields.TEMPLATE_ID]
|
||||
|
||||
|
||||
def _validate_not_condition(dnf_result, definitions_index):
|
||||
"""Not operator validation
|
||||
|
||||
Not operator can appear only on edges.
|
||||
|
||||
:param dnf_result:
|
||||
:param definitions_index:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if isinstance(dnf_result, Not):
|
||||
for arg in dnf_result.args:
|
||||
if isinstance(arg, Symbol):
|
||||
definition = definitions_index.get(str(arg), None)
|
||||
if not (definition and
|
||||
definition.get(EProps.RELATIONSHIP_TYPE)):
|
||||
msg = status_msgs[86] + ' template id: %s' % arg
|
||||
LOG.error('%s status code: %s' % (msg, 86))
|
||||
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_content_correct_result()
|
||||
|
||||
for arg in dnf_result.args:
|
||||
if not isinstance(arg, Symbol):
|
||||
res = _validate_not_condition(arg, definitions_index)
|
||||
if not res.is_valid_config:
|
||||
return res
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_scenario_actions(actions, definitions_index):
|
||||
|
||||
for action in actions:
|
||||
result = _validate_scenario_action(action[TemplateFields.ACTION],
|
||||
definitions_index)
|
||||
if not result.is_valid_config:
|
||||
return result
|
||||
|
||||
return get_content_correct_result()
|
||||
|
||||
|
||||
def _validate_scenario_action(action, definitions_index):
|
||||
|
||||
action_type = action[TemplateFields.ACTION_TYPE]
|
||||
|
||||
action_validators = {
|
||||
ActionType.RAISE_ALARM: RaiseAlarmValidator(),
|
||||
ActionType.SET_STATE: SetStateValidator(),
|
||||
ActionType.ADD_CAUSAL_RELATIONSHIP: AddCausalRelationshipValidator(),
|
||||
ActionType.MARK_DOWN: MarkDownValidator(),
|
||||
ActionType.EXECUTE_MISTRAL: ExecuteMistralValidator(),
|
||||
}
|
||||
|
||||
if action_type not in action_validators:
|
||||
LOG.error('%s status code: %s' % (status_msgs[120], 120))
|
||||
return get_content_fault_result(120)
|
||||
|
||||
return action_validators[action_type].validate(action, definitions_index)
|
||||
|
@ -15,7 +15,7 @@
|
||||
from vitrage.evaluator.condition import EdgeDescription
|
||||
from vitrage.evaluator.condition import SymbolResolver
|
||||
from vitrage.evaluator.template_data import TemplateData
|
||||
from vitrage.evaluator.template_validation.content.template_content_validator \
|
||||
from vitrage.evaluator.template_validation.content.scenario_validator \
|
||||
import get_condition_common_targets
|
||||
from vitrage.tests import base
|
||||
from vitrage.tests.mocks import utils
|
||||
|
Loading…
Reference in New Issue
Block a user