34e9e3cc16
Change-Id: I80819413759b4ffdda75a87beddc5dab1adc6bd3
193 lines
5.7 KiB
ReStructuredText
193 lines
5.7 KiB
ReStructuredText
========================
|
|
Vitrage Template Loading
|
|
========================
|
|
|
|
Overview
|
|
========
|
|
|
|
Vitrage templates are defined in yaml with specific format_. During startup,
|
|
templates are loaded into ``TemplateData``. After that , scenarios in loaded
|
|
templates will be added into scenario repository.
|
|
|
|
This document explains the implementation details of template data to help
|
|
developer understand how scenario_evaluator_ works.
|
|
|
|
.. _format: vitrage-template-format.html
|
|
.. _scenario_evaluator: scenario-evaluator.html
|
|
|
|
Example
|
|
=======
|
|
|
|
Let's take a basic template as example
|
|
|
|
.. code-block:: yaml
|
|
|
|
metadata:
|
|
name: basic_template
|
|
description: basic template for general tests
|
|
definitions:
|
|
entities:
|
|
- entity:
|
|
category: ALARM
|
|
type: nagios
|
|
name: HOST_HIGH_CPU_LOAD
|
|
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
|
|
scenarios:
|
|
- scenario:
|
|
condition: alarm_on_host
|
|
actions:
|
|
- action:
|
|
action_type: set_state
|
|
properties:
|
|
state: SUBOPTIMAL
|
|
action_target:
|
|
target: resource
|
|
|
|
``TemplateData`` will build ``entities``, ``relationships`` and most importantly
|
|
``scenarios`` out from the definition.
|
|
|
|
.. code-block:: python
|
|
|
|
expected_entities = {
|
|
'alarm': Vertex(vertex_id='alarm',
|
|
properties={'vitrage_category': 'ALARM',
|
|
'vitrage_type': 'nagios',
|
|
'name': 'HOST_HIGH_CPU_LOAD',
|
|
}),
|
|
'resource': Vertex(vertex_id='resource',
|
|
properties={'vitrage_category': 'RESOURCE',
|
|
'vitrage_type': 'nova.host',
|
|
})
|
|
}
|
|
|
|
expected_relationships = {
|
|
'alarm_on_host': EdgeDescription(
|
|
edge=Edge(source_id='alarm',
|
|
target_id='resource',
|
|
label='on',
|
|
properties={'relationship_type': 'on'}),
|
|
source=expected_entities['alarm'],
|
|
target=expected_entities['resource']
|
|
)
|
|
}
|
|
|
|
expected_scenario = Scenario(
|
|
id='basic_template-scenario0',
|
|
condition=[
|
|
[ConditionVar(symbol_name='alarm_on_host',
|
|
positive=True)]],
|
|
actions=[
|
|
ActionSpecs(
|
|
type='set_state',
|
|
targets={'target': 'resource'},
|
|
properties={'state': 'SUBOPTIMAL'})],
|
|
subgraphs=template_data.scenarios[0].subgraphs, # ignore subgraphs
|
|
entities=expected_entities,
|
|
relationships=expected_relationships
|
|
)
|
|
|
|
Entities and relationships
|
|
==========================
|
|
|
|
Entities and relationships are loaded into dicts keyed by ``template_id`` so
|
|
that the references in scenarios can be resolved quickly.
|
|
|
|
Note that entities and relationships dicts are **NOT** added to scenario
|
|
repository. This implies the scope of ``template_id`` is restricted to one
|
|
template file. It is **NOT** global.
|
|
|
|
It is considered invalid to have duplicated ``template_id`` in one template, but
|
|
it is possible that two or more entities have exactly the same properties except
|
|
``template_id``. There is an example in
|
|
``vitrage/tests/templates/evaluator/high_availability.yaml``:
|
|
|
|
.. code:: yaml
|
|
|
|
- entity:
|
|
category: RESOURCE
|
|
type: nova.instance
|
|
template_id: instance1
|
|
- entity:
|
|
category: RESOURCE
|
|
type: nova.instance
|
|
template_id: instance2
|
|
|
|
It is used to model scenario contains two or more entities of same type, such
|
|
as high availability condition.
|
|
|
|
Scenarios
|
|
=========
|
|
|
|
``Scenario`` are defined as a ``namedtuple``
|
|
|
|
.. code-block:: python
|
|
|
|
Scenario = namedtuple('Scenario', ['id', 'condition', 'actions', 'subgraphs'])
|
|
|
|
id
|
|
--
|
|
|
|
Formatted from template name and scenario index
|
|
|
|
condition
|
|
---------
|
|
|
|
Condition strings in template are expressions composed of template id and
|
|
operators. As explained in embedded comment:
|
|
|
|
The condition string will be converted here into DNF (Disjunctive
|
|
Normal Form), e.g., (X and Y) or (X and Z) or (X and V and not W)...
|
|
where X, Y, Z, V, W are either entities or relationships
|
|
more details: https://en.wikipedia.org/wiki/Disjunctive_normal_form
|
|
|
|
The condition variable lists is then extracted from the DNF object. It
|
|
is a list of lists. Each inner list represents an AND expression
|
|
compound condition variables. The outer list presents the OR expression
|
|
|
|
[[and_var1, and_var2, ...], or_list_2, ...]
|
|
|
|
:param condition_str: the string as it written in the template itself
|
|
:return: condition_vars_lists
|
|
|
|
actions
|
|
-------
|
|
|
|
``actions`` is a list of ``ActionSpecs``.
|
|
|
|
The action targets in the spec must be referenced in the condition definition.
|
|
They are either linked to ``vertex_id`` of entity condition variables or
|
|
``source_id`` and ``target_id`` in relationship condition variable extracted.
|
|
|
|
In each matched subgraph in the entity graph, the targets will be resolved as
|
|
concrete vertices or edges.
|
|
|
|
subgraphs
|
|
---------
|
|
|
|
Sub graphs are built from conditions for pattern matching in the entity graph.
|
|
Each sub-list in condition variables list is compiled into one sub graph. The
|
|
actions will be triggered if any of the subgraph is matched.
|
|
|
|
entities & relationships
|
|
------------------------
|
|
|
|
Dicts of **touched** entities and relationships during subgraph building are
|
|
saved in scenario.
|
|
|
|
This makes creation of the scenarios repository index on related entities and
|
|
relationships easier and more efficient. You don't need to traverse the
|
|
condition object again, which is already done once during subgraphs building.
|
|
It also eliminate the necessity of duplication check because there is no
|
|
duplicate entities or relationships in these dicts compared to the condition
|
|
variables lists.
|