Merge "Support the option to include definition template files in Vitrage templates."
This commit is contained in:
commit
fc30c1e378
@ -34,7 +34,8 @@ class TemplateApis(object):
|
|||||||
FAILED_MSG = 'validation failed'
|
FAILED_MSG = 'validation failed'
|
||||||
OK_MSG = 'validation OK'
|
OK_MSG = 'validation OK'
|
||||||
|
|
||||||
def __init__(self, templates):
|
def __init__(self, templates, def_templates={}):
|
||||||
|
self.def_templates = def_templates
|
||||||
self.templates = templates
|
self.templates = templates
|
||||||
|
|
||||||
def get_templates(self, ctx):
|
def get_templates(self, ctx):
|
||||||
@ -72,10 +73,10 @@ class TemplateApis(object):
|
|||||||
results = []
|
results = []
|
||||||
for template in templates:
|
for template in templates:
|
||||||
|
|
||||||
template_def = template[1]
|
template_definition = template[1]
|
||||||
path = template[0]
|
path = template[0]
|
||||||
|
|
||||||
syntax_result = syntax_validation(template_def)
|
syntax_result = syntax_validation(template_definition)
|
||||||
if not syntax_result.is_valid_config:
|
if not syntax_result.is_valid_config:
|
||||||
self._add_result(path,
|
self._add_result(path,
|
||||||
self.FAILED_MSG,
|
self.FAILED_MSG,
|
||||||
@ -85,7 +86,9 @@ class TemplateApis(object):
|
|||||||
results)
|
results)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
content_result = content_validation(template_def)
|
content_result = content_validation(
|
||||||
|
template_definition,
|
||||||
|
self.def_templates)
|
||||||
if not content_result.is_valid_config:
|
if not content_result.is_valid_config:
|
||||||
self._add_result(path,
|
self._add_result(path,
|
||||||
self.FAILED_MSG,
|
self.FAILED_MSG,
|
||||||
|
@ -52,7 +52,9 @@ class VitrageApiHandlerService(os_service.Service):
|
|||||||
endpoints = [TopologyApis(self.entity_graph, self.conf),
|
endpoints = [TopologyApis(self.entity_graph, self.conf),
|
||||||
AlarmApis(self.entity_graph, self.conf),
|
AlarmApis(self.entity_graph, self.conf),
|
||||||
RcaApis(self.entity_graph, self.conf),
|
RcaApis(self.entity_graph, self.conf),
|
||||||
TemplateApis(self.scenario_repo.templates),
|
TemplateApis(
|
||||||
|
self.scenario_repo.templates,
|
||||||
|
self.scenario_repo.def_templates),
|
||||||
EventApis(self.conf),
|
EventApis(self.conf),
|
||||||
ResourceApis(self.entity_graph, self.conf)]
|
ResourceApis(self.entity_graph, self.conf)]
|
||||||
|
|
||||||
|
@ -24,5 +24,8 @@ OPTS = [
|
|||||||
cfg.StrOpt('equivalences_dir',
|
cfg.StrOpt('equivalences_dir',
|
||||||
default='/etc/vitrage/templates/equivalences',
|
default='/etc/vitrage/templates/equivalences',
|
||||||
help='A path for entity equivalences used by the evaluator'
|
help='A path for entity equivalences used by the evaluator'
|
||||||
)
|
),
|
||||||
|
cfg.StrOpt('def_templates_dir',
|
||||||
|
default='/etc/vitrage/templates/def_templates',
|
||||||
|
help='A path for def_template templates used by the evaluator')
|
||||||
]
|
]
|
||||||
|
@ -23,6 +23,10 @@ from vitrage.evaluator.equivalence_repository import EquivalenceRepository
|
|||||||
from vitrage.evaluator.template_data import TemplateData
|
from vitrage.evaluator.template_data import TemplateData
|
||||||
from vitrage.evaluator.template_validation.content.template_content_validator \
|
from vitrage.evaluator.template_validation.content.template_content_validator \
|
||||||
import content_validation
|
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 \
|
from vitrage.evaluator.template_validation.template_syntax_validator import \
|
||||||
syntax_validation
|
syntax_validation
|
||||||
from vitrage.utils import datetime as datetime_utils
|
from vitrage.utils import datetime as datetime_utils
|
||||||
@ -31,21 +35,32 @@ from vitrage.utils import file as file_utils
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
EdgeKeyScenario = namedtuple('EdgeKeyScenario', ['label', 'source', 'target'])
|
EdgeKeyScenario = namedtuple('EdgeKeyScenario', ['label', 'source', 'target'])
|
||||||
|
DEF_TEMPLATES_DIR_OPT = 'def_templates_dir'
|
||||||
|
|
||||||
|
|
||||||
class ScenarioRepository(object):
|
class ScenarioRepository(object):
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
self._templates = {}
|
self._templates = {}
|
||||||
|
self._def_templates = {}
|
||||||
self.entity_equivalences = EquivalenceRepository().load_files(
|
self.entity_equivalences = EquivalenceRepository().load_files(
|
||||||
conf.evaluator.equivalences_dir)
|
conf.evaluator.equivalences_dir)
|
||||||
self.relationship_scenarios = defaultdict(list)
|
self.relationship_scenarios = defaultdict(list)
|
||||||
self.entity_scenarios = defaultdict(list)
|
self.entity_scenarios = defaultdict(list)
|
||||||
|
self._load_def_template_files(conf)
|
||||||
self._load_templates_files(conf)
|
self._load_templates_files(conf)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def templates(self):
|
def templates(self):
|
||||||
return self._templates
|
return self._templates
|
||||||
|
|
||||||
|
@property
|
||||||
|
def def_templates(self):
|
||||||
|
return self._def_templates
|
||||||
|
|
||||||
|
@def_templates.setter
|
||||||
|
def def_templates(self, def_templates):
|
||||||
|
self._def_templates = def_templates
|
||||||
|
|
||||||
@templates.setter
|
@templates.setter
|
||||||
def templates(self, templates):
|
def templates(self, templates):
|
||||||
self._templates = templates
|
self._templates = templates
|
||||||
@ -82,27 +97,47 @@ class ScenarioRepository(object):
|
|||||||
|
|
||||||
def add_template(self, template_def):
|
def add_template(self, template_def):
|
||||||
|
|
||||||
current_time = datetime_utils.utcnow()
|
|
||||||
|
|
||||||
result = syntax_validation(template_def)
|
result = syntax_validation(template_def)
|
||||||
if not result.is_valid_config:
|
if not result.is_valid_config:
|
||||||
LOG.info('Unable to load template: %s' % result.comment)
|
LOG.info('Unable to load template, syntax err: %s'
|
||||||
|
% result.comment)
|
||||||
else:
|
else:
|
||||||
result = content_validation(template_def)
|
result = content_validation(template_def, self._def_templates)
|
||||||
if not result.is_valid_config:
|
if not result.is_valid_config:
|
||||||
LOG.info('Unable to load template: %s' % result.comment)
|
LOG.info('Unable to load template, content err: %s'
|
||||||
|
% result.comment)
|
||||||
|
|
||||||
template_uuid = uuidutils.generate_uuid()
|
template_uuid = uuidutils.generate_uuid()
|
||||||
|
current_time = datetime_utils.utcnow()
|
||||||
self.templates[str(template_uuid)] = Template(template_uuid,
|
self.templates[str(template_uuid)] = Template(template_uuid,
|
||||||
template_def,
|
template_def,
|
||||||
current_time,
|
current_time,
|
||||||
result)
|
result)
|
||||||
if result.is_valid_config:
|
if result.is_valid_config:
|
||||||
template_data = TemplateData(template_def)
|
template_data = TemplateData(template_def, self._def_templates)
|
||||||
for scenario in template_data.scenarios:
|
for scenario in template_data.scenarios:
|
||||||
for equivalent_scenario in self._expand_equivalence(scenario):
|
for equivalent_scenario in self._expand_equivalence(scenario):
|
||||||
self._add_scenario(equivalent_scenario)
|
self._add_scenario(equivalent_scenario)
|
||||||
|
|
||||||
|
def add_def_template(self, def_template):
|
||||||
|
|
||||||
|
result = def_template_syntax_validation(def_template)
|
||||||
|
if not result.is_valid_config:
|
||||||
|
LOG.info('Unable to load definition template, syntax err: %s'
|
||||||
|
% result.comment)
|
||||||
|
else:
|
||||||
|
result = def_template_content_validation(def_template)
|
||||||
|
if not result.is_valid_config:
|
||||||
|
LOG.info('Unable to load definition template, content err: %s'
|
||||||
|
% result.comment)
|
||||||
|
|
||||||
|
current_time = datetime_utils.utcnow()
|
||||||
|
include_uuid = uuidutils.generate_uuid()
|
||||||
|
self._def_templates[str(include_uuid)] = Template(include_uuid,
|
||||||
|
def_template,
|
||||||
|
current_time,
|
||||||
|
result)
|
||||||
|
|
||||||
def _expand_equivalence(self, scenario):
|
def _expand_equivalence(self, scenario):
|
||||||
equivalent_scenarios = [scenario]
|
equivalent_scenarios = [scenario]
|
||||||
for symbol_name, entity in scenario.entities.items():
|
for symbol_name, entity in scenario.entities.items():
|
||||||
@ -133,6 +168,16 @@ class ScenarioRepository(object):
|
|||||||
for relationship in scenario.relationships.values():
|
for relationship in scenario.relationships.values():
|
||||||
self._add_relationship_scenario(scenario, relationship)
|
self._add_relationship_scenario(scenario, relationship)
|
||||||
|
|
||||||
|
def _load_def_template_files(self, conf):
|
||||||
|
|
||||||
|
if DEF_TEMPLATES_DIR_OPT in conf.evaluator:
|
||||||
|
|
||||||
|
def_templates_dir = conf.evaluator.def_templates_dir
|
||||||
|
def_templates = file_utils.load_yaml_files(def_templates_dir)
|
||||||
|
|
||||||
|
for def_template in def_templates:
|
||||||
|
self.add_def_template(def_template)
|
||||||
|
|
||||||
def _load_templates_files(self, conf):
|
def _load_templates_files(self, conf):
|
||||||
|
|
||||||
templates_dir = conf.evaluator.templates_dir
|
templates_dir = conf.evaluator.templates_dir
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
from vitrage.common.constants import EdgeProperties as EProps
|
from vitrage.common.constants import EdgeProperties as EProps
|
||||||
from vitrage.common.constants import VertexProperties as VProps
|
from vitrage.common.constants import VertexProperties as VProps
|
||||||
from vitrage.common.exception import VitrageError
|
from vitrage.common.exception import VitrageError
|
||||||
@ -26,6 +27,7 @@ from vitrage.graph.algo_driver.sub_graph_matching import NEG_CONDITION
|
|||||||
from vitrage.graph.driver.networkx_graph import NXGraph
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
from vitrage.graph import Edge
|
from vitrage.graph import Edge
|
||||||
from vitrage.graph import Vertex
|
from vitrage.graph import Vertex
|
||||||
|
from vitrage.utils import evaluator as evaluator_utils
|
||||||
|
|
||||||
ActionSpecs = namedtuple('ActionSpecs', ['type', 'targets', 'properties'])
|
ActionSpecs = namedtuple('ActionSpecs', ['type', 'targets', 'properties'])
|
||||||
Scenario = namedtuple('Scenario', ['id',
|
Scenario = namedtuple('Scenario', ['id',
|
||||||
@ -61,18 +63,32 @@ class TemplateData(object):
|
|||||||
'operational_severity': VProps.VITRAGE_OPERATIONAL_SEVERITY
|
'operational_severity': VProps.VITRAGE_OPERATIONAL_SEVERITY
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, template_def):
|
def __init__(self, template_def, def_templates={}):
|
||||||
|
|
||||||
self.name = template_def[TFields.METADATA][TFields.NAME]
|
self.name = template_def[TFields.METADATA][TFields.NAME]
|
||||||
|
defs = {}
|
||||||
|
if TFields.DEFINITIONS in template_def:
|
||||||
defs = template_def[TFields.DEFINITIONS]
|
defs = template_def[TFields.DEFINITIONS]
|
||||||
|
if TFields.ENTITIES in defs:
|
||||||
self.entities = self._build_entities(defs[TFields.ENTITIES])
|
self.entities = self._build_entities(defs[TFields.ENTITIES])
|
||||||
|
|
||||||
self.relationships = {}
|
self.relationships = {}
|
||||||
|
|
||||||
|
# Add definitions from template then from definition templates.
|
||||||
|
if TFields.INCLUDES in template_def:
|
||||||
|
includes = template_def[TFields.INCLUDES]
|
||||||
|
self._build_entities_from_def_templates(
|
||||||
|
includes, def_templates, self.entities)
|
||||||
|
|
||||||
if TFields.RELATIONSHIPS in defs:
|
if TFields.RELATIONSHIPS in defs:
|
||||||
self.relationships = self._build_relationships(
|
self.relationships = self._build_relationships(
|
||||||
defs[TFields.RELATIONSHIPS])
|
defs[TFields.RELATIONSHIPS])
|
||||||
|
|
||||||
|
if TFields.INCLUDES in template_def:
|
||||||
|
includes = template_def[TFields.INCLUDES]
|
||||||
|
self._build_relationships_with_def_templates(includes,
|
||||||
|
def_templates,
|
||||||
|
self.relationships)
|
||||||
|
|
||||||
self.scenarios = self._build_scenarios(template_def[TFields.SCENARIOS])
|
self.scenarios = self._build_scenarios(template_def[TFields.SCENARIOS])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -120,6 +136,27 @@ class TemplateData(object):
|
|||||||
|
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
|
def _build_entities_from_def_templates(
|
||||||
|
self, includes, def_templates, entities):
|
||||||
|
|
||||||
|
for def_template_dict in includes:
|
||||||
|
|
||||||
|
name = def_template_dict[TFields.NAME]
|
||||||
|
def_template = evaluator_utils.find_def_template(
|
||||||
|
name, def_templates)
|
||||||
|
defs = def_template[TFields.DEFINITIONS]
|
||||||
|
entities_defs = defs[TFields.ENTITIES]
|
||||||
|
|
||||||
|
for entity_def in entities_defs:
|
||||||
|
|
||||||
|
entity_dict = entity_def[TFields.ENTITY]
|
||||||
|
template_id = entity_dict[TFields.TEMPLATE_ID]
|
||||||
|
if template_id not in entities:
|
||||||
|
|
||||||
|
properties = self._convert_properties_with_dictionary(
|
||||||
|
self._extract_properties(entity_dict))
|
||||||
|
entities[template_id] = Vertex(template_id, properties)
|
||||||
|
|
||||||
def _build_relationships(self, relationships_defs):
|
def _build_relationships(self, relationships_defs):
|
||||||
|
|
||||||
relationships = {}
|
relationships = {}
|
||||||
@ -132,6 +169,28 @@ class TemplateData(object):
|
|||||||
|
|
||||||
return relationships
|
return relationships
|
||||||
|
|
||||||
|
def _build_relationships_with_def_templates(
|
||||||
|
self, includes, def_templates, relationships):
|
||||||
|
|
||||||
|
for def_template_dict in includes:
|
||||||
|
|
||||||
|
name = def_template_dict[TFields.NAME]
|
||||||
|
def_template = evaluator_utils.find_def_template(
|
||||||
|
name, def_templates)
|
||||||
|
|
||||||
|
if TFields.RELATIONSHIPS in def_template[TFields.DEFINITIONS]:
|
||||||
|
defs = def_template[TFields.DEFINITIONS]
|
||||||
|
relationship_defs = defs[TFields.RELATIONSHIPS]
|
||||||
|
|
||||||
|
for relationship_def in relationship_defs:
|
||||||
|
relationship_dict = relationship_def[TFields.RELATIONSHIP]
|
||||||
|
template_id = relationship_dict[TFields.TEMPLATE_ID]
|
||||||
|
|
||||||
|
if template_id not in relationships:
|
||||||
|
relationship = self._extract_relationship_info(
|
||||||
|
relationship_dict)
|
||||||
|
relationships[template_id] = relationship
|
||||||
|
|
||||||
def _extract_relationship_info(self, relationship_dict):
|
def _extract_relationship_info(self, relationship_dict):
|
||||||
|
|
||||||
source_id = relationship_dict[TFields.SOURCE]
|
source_id = relationship_dict[TFields.SOURCE]
|
||||||
|
@ -26,6 +26,7 @@ class TemplateFields(TemplateTopologyFields):
|
|||||||
ACTION_TYPE = 'action_type'
|
ACTION_TYPE = 'action_type'
|
||||||
CATEGORY = 'category'
|
CATEGORY = 'category'
|
||||||
CONDITION = 'condition'
|
CONDITION = 'condition'
|
||||||
|
INCLUDES = 'includes'
|
||||||
SEVERITY = 'severity'
|
SEVERITY = 'severity'
|
||||||
SCENARIO = 'scenario'
|
SCENARIO = 'scenario'
|
||||||
STATE = 'state'
|
STATE = 'state'
|
||||||
|
@ -43,18 +43,33 @@ from vitrage.evaluator.template_validation.content.raise_alarm_validator \
|
|||||||
from vitrage.evaluator.template_validation.content.set_state_validator \
|
from vitrage.evaluator.template_validation.content.set_state_validator \
|
||||||
import SetStateValidator
|
import SetStateValidator
|
||||||
from vitrage.evaluator.template_validation.status_messages import status_msgs
|
from vitrage.evaluator.template_validation.status_messages import status_msgs
|
||||||
|
from vitrage.utils import evaluator as evaluator_utils
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def content_validation(template):
|
def content_validation(template, def_templates={}):
|
||||||
|
|
||||||
|
result = get_content_correct_result()
|
||||||
|
entities_index = {}
|
||||||
|
template_definitions = {}
|
||||||
|
|
||||||
|
if TemplateFields.DEFINITIONS in template:
|
||||||
template_definitions = template[TemplateFields.DEFINITIONS]
|
template_definitions = template[TemplateFields.DEFINITIONS]
|
||||||
|
|
||||||
entities_index = {}
|
if TemplateFields.ENTITIES in template_definitions:
|
||||||
entities = template_definitions[TemplateFields.ENTITIES]
|
entities = template_definitions[TemplateFields.ENTITIES]
|
||||||
result = _validate_entities_definition(entities, entities_index)
|
result = _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,
|
||||||
|
def_templates,
|
||||||
|
entities_index)
|
||||||
|
|
||||||
relationships_index = {}
|
relationships_index = {}
|
||||||
|
|
||||||
if result.is_valid_config and \
|
if result.is_valid_config and \
|
||||||
@ -64,6 +79,15 @@ def content_validation(template):
|
|||||||
result = _validate_relationships_definitions(relationships,
|
result = _validate_relationships_definitions(relationships,
|
||||||
relationships_index,
|
relationships_index,
|
||||||
entities_index)
|
entities_index)
|
||||||
|
|
||||||
|
if result.is_valid_config and TemplateFields.INCLUDES in template:
|
||||||
|
template_includes = template[TemplateFields.INCLUDES]
|
||||||
|
result = _validate_relationships_definitions_with_includes(
|
||||||
|
template_includes,
|
||||||
|
def_templates,
|
||||||
|
entities_index,
|
||||||
|
relationships_index)
|
||||||
|
|
||||||
if result.is_valid_config:
|
if result.is_valid_config:
|
||||||
scenarios = template[TemplateFields.SCENARIOS]
|
scenarios = template[TemplateFields.SCENARIOS]
|
||||||
definitions_index = entities_index.copy()
|
definitions_index = entities_index.copy()
|
||||||
@ -73,6 +97,25 @@ def content_validation(template):
|
|||||||
return result
|
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):
|
def _validate_entities_definition(entities, entities_index):
|
||||||
|
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
@ -98,6 +141,49 @@ def _validate_entity_definition(entity_dict, entities_index):
|
|||||||
return get_content_correct_result()
|
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,
|
def _validate_relationships_definitions(relationships,
|
||||||
relationships_index,
|
relationships_index,
|
||||||
entities_index):
|
entities_index):
|
||||||
@ -116,6 +202,49 @@ def _validate_relationships_definitions(relationships,
|
|||||||
return get_content_correct_result()
|
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):
|
def _validate_relationship(relationship, relationships_index, entities_index):
|
||||||
|
|
||||||
template_id = relationship[TemplateFields.TEMPLATE_ID]
|
template_id = relationship[TemplateFields.TEMPLATE_ID]
|
||||||
|
@ -79,4 +79,10 @@ status_msgs = {
|
|||||||
'block',
|
'block',
|
||||||
134: 'condition can not contain only \'not\' clauses',
|
134: 'condition can not contain only \'not\' clauses',
|
||||||
135: 'condition must contain a common entity for all \'or\' clauses',
|
135: 'condition must contain a common entity for all \'or\' clauses',
|
||||||
|
|
||||||
|
# def_templates status messages 140-159
|
||||||
|
140: 'At least one template must be included',
|
||||||
|
141: 'Name field is unspecified for include',
|
||||||
|
142: 'Trying to include a template that does not exist',
|
||||||
|
143: 'Includable cannot have Includes or Scenarios',
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ from voluptuous import All
|
|||||||
from voluptuous import Any
|
from voluptuous import Any
|
||||||
from voluptuous import Error
|
from voluptuous import Error
|
||||||
from voluptuous import Invalid
|
from voluptuous import Invalid
|
||||||
|
from voluptuous import Optional
|
||||||
from voluptuous import Required
|
from voluptuous import Required
|
||||||
from voluptuous import Schema
|
from voluptuous import Schema
|
||||||
|
|
||||||
@ -31,21 +32,24 @@ from vitrage.evaluator.template_validation.status_messages import status_msgs
|
|||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
RESULT_DESCRIPTION = 'Template syntax validation'
|
RESULT_DESCRIPTION = 'Template syntax validation'
|
||||||
|
|
||||||
|
|
||||||
def syntax_validation(template_conf):
|
def syntax_validation(template_conf):
|
||||||
|
|
||||||
result = _validate_template_sections(template_conf)
|
result = _validate_template_sections(template_conf)
|
||||||
|
|
||||||
if result.is_valid_config:
|
if result.is_valid_config:
|
||||||
metadata = template_conf[TemplateFields.METADATA]
|
metadata = template_conf[TemplateFields.METADATA]
|
||||||
result = _validate_metadata_section(metadata)
|
result = _validate_metadata_section(metadata)
|
||||||
|
|
||||||
if result.is_valid_config:
|
if result.is_valid_config and TemplateFields.INCLUDES in template_conf:
|
||||||
|
includes = template_conf[TemplateFields.INCLUDES]
|
||||||
|
result = _validate_includes_section(includes)
|
||||||
|
|
||||||
|
if result.is_valid_config and TemplateFields.DEFINITIONS in template_conf:
|
||||||
definitions = template_conf[TemplateFields.DEFINITIONS]
|
definitions = template_conf[TemplateFields.DEFINITIONS]
|
||||||
result = _validate_definitions_section(definitions)
|
has_includes = TemplateFields.INCLUDES in template_conf
|
||||||
|
result = _validate_definitions_section(definitions, has_includes)
|
||||||
|
|
||||||
if result.is_valid_config:
|
if result.is_valid_config:
|
||||||
scenarios = template_conf[TemplateFields.SCENARIOS]
|
scenarios = template_conf[TemplateFields.SCENARIOS]
|
||||||
@ -54,18 +58,52 @@ def syntax_validation(template_conf):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _validate_template_sections(template_conf):
|
def def_template_syntax_validation(def_template_conf):
|
||||||
|
result = _validate_def_template_template_sections(def_template_conf)
|
||||||
|
|
||||||
|
if TemplateFields.INCLUDES in def_template_conf or \
|
||||||
|
TemplateFields.SCENARIOS in def_template_conf:
|
||||||
|
LOG.error('%s status code: %s' % (status_msgs[143], 143))
|
||||||
|
return get_fault_result(RESULT_DESCRIPTION, 143)
|
||||||
|
|
||||||
|
if result.is_valid_config:
|
||||||
|
metadata = def_template_conf[TemplateFields.METADATA]
|
||||||
|
result = _validate_metadata_section(metadata)
|
||||||
|
|
||||||
|
if result.is_valid_config:
|
||||||
|
definitions = def_template_conf[TemplateFields.DEFINITIONS]
|
||||||
|
result = _validate_definitions_section(definitions, False)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_def_template_template_sections(def_template_conf):
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
Required(TemplateFields.DEFINITIONS, msg=21): dict,
|
Required(TemplateFields.DEFINITIONS, msg=21): dict,
|
||||||
Required(TemplateFields.METADATA, msg=62): dict,
|
Required(TemplateFields.METADATA, msg=62): dict,
|
||||||
Required(TemplateFields.SCENARIOS, msg=80): list
|
})
|
||||||
|
return _validate_dict_schema(schema, def_template_conf)
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_template_sections(template_conf):
|
||||||
|
if TemplateFields.INCLUDES in template_conf:
|
||||||
|
schema = Schema({
|
||||||
|
Optional(TemplateFields.DEFINITIONS): dict,
|
||||||
|
Required(TemplateFields.METADATA, msg=62): dict,
|
||||||
|
Required(TemplateFields.SCENARIOS, msg=80): list,
|
||||||
|
Optional(TemplateFields.INCLUDES): list
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
schema = Schema({
|
||||||
|
Required(TemplateFields.DEFINITIONS, msg=21): dict,
|
||||||
|
Required(TemplateFields.METADATA, msg=62): dict,
|
||||||
|
Required(TemplateFields.SCENARIOS, msg=80): list,
|
||||||
|
Optional(TemplateFields.INCLUDES): list
|
||||||
})
|
})
|
||||||
return _validate_dict_schema(schema, template_conf)
|
return _validate_dict_schema(schema, template_conf)
|
||||||
|
|
||||||
|
|
||||||
def _validate_metadata_section(metadata):
|
def _validate_metadata_section(metadata):
|
||||||
|
|
||||||
any_str = Any(str, six.text_type)
|
any_str = Any(str, six.text_type)
|
||||||
|
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
@ -75,10 +113,45 @@ def _validate_metadata_section(metadata):
|
|||||||
return _validate_dict_schema(schema, metadata)
|
return _validate_dict_schema(schema, metadata)
|
||||||
|
|
||||||
|
|
||||||
def _validate_definitions_section(definitions):
|
def _validate_includes_section(includes):
|
||||||
|
any_str = Any(str, six.text_type)
|
||||||
|
if not includes:
|
||||||
|
LOG.error('%s status code: %s' % (status_msgs[140], 140))
|
||||||
|
return get_fault_result(RESULT_DESCRIPTION, 140)
|
||||||
|
|
||||||
if TemplateFields.RELATIONSHIPS not in definitions or \
|
for name in includes:
|
||||||
definitions[TemplateFields.RELATIONSHIPS] != '':
|
schema = Schema({
|
||||||
|
Required(TemplateFields.NAME, msg=141): any_str
|
||||||
|
})
|
||||||
|
result = _validate_name_schema(schema, name)
|
||||||
|
if not result.is_valid_config:
|
||||||
|
return result
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_name_schema(schema, name):
|
||||||
|
try:
|
||||||
|
schema(name)
|
||||||
|
except Error as e:
|
||||||
|
|
||||||
|
status_code = _get_status_code(e)
|
||||||
|
if status_code:
|
||||||
|
msg = status_msgs[status_code]
|
||||||
|
else:
|
||||||
|
# General syntax error
|
||||||
|
status_code = 4
|
||||||
|
msg = status_msgs[4] + str(e)
|
||||||
|
|
||||||
|
LOG.error('%s status code: %s' % (msg, status_code))
|
||||||
|
return get_fault_result(RESULT_DESCRIPTION, status_code, msg)
|
||||||
|
|
||||||
|
return get_correct_result(RESULT_DESCRIPTION)
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_definitions_section(definitions, has_includes):
|
||||||
|
if TemplateFields.RELATIONSHIPS not in definitions \
|
||||||
|
or definitions[TemplateFields.RELATIONSHIPS] != '':
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
Required(TemplateFields.ENTITIES, msg=20): list,
|
Required(TemplateFields.ENTITIES, msg=20): list,
|
||||||
TemplateFields.RELATIONSHIPS: list
|
TemplateFields.RELATIONSHIPS: list
|
||||||
@ -88,8 +161,9 @@ def _validate_definitions_section(definitions):
|
|||||||
else:
|
else:
|
||||||
result = get_correct_result(RESULT_DESCRIPTION)
|
result = get_correct_result(RESULT_DESCRIPTION)
|
||||||
|
|
||||||
if result.is_valid_config:
|
if result.is_valid_config and TemplateFields.ENTITIES in definitions:
|
||||||
result = _validate_entities(definitions[TemplateFields.ENTITIES])
|
entities = definitions[TemplateFields.ENTITIES]
|
||||||
|
result = _validate_entities(entities, has_includes)
|
||||||
|
|
||||||
relationships = definitions.get(TemplateFields.RELATIONSHIPS, None)
|
relationships = definitions.get(TemplateFields.RELATIONSHIPS, None)
|
||||||
if result.is_valid_config and relationships:
|
if result.is_valid_config and relationships:
|
||||||
@ -98,9 +172,8 @@ def _validate_definitions_section(definitions):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _validate_entities(entities):
|
def _validate_entities(entities, has_includes):
|
||||||
|
if not entities and not has_includes:
|
||||||
if not entities:
|
|
||||||
LOG.error('%s status code: %s' % (status_msgs[43], 43))
|
LOG.error('%s status code: %s' % (status_msgs[43], 43))
|
||||||
return get_fault_result(RESULT_DESCRIPTION, 43)
|
return get_fault_result(RESULT_DESCRIPTION, 43)
|
||||||
|
|
||||||
@ -121,7 +194,6 @@ def _validate_entities(entities):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_entity_dict(entity_dict):
|
def _validate_entity_dict(entity_dict):
|
||||||
|
|
||||||
any_str = Any(str, six.text_type)
|
any_str = Any(str, six.text_type)
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
Required(TemplateFields.CATEGORY, msg=42):
|
Required(TemplateFields.CATEGORY, msg=42):
|
||||||
@ -135,7 +207,6 @@ def _validate_entity_dict(entity_dict):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_relationships(relationships):
|
def _validate_relationships(relationships):
|
||||||
|
|
||||||
for relationship in relationships:
|
for relationship in relationships:
|
||||||
|
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
@ -153,7 +224,6 @@ def _validate_relationships(relationships):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_relationship_dict(relationship_dict):
|
def _validate_relationship_dict(relationship_dict):
|
||||||
|
|
||||||
any_str = Any(str, six.text_type)
|
any_str = Any(str, six.text_type)
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
Required(TemplateFields.SOURCE, msg=102): any_str,
|
Required(TemplateFields.SOURCE, msg=102): any_str,
|
||||||
@ -166,7 +236,6 @@ def _validate_relationship_dict(relationship_dict):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_scenarios_section(scenarios):
|
def _validate_scenarios_section(scenarios):
|
||||||
|
|
||||||
if not scenarios:
|
if not scenarios:
|
||||||
LOG.error('%s status code: %s' % (status_msgs[81], 81))
|
LOG.error('%s status code: %s' % (status_msgs[81], 81))
|
||||||
return get_fault_result(RESULT_DESCRIPTION, 81)
|
return get_fault_result(RESULT_DESCRIPTION, 81)
|
||||||
@ -188,7 +257,6 @@ def _validate_scenarios_section(scenarios):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_scenario(scenario):
|
def _validate_scenario(scenario):
|
||||||
|
|
||||||
any_str = Any(str, six.text_type)
|
any_str = Any(str, six.text_type)
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
Required(TemplateFields.CONDITION, msg=83): any_str,
|
Required(TemplateFields.CONDITION, msg=83): any_str,
|
||||||
@ -203,7 +271,6 @@ def _validate_scenario(scenario):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_actions_schema(actions):
|
def _validate_actions_schema(actions):
|
||||||
|
|
||||||
if not actions:
|
if not actions:
|
||||||
LOG.error('%s status code: %s' % (status_msgs[121], 121))
|
LOG.error('%s status code: %s' % (status_msgs[121], 121))
|
||||||
return get_fault_result(RESULT_DESCRIPTION, 121)
|
return get_fault_result(RESULT_DESCRIPTION, 121)
|
||||||
@ -225,7 +292,6 @@ def _validate_actions_schema(actions):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_action_schema(action):
|
def _validate_action_schema(action):
|
||||||
|
|
||||||
schema = Schema({
|
schema = Schema({
|
||||||
Required(TemplateFields.ACTION_TYPE, msg=123):
|
Required(TemplateFields.ACTION_TYPE, msg=123):
|
||||||
_validate_action_type_field(),
|
_validate_action_type_field(),
|
||||||
@ -236,7 +302,6 @@ def _validate_action_schema(action):
|
|||||||
|
|
||||||
|
|
||||||
def _validate_dict_schema(schema, value):
|
def _validate_dict_schema(schema, value):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
schema(value)
|
schema(value)
|
||||||
except Error as e:
|
except Error as e:
|
||||||
@ -268,6 +333,7 @@ def _validate_template_id_value(msg=None):
|
|||||||
return str(v)
|
return str(v)
|
||||||
else:
|
else:
|
||||||
raise Invalid(msg or 1)
|
raise Invalid(msg or 1)
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
@ -277,6 +343,7 @@ def _validate_category_field(msg=None):
|
|||||||
return str(v)
|
return str(v)
|
||||||
else:
|
else:
|
||||||
raise Invalid(msg or 45)
|
raise Invalid(msg or 45)
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
@ -286,4 +353,5 @@ def _validate_action_type_field(msg=None):
|
|||||||
return str(v)
|
return str(v)
|
||||||
else:
|
else:
|
||||||
raise Invalid(msg or 120)
|
raise Invalid(msg or 120)
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
|
from collections import namedtuple
|
||||||
import json
|
import json
|
||||||
from os.path import dirname
|
from os.path import dirname
|
||||||
from os import walk
|
from os import walk
|
||||||
@ -47,6 +48,25 @@ def load_specs(target_filename, target_folder=None):
|
|||||||
return json.load(reader(infile))
|
return json.load(reader(infile))
|
||||||
|
|
||||||
|
|
||||||
|
def get_def_templates_dict_from_list(def_temps_list):
|
||||||
|
"""Turns a list of def_temps into a dictionary of def_temps where the keys
|
||||||
|
|
||||||
|
are their index in the list. Used by unit tests
|
||||||
|
|
||||||
|
:param def_temps_list: def_temp list to convert
|
||||||
|
:type def_temps_list: list
|
||||||
|
:return: a def_temps dict
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
Template = namedtuple('Template', 'data')
|
||||||
|
dict = {}
|
||||||
|
for num, item in zip(range(len(def_temps_list)), def_temps_list):
|
||||||
|
dict[num] = Template(item)
|
||||||
|
|
||||||
|
return dict
|
||||||
|
|
||||||
|
|
||||||
def _get_full_path(target_filename, target_folder):
|
def _get_full_path(target_filename, target_folder):
|
||||||
"""Returns the full path for the given folder and filename
|
"""Returns the full path for the given folder and filename
|
||||||
|
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
metadata:
|
||||||
|
#a basic def_template file
|
||||||
|
name: basic_def_template
|
||||||
|
description: basic def_template for general tests
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: host_problem
|
||||||
|
template_id: alarm
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource
|
||||||
|
relationships:
|
||||||
|
- relationship:
|
||||||
|
source: alarm
|
||||||
|
target: resource
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_on_host
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
metadata:
|
||||||
|
name: large_def_template
|
||||||
|
description: definition template with entities and relationsihps for tests
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: NETWORK_PROBLEM
|
||||||
|
template_id: network_alarm
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: CLUSTER_PROBLEM
|
||||||
|
template_id: cluster_alarm
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.zone
|
||||||
|
template_id: nova_zone
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: openstack.cluster
|
||||||
|
template_id: openstack_cluster
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: neutron.network
|
||||||
|
template_id: neutron_network
|
||||||
|
relationships:
|
||||||
|
- relationship:
|
||||||
|
source: openstack_cluster
|
||||||
|
target: nova_zone
|
||||||
|
relationship_type: contains
|
||||||
|
template_id : cluster_contains_zone
|
||||||
|
- relationship:
|
||||||
|
source: neutron_network
|
||||||
|
target: nova_zone
|
||||||
|
relationship_type: attached
|
||||||
|
template_id : network_attached_zone
|
||||||
|
- relationship:
|
||||||
|
source: network_alarm
|
||||||
|
target: neutron_network
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_on_network
|
@ -0,0 +1,10 @@
|
|||||||
|
metadata:
|
||||||
|
name: single_entity
|
||||||
|
description: definition template with a single entity
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
metadata:
|
||||||
|
name: def_template_with_include
|
||||||
|
description: a def_template with an include section for FAILING tests
|
||||||
|
includes:
|
||||||
|
- name: some_def_template
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: host_problem
|
||||||
|
template_id: alarm_inc
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource_inc
|
||||||
|
relationships:
|
||||||
|
- relationship:
|
||||||
|
source: alarm_inc
|
||||||
|
target: resource_inc
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_inc_on_host_inc
|
@ -0,0 +1,30 @@
|
|||||||
|
metadata:
|
||||||
|
name: def_template_with_scenarios
|
||||||
|
description: def_template with a scenarios section
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: host_problem
|
||||||
|
template_id: alarm_scen
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource_scen
|
||||||
|
relationships:
|
||||||
|
- relationship:
|
||||||
|
source: alarm_scen
|
||||||
|
target: resource_scen
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_scen_on_host_scen
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host_scen
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: resource_scen
|
@ -0,0 +1,26 @@
|
|||||||
|
metadata:
|
||||||
|
name: basic_template_with_include
|
||||||
|
description: basic template for general tests
|
||||||
|
includes:
|
||||||
|
- name: basic_def_template
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: host_problem
|
||||||
|
template_id: alarm11
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource11
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: resource
|
@ -0,0 +1,32 @@
|
|||||||
|
metadata:
|
||||||
|
name: basic_template_with_include
|
||||||
|
description: basic template for general tests
|
||||||
|
includes:
|
||||||
|
- name: fake_def_template
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: host_problem
|
||||||
|
template_id: alarm11
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource11
|
||||||
|
relationships:
|
||||||
|
- relationship:
|
||||||
|
source: alarm11
|
||||||
|
target: resource11
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm11_on_host11
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host11
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: resource11
|
@ -0,0 +1,34 @@
|
|||||||
|
metadata:
|
||||||
|
name: basic_template_with_two_includes
|
||||||
|
description: A template file which includes two defintion templates
|
||||||
|
includes:
|
||||||
|
- name: basic_def_template
|
||||||
|
- name: large_def_template
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: host_problem
|
||||||
|
template_id: alarm11
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource11
|
||||||
|
relationships:
|
||||||
|
#cluster_alarm from large_def_template and resource from basic_def_template
|
||||||
|
- relationship:
|
||||||
|
source: cluster_alarm
|
||||||
|
target: resource
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_on_resource
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_resource
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: resource
|
@ -0,0 +1,25 @@
|
|||||||
|
metadata:
|
||||||
|
name: template_with_empty_include
|
||||||
|
description: template with an empty include to invoke error
|
||||||
|
includes:
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: nagios
|
||||||
|
name: host_problem
|
||||||
|
template_id: alarm11
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: resource11
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: resource
|
@ -0,0 +1,15 @@
|
|||||||
|
metadata:
|
||||||
|
name: no_definitions_only_include
|
||||||
|
description: A template which only uses another definition template's definitions and has none of its own
|
||||||
|
includes:
|
||||||
|
- name: basic_def_template
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: resource
|
@ -0,0 +1,36 @@
|
|||||||
|
metadata:
|
||||||
|
name: only_using_def_template_definitions
|
||||||
|
description: A template file which only uses the entities in the files it includes and has none of its own
|
||||||
|
includes:
|
||||||
|
- name: basic_def_template
|
||||||
|
- name: large_def_template
|
||||||
|
definitions:
|
||||||
|
relationships:
|
||||||
|
#cluster_alarm from large_def_template and resource from basic_def_template
|
||||||
|
- relationship:
|
||||||
|
source: cluster_alarm
|
||||||
|
target: resource
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_on_resource
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_resource
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
#from large_def_template
|
||||||
|
target: openstack_cluster
|
||||||
|
- scenario:
|
||||||
|
#from large_def_template
|
||||||
|
condition: alarm_on_network
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
#from basic_def_template
|
||||||
|
target: resource
|
@ -0,0 +1,16 @@
|
|||||||
|
metadata:
|
||||||
|
name: basic_template_with_include
|
||||||
|
description: basic template for general tests
|
||||||
|
includes:
|
||||||
|
- name: basic_def_template
|
||||||
|
- name: single_entity
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
action_target:
|
||||||
|
target: resource
|
@ -33,11 +33,66 @@ class TemplateContentValidatorTest(ValidatorTest):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
|
||||||
template_dir_path = '%s/templates/general' % utils.get_resources_dir()
|
template_dir_path = '%s/templates/general' % utils.get_resources_dir()
|
||||||
|
cls.def_templates_tests_path = '%s/templates/def_template_tests/' % \
|
||||||
|
utils.get_resources_dir()
|
||||||
|
cls.def_templates_dir_path = cls.def_templates_tests_path +\
|
||||||
|
'definition_templates'
|
||||||
cls.templates = file_utils.load_yaml_files(template_dir_path)
|
cls.templates = file_utils.load_yaml_files(template_dir_path)
|
||||||
|
def_templates_list = file_utils.load_yaml_files(
|
||||||
|
cls.def_templates_dir_path)
|
||||||
|
cls.def_templates = utils.get_def_templates_dict_from_list(
|
||||||
|
def_templates_list)
|
||||||
cls.first_template = cls.templates[0]
|
cls.first_template = cls.templates[0]
|
||||||
|
|
||||||
cls._hide_useless_logging_messages()
|
cls._hide_useless_logging_messages()
|
||||||
|
|
||||||
|
def test_template_with_conflicting_include_entities(self):
|
||||||
|
template_path = '/templates/with_conflicting_include_entities.yaml'
|
||||||
|
template = file_utils.load_yaml_file(self.def_templates_tests_path +
|
||||||
|
template_path)
|
||||||
|
|
||||||
|
self._execute_and_assert_with_fault_result(template,
|
||||||
|
2,
|
||||||
|
self.def_templates)
|
||||||
|
|
||||||
|
def test_template_with_no_defs_only_includes(self):
|
||||||
|
template_path = '/templates/only_using_def_template_definitions.yaml'
|
||||||
|
template = file_utils.load_yaml_file(self.def_templates_tests_path +
|
||||||
|
template_path)
|
||||||
|
|
||||||
|
self._execute_and_assert_with_correct_result(template,
|
||||||
|
self.def_templates)
|
||||||
|
|
||||||
|
def test_template_with_multiple_includes(self):
|
||||||
|
template_path = '/templates/basic_with_two_includes.yaml'
|
||||||
|
template = file_utils.load_yaml_file(self.def_templates_tests_path +
|
||||||
|
template_path)
|
||||||
|
|
||||||
|
self._execute_and_assert_with_correct_result(template,
|
||||||
|
self.def_templates)
|
||||||
|
|
||||||
|
def test_template_with_nonexisiting_includes(self):
|
||||||
|
|
||||||
|
template_path = '/templates/basic_with_include_that_doesnt_exist.yaml'
|
||||||
|
template = file_utils.load_yaml_file(self.def_templates_tests_path +
|
||||||
|
template_path)
|
||||||
|
self._execute_and_assert_with_fault_result(template, 142)
|
||||||
|
|
||||||
|
def test_template_with_missing_def_template_dir(self):
|
||||||
|
|
||||||
|
template_path = '/templates/basic_with_include.yaml'
|
||||||
|
template = file_utils.load_yaml_file(self.def_templates_tests_path +
|
||||||
|
template_path)
|
||||||
|
self._execute_and_assert_with_fault_result(template, 142)
|
||||||
|
|
||||||
|
def test_template_with_include(self):
|
||||||
|
|
||||||
|
template_path = '/templates/basic_with_include.yaml'
|
||||||
|
template = file_utils.load_yaml_file(self.def_templates_tests_path +
|
||||||
|
template_path)
|
||||||
|
self._execute_and_assert_with_correct_result(template,
|
||||||
|
self.def_templates)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clone_template(self):
|
def clone_template(self):
|
||||||
return copy.deepcopy(self.first_template)
|
return copy.deepcopy(self.first_template)
|
||||||
@ -217,14 +272,17 @@ class TemplateContentValidatorTest(ValidatorTest):
|
|||||||
self._execute_and_assert_with_fault_result(
|
self._execute_and_assert_with_fault_result(
|
||||||
template_definition, status_code)
|
template_definition, status_code)
|
||||||
|
|
||||||
def _execute_and_assert_with_fault_result(self, template, status_code):
|
def _execute_and_assert_with_fault_result(self,
|
||||||
|
template,
|
||||||
|
status_code,
|
||||||
|
def_temps={}):
|
||||||
|
|
||||||
result = validator.content_validation(template)
|
result = validator.content_validation(template, def_temps)
|
||||||
self._assert_fault_result(result, status_code)
|
self._assert_fault_result(result, status_code)
|
||||||
|
|
||||||
def _execute_and_assert_with_correct_result(self, template):
|
def _execute_and_assert_with_correct_result(self, template, def_temps={}):
|
||||||
|
|
||||||
result = validator.content_validation(template)
|
result = validator.content_validation(template, def_temps)
|
||||||
self._assert_correct_result(result)
|
self._assert_correct_result(result)
|
||||||
|
|
||||||
def _create_scenario_actions(self, target, source):
|
def _create_scenario_actions(self, target, source):
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
# 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.template_validation.status_messages import status_msgs
|
||||||
|
from vitrage.evaluator.template_validation import template_syntax_validator
|
||||||
|
from vitrage.tests import base
|
||||||
|
from vitrage.tests.mocks import utils
|
||||||
|
from vitrage.utils import file as file_utils
|
||||||
|
|
||||||
|
|
||||||
|
class DefTemplateSyntaxValidatorTest(base.BaseTest):
|
||||||
|
|
||||||
|
# noinspection PyPep8Naming
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
cls.def_template_dir_path = utils.get_resources_dir() + \
|
||||||
|
'/templates/def_template_tests'
|
||||||
|
|
||||||
|
def test_def_template_with_include_section(self):
|
||||||
|
|
||||||
|
def_template_path = self.def_template_dir_path + \
|
||||||
|
'/definition_templates/with_include.yaml'
|
||||||
|
def_template = file_utils.load_yaml_file(def_template_path)
|
||||||
|
self._test_execution_with_fault_result_for_def_template(def_template,
|
||||||
|
143)
|
||||||
|
|
||||||
|
def test_def_template_with_scenario_section(self):
|
||||||
|
|
||||||
|
def_template_path = self.def_template_dir_path + \
|
||||||
|
'/definition_templates/with_scenarios.yaml'
|
||||||
|
def_template = file_utils.load_yaml_file(def_template_path)
|
||||||
|
self._test_execution_with_fault_result_for_def_template(def_template,
|
||||||
|
143)
|
||||||
|
|
||||||
|
def test_basic_def_template(self):
|
||||||
|
template_path = self.def_template_dir_path +\
|
||||||
|
'/templates/basic_with_include.yaml'
|
||||||
|
template = file_utils.load_yaml_file(template_path)
|
||||||
|
|
||||||
|
self._test_execution_with_correct_result(template)
|
||||||
|
|
||||||
|
def _test_execution_with_fault_result_for_def_template(self,
|
||||||
|
def_template,
|
||||||
|
expected_code):
|
||||||
|
|
||||||
|
result = template_syntax_validator.def_template_syntax_validation(
|
||||||
|
def_template)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertFalse(result.is_valid_config)
|
||||||
|
self.assertTrue(result.comment.startswith(status_msgs[expected_code]))
|
||||||
|
self.assertEqual(expected_code, result.status_code)
|
||||||
|
|
||||||
|
def _test_execution_with_correct_result(self, template):
|
||||||
|
|
||||||
|
# Test action
|
||||||
|
result = template_syntax_validator.syntax_validation(template)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self.assertTrue(result.is_valid_config)
|
||||||
|
self.assertEqual(result.comment, status_msgs[0])
|
||||||
|
self.assertEqual(0, result.status_code)
|
@ -29,6 +29,8 @@ class TemplateSyntaxValidatorTest(base.BaseTest):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
cls.def_template_dir_path = utils.get_resources_dir() + \
|
||||||
|
'/templates/def_template_tests'
|
||||||
template_dir_path = '%s/templates/general' % utils.get_resources_dir()
|
template_dir_path = '%s/templates/general' % utils.get_resources_dir()
|
||||||
cls.template_yamls = file_utils.load_yaml_files(template_dir_path)
|
cls.template_yamls = file_utils.load_yaml_files(template_dir_path)
|
||||||
cls.first_template = cls.template_yamls[0]
|
cls.first_template = cls.template_yamls[0]
|
||||||
@ -189,6 +191,19 @@ class TemplateSyntaxValidatorTest(base.BaseTest):
|
|||||||
scenario[TemplateFields.SCENARIO][TemplateFields.ACTIONS] = []
|
scenario[TemplateFields.SCENARIO][TemplateFields.ACTIONS] = []
|
||||||
self._test_execution_with_fault_result(template, 121)
|
self._test_execution_with_fault_result(template, 121)
|
||||||
|
|
||||||
|
def test_template_with_include_with_empty_name(self):
|
||||||
|
template_path = self.def_template_dir_path +\
|
||||||
|
'/templates/include_with_empty_name.yaml'
|
||||||
|
template = file_utils.load_yaml_file(template_path)
|
||||||
|
self._test_execution_with_fault_result(template, 4)
|
||||||
|
|
||||||
|
def test_template_with_include_with_no_defnitions(self):
|
||||||
|
template_path = self.def_template_dir_path +\
|
||||||
|
'/templates/no_definitions_only_include.yaml'
|
||||||
|
template = file_utils.load_yaml_file(template_path)
|
||||||
|
|
||||||
|
self._test_execution_with_correct_result(template)
|
||||||
|
|
||||||
def _test_validate_action_without_required_fields(self):
|
def _test_validate_action_without_required_fields(self):
|
||||||
|
|
||||||
self._test_validate_action_without_required_field(
|
self._test_validate_action_without_required_field(
|
||||||
@ -214,7 +229,9 @@ class TemplateSyntaxValidatorTest(base.BaseTest):
|
|||||||
|
|
||||||
self._test_execution_with_fault_result(template, status_msgs[100])
|
self._test_execution_with_fault_result(template, status_msgs[100])
|
||||||
|
|
||||||
def _test_execution_with_fault_result(self, template, expected_code):
|
def _test_execution_with_fault_result(self,
|
||||||
|
template,
|
||||||
|
expected_code):
|
||||||
|
|
||||||
# Test action
|
# Test action
|
||||||
result = template_syntax_validator.syntax_validation(template)
|
result = template_syntax_validator.syntax_validation(template)
|
||||||
|
@ -28,7 +28,6 @@ from vitrage.utils import file as file_utils
|
|||||||
|
|
||||||
class ScenarioRepositoryTest(base.BaseTest):
|
class ScenarioRepositoryTest(base.BaseTest):
|
||||||
BASE_DIR = utils.get_resources_dir() + '/templates/general'
|
BASE_DIR = utils.get_resources_dir() + '/templates/general'
|
||||||
HOST_HIGH_CPU = 'host_high_cpu_load_to_instance_cpu_suboptimal'
|
|
||||||
OPTS = [
|
OPTS = [
|
||||||
cfg.StrOpt('templates_dir',
|
cfg.StrOpt('templates_dir',
|
||||||
default=BASE_DIR,
|
default=BASE_DIR,
|
||||||
@ -103,9 +102,15 @@ class EquivalentScenarioTest(base.BaseTest):
|
|||||||
BASE_DIR = utils.get_resources_dir() + '/templates/equivalent_scenarios/'
|
BASE_DIR = utils.get_resources_dir() + '/templates/equivalent_scenarios/'
|
||||||
OPTS = [
|
OPTS = [
|
||||||
cfg.StrOpt('templates_dir',
|
cfg.StrOpt('templates_dir',
|
||||||
default=BASE_DIR),
|
default=BASE_DIR,
|
||||||
|
),
|
||||||
|
cfg.StrOpt('def_templates_dir',
|
||||||
|
default=(utils.get_resources_dir() +
|
||||||
|
'/templates/def_template_tests'),
|
||||||
|
),
|
||||||
cfg.StrOpt('equivalences_dir',
|
cfg.StrOpt('equivalences_dir',
|
||||||
default=BASE_DIR + '/equivalences')]
|
default=BASE_DIR + '/equivalences',),
|
||||||
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
@ -37,6 +37,119 @@ from vitrage.utils import file as file_utils
|
|||||||
class BasicTemplateTest(base.BaseTest):
|
class BasicTemplateTest(base.BaseTest):
|
||||||
|
|
||||||
BASIC_TEMPLATE = 'basic.yaml'
|
BASIC_TEMPLATE = 'basic.yaml'
|
||||||
|
BASIC_TEMPLATE_WITH_INCLUDE = 'basic_with_include.yaml'
|
||||||
|
DEF_TEMPLATE_TESTS_DIR = utils.get_resources_dir() +\
|
||||||
|
'/templates/def_template_tests'
|
||||||
|
|
||||||
|
def test_basic_template_with_include(self):
|
||||||
|
|
||||||
|
# Test setup
|
||||||
|
template_path = self.DEF_TEMPLATE_TESTS_DIR +\
|
||||||
|
'/templates/%s' % self.BASIC_TEMPLATE_WITH_INCLUDE
|
||||||
|
template_definition = file_utils.load_yaml_file(template_path, True)
|
||||||
|
def_templates_path = self.DEF_TEMPLATE_TESTS_DIR + \
|
||||||
|
'/definition_templates'
|
||||||
|
def_demplates_list = file_utils.load_yaml_files(
|
||||||
|
def_templates_path)
|
||||||
|
def_templates_dict = utils.get_def_templates_dict_from_list(
|
||||||
|
def_demplates_list)
|
||||||
|
template_data = TemplateData(template_definition, def_templates_dict)
|
||||||
|
entities = template_data.entities
|
||||||
|
relationships = template_data.relationships
|
||||||
|
scenarios = template_data.scenarios
|
||||||
|
definitions = template_definition[TFields.DEFINITIONS]
|
||||||
|
def_template = file_utils.load_yaml_file(
|
||||||
|
def_templates_path + '/basic_def_template.yaml')
|
||||||
|
def_template_entities = \
|
||||||
|
def_template[TFields.DEFINITIONS][TFields.ENTITIES]
|
||||||
|
def_template_relationships = \
|
||||||
|
def_template[TFields.DEFINITIONS][TFields.RELATIONSHIPS]
|
||||||
|
definitions[TFields.ENTITIES] += def_template_entities
|
||||||
|
definitions[TFields.RELATIONSHIPS] = def_template_relationships
|
||||||
|
|
||||||
|
# Assertions
|
||||||
|
for definition in definitions[TFields.ENTITIES]:
|
||||||
|
for key, value in definition['entity'].items():
|
||||||
|
new_key = TemplateData.PROPS_CONVERSION[key] if key in \
|
||||||
|
TemplateData.PROPS_CONVERSION else key
|
||||||
|
del definition['entity'][key]
|
||||||
|
definition['entity'][new_key] = value
|
||||||
|
self._validate_entities(entities, definitions[TFields.ENTITIES])
|
||||||
|
|
||||||
|
relate_def = def_template_relationships
|
||||||
|
self._validate_relationships(relationships, relate_def, entities)
|
||||||
|
self._validate_scenarios(scenarios, entities)
|
||||||
|
|
||||||
|
expected_entities = {
|
||||||
|
'alarm11': Vertex(
|
||||||
|
vertex_id='alarm11',
|
||||||
|
properties={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
|
||||||
|
VProps.VITRAGE_TYPE: NAGIOS_DATASOURCE,
|
||||||
|
VProps.NAME: 'host_problem'
|
||||||
|
}),
|
||||||
|
'resource11': Vertex(
|
||||||
|
vertex_id='resource11',
|
||||||
|
properties={VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
|
||||||
|
VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE
|
||||||
|
}),
|
||||||
|
'alarm': Vertex(
|
||||||
|
vertex_id='alarm',
|
||||||
|
properties={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
|
||||||
|
VProps.VITRAGE_TYPE: NAGIOS_DATASOURCE,
|
||||||
|
VProps.NAME: 'host_problem'
|
||||||
|
}),
|
||||||
|
'resource': Vertex(
|
||||||
|
vertex_id='resource',
|
||||||
|
properties={VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
|
||||||
|
VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE
|
||||||
|
})
|
||||||
|
}
|
||||||
|
expected_relationships = {
|
||||||
|
'alarm_on_host': EdgeDescription(
|
||||||
|
edge=Edge(source_id='alarm',
|
||||||
|
target_id='resource',
|
||||||
|
label=EdgeLabel.ON,
|
||||||
|
properties={EdgeProperties.RELATIONSHIP_TYPE:
|
||||||
|
EdgeLabel.ON}),
|
||||||
|
source=expected_entities['alarm'],
|
||||||
|
target=expected_entities['resource']
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
scenario_entities = {
|
||||||
|
'alarm': Vertex(
|
||||||
|
vertex_id='alarm',
|
||||||
|
properties={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
|
||||||
|
VProps.VITRAGE_TYPE: NAGIOS_DATASOURCE,
|
||||||
|
VProps.NAME: 'host_problem'
|
||||||
|
}),
|
||||||
|
'resource': Vertex(
|
||||||
|
vertex_id='resource',
|
||||||
|
properties={VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
|
||||||
|
VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
expected_scenario = Scenario(
|
||||||
|
id='basic_template_with_include-scenario0',
|
||||||
|
condition=[
|
||||||
|
[ConditionVar(symbol_name='alarm_on_host',
|
||||||
|
positive=True)]],
|
||||||
|
actions=[
|
||||||
|
ActionSpecs(
|
||||||
|
type=ActionType.SET_STATE,
|
||||||
|
targets={'target': 'resource'},
|
||||||
|
properties={'state':
|
||||||
|
OperationalResourceState.SUBOPTIMAL})],
|
||||||
|
subgraphs=template_data.scenarios[0].subgraphs,
|
||||||
|
entities=scenario_entities,
|
||||||
|
relationships=expected_relationships
|
||||||
|
)
|
||||||
|
|
||||||
|
self._validate_strict_equal(template_data,
|
||||||
|
expected_entities,
|
||||||
|
expected_relationships,
|
||||||
|
expected_scenario)
|
||||||
|
|
||||||
def test_basic_template(self):
|
def test_basic_template(self):
|
||||||
|
|
||||||
|
24
vitrage/utils/evaluator.py
Normal file
24
vitrage/utils/evaluator.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# 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.template_fields import TemplateFields
|
||||||
|
|
||||||
|
|
||||||
|
def find_def_template(name, def_templates):
|
||||||
|
|
||||||
|
for def_template_obj in def_templates.values():
|
||||||
|
def_template = def_template_obj.data
|
||||||
|
if def_template[TemplateFields.METADATA][TemplateFields.NAME] == name:
|
||||||
|
|
||||||
|
return def_template
|
||||||
|
return None
|
Loading…
x
Reference in New Issue
Block a user