states configuration documentation + changes

Change-Id: I93266b0fe59436b53ffe76bbcb37f0b4734eff33
This commit is contained in:
Alexey Weyl 2016-03-03 07:59:01 +02:00
parent 60b92ca099
commit 9bac7830e2
14 changed files with 331 additions and 119 deletions

View File

@ -0,0 +1,95 @@
=========================
Alarm State Configuration
=========================
Configure Access to Alarm State
-------------------------------
The following should be set in **/etc/vitrage/vitrage.conf**, under entity_graph section:
+----------------------+------------------------------------+--------------------------------+
| Name | Description | Default Value |
+======================+====================================+================================+
| states_plugins_dir | Directory path from where to load | /etc/vitrage/states_plugins/ |
| | the states configurations | |
+----------------------+------------------------------------+--------------------------------+
Configure Alarm State Mapping
-----------------------------
Alarm state configuration is made to configure how states of specific alarm are normalized.
For each normalized state a priority is set as well, so that when alarm will have the original state and the Vitrage state, Vitrage will know what state is more important.
UNKNOWN state has to be configured in each alarm state configuration file.
The file name has to be in the same name as it's plugin name.
State configuration yaml file has to be defined for all the plugins which were chosen to be used in Vitrage.
**Format**
::
category: ALARM
states:
- normalized state:
name: <Normalized alarm state name - must be from NormalizedAlarmState class>
priority: <Alarm state priority - an integer>
original states:
- name: <Original alarm state name>
- name: <Original alarm state name>
- normalized state:
name: <Normalized alarm state name - must be from NormalizedAlarmState class>
priority: <Alarm state priority - an integer>
original states:
- name: <Original alarm state name>
- name: <Original alarm state name>
...
**Example**
The following file will map alarm states.
Original states 'CRITICAL' and 'DOWN' will be mapped to normalized state 'CRITICAL'.
Normalized state 'SEVER' has no original states.
Original state 'WARNING' is mapped to normalized state 'WARNING', etc.
::
category: ALARM
states:
- normalized state:
name: CRITICAL
priority: 50
original states:
- name: CRITITCAL
- name: DOWN
- normalized state:
name: SEVER
priority: 40
original states:
- normalized state:
name: WARNING
priority: 30
original states:
- name: WARNING
- normalized state:
name: UNKNOWN
priority: 20
original states:
- name: UNKNOWN
- normalized state:
name: OK
priority: 10
original states:
- name: OK
- name: UP
**Default Configuration**
Default configurations for alarms states will be installed with Vitrage.

View File

@ -0,0 +1,79 @@
============================
Resource State Configuration
============================
Configure Access to Resource State
----------------------------------
The following should be set in **/etc/vitrage/vitrage.conf**, under entity_graph section:
+----------------------+------------------------------------+--------------------------------+
| Name | Description | Default Value |
+======================+====================================+================================+
| states_plugins_dir | Directory path from where to load | /etc/vitrage/states_plugins/ |
| | the states configurations | |
+----------------------+------------------------------------+--------------------------------+
Configure Resource State Mapping
--------------------------------
Resource state configuration is made to configure how states of specific resource are normalized.
For each normalized state a priority is set as well, so that when resource will have the original state and the Vitrage state, Vitrage will know what state is more important.
UNRECOGNIZED state has to be configured in each resource state configuration file.
The file name has to be in the same name as it's plugin name.
State configuration yaml file has to be defined for all the plugins which were chosen to be used in Vitrage.
**Format**
::
category: RESOURCE
states:
- normalized state:
name: <Normalized resource state name - must be from NormalizedResourceState class>
priority: <Resource state priority - an integer>
original states:
- name: <Original resource state name>
- name: <Original resource state name>
- normalized state:
name: <Normalized resource state name - must be from NormalizedResourceState class>
priority: <Resource state priority - an integer>
original states:
- name: <Original resource state name>
- name: <Original resource state name>
...
**Example**
The following is mapping resource states.
Original states 'DELETED' and 'TERMINATED' will be mapped to normalized state 'TERMINATED'.
Original states 'ACTIVE' and 'RUNNING' to normalized state 'RUNNING'.
::
category: RESOURCE
states:
- normalized state:
name: TERMINATED
priority: 20
original states:
- name: DELETED
- name: TERMINATED
- normalized state:
name: RUNNING
priority: 10
original states:
- name: ACTIVE
- name: RUNNING
**Default Configuration**
Default configurations for resource states will be installed with Vitrage.

View File

@ -22,7 +22,7 @@ Physical configuration is made for configuring statically physical entities, and
Some physical entities, such as switches, can not be retrieved from OpenStack, so for now we will configure them statically.
There may be more than one configuration file. All files will be read from ...
There may be more than one configuration file. All files will be read from /etc/vitrage/static_plugins/.
**Format**
::

View File

@ -13,9 +13,10 @@
# under the License.
class AlarmState(object):
class NormalizedAlarmState(object):
CRITICAL = 'CRITICAL'
SEVER = 'SEVER'
WARNING = 'WARNING'
DISABLED = 'DISABLED'
UNKNOWN = 'UNKNOWN'
UNDEFINED = 'UNDEFINED'

View File

@ -13,20 +13,14 @@
# under the License.
class ResourceState(object):
class NormalizedResourceState(object):
TERMINATED = 'TERMINATED'
ERROR = 'ERROR'
UNRECOGNIZED = 'UNRECOGNIZED'
UNAVAILABLE = 'UNAVAILABLE'
SUSPENDED = 'SUSPENDED'
HIBERNATE = 'HIBERNATE'
PAUSED = 'PAUSED'
TERMINATING = 'TERMINATING'
SUSPENDING = 'SUSPENDING'
REBUILDING = 'REBUILDING'
STARTING = 'STARTING'
RESCUED = 'RESCUED'
RESIZED = 'RESIZED'
TRANSIENT = 'TRANSIENT'
SUBOPTIMAL = 'SUBOPTIMAL'
AVAILABLE = 'AVAILABLE'
RUNNING = 'RUNNING'
CREATING = 'CREATING'
UNDEFINED = 'UNDEFINED'

View File

@ -13,13 +13,14 @@
# under the License.
import os
import traceback
from oslo_log import log
from vitrage.common.constants import EntityCategory
from vitrage.common import file_utils
from vitrage.entity_graph.states.alarm_state import AlarmState
from vitrage.entity_graph.states.resource_state import ResourceState
from vitrage.entity_graph.states.alarm_state import NormalizedAlarmState
from vitrage.entity_graph.states.resource_state import NormalizedResourceState
LOG = log.getLogger(__name__)
@ -51,23 +52,19 @@ class StateManager(object):
def aggregated_state(self, state1, state2, plugin_name,
is_normalized=False):
if plugin_name in self.states_plugins:
upper_state1 = state1 if not state1 else state1.upper()
upper_state2 = state2 if not state2 else state2.upper()
normalized_state1, state_priority1 = \
self._find_normalized_state_and_priority(state1,
plugin_name,
is_normalized)
normalized_state2, state_priority2 = \
self._find_normalized_state_and_priority(state2,
plugin_name,
is_normalized)
normalized_state1 = upper_state1.upper() if is_normalized else \
self.normalize_state(plugin_name, upper_state1)
normalized_state2 = upper_state2.upper() if is_normalized else \
self.normalize_state(plugin_name, upper_state2)
priority_state1 = self.state_priority(plugin_name,
normalized_state1)
priority_state2 = self.state_priority(plugin_name,
normalized_state2)
return normalized_state1 if priority_state1 > priority_state2 \
return normalized_state1 if state_priority1 > state_priority2 \
else normalized_state2
else:
return ResourceState.UNDEFINED
return NormalizedResourceState.UNDEFINED
def _load_state_configurations(self):
states_plugins = {}
@ -76,15 +73,18 @@ class StateManager(object):
self.cfg.entity_graph.states_plugins_dir, '.yaml')
for file_name in files:
full_path = self.cfg.entity_graph.states_plugins_dir + '/' \
+ file_name
states, priorities, unknown_type = \
self._retrieve_states_and_priorities_from_file(full_path)
states_plugins[os.path.splitext(file_name)[0]] = {
self.STATES: states,
self.PRIORITIES: priorities,
self.UNKNOWN_TYPE: unknown_type
}
try:
full_path = self.cfg.entity_graph.states_plugins_dir + '/' \
+ file_name
states, priorities, unknown_type = \
self._retrieve_states_and_priorities_from_file(full_path)
states_plugins[os.path.splitext(file_name)[0]] = {
self.STATES: states,
self.PRIORITIES: priorities,
self.UNKNOWN_TYPE: unknown_type
}
except Exception:
LOG.error("Exception: %s", traceback.print_exc())
# TODO(Alexey): implement this after finishing implement load
# specific plugins from configuration
@ -120,14 +120,14 @@ class StateManager(object):
@staticmethod
def _add_default_states(states, priorities):
states[None] = ResourceState.UNDEFINED
priorities[ResourceState.UNDEFINED] = 0
states[None] = NormalizedResourceState.UNDEFINED
priorities[NormalizedResourceState.UNDEFINED] = 0
@staticmethod
def _init_category_unknown_type():
return {
EntityCategory.RESOURCE: ResourceState.UNRECOGNIZED,
EntityCategory.ALARM: AlarmState.UNKNOWN
EntityCategory.RESOURCE: NormalizedResourceState.UNRECOGNIZED,
EntityCategory.ALARM: NormalizedAlarmState.UNKNOWN
}
def _init_category_additional_data(self):
@ -138,12 +138,44 @@ class StateManager(object):
@staticmethod
def _resource_additional_states(states, priorities, full_path):
if ResourceState.UNRECOGNIZED not in priorities:
raise ValueError('%s state is not defined in %s',
ResourceState.UNRECOGNIZED, full_path)
StateManager._additional_states(states, priorities, full_path,
NormalizedResourceState.UNRECOGNIZED,
NormalizedResourceState())
@staticmethod
def _alarm_additional_states(states, priorities, full_path):
if AlarmState.UNKNOWN not in priorities:
StateManager._additional_states(states, priorities, full_path,
NormalizedAlarmState.UNKNOWN,
NormalizedAlarmState())
@staticmethod
def _additional_states(states, priorities, full_path,
unknown_state, state_class_instance):
if unknown_state not in priorities:
raise ValueError('%s state is not defined in %s',
AlarmState.UNKNOWN, full_path)
NormalizedAlarmState.UNKNOWN, full_path)
# check that all the normalized states exists
normalized_states = StateManager._get_all_local_variables_of_class(
state_class_instance)
for key in priorities.keys():
if key not in normalized_states:
raise ValueError('Normalized state %s for %s is not in %s',
key, full_path,
state_class_instance.__class__.__name__)
def _find_normalized_state_and_priority(self, state,
plugin_name, is_normalized):
upper_state1 = state if not state else state.upper()
normalized_state = upper_state1.upper() if is_normalized else \
self.normalize_state(plugin_name, upper_state1)
state_priority = self.state_priority(plugin_name, normalized_state)
return normalized_state, state_priority
@staticmethod
def _get_all_local_variables_of_class(class_instance):
return [attr for attr in dir(class_instance) if not callable(attr)
and not attr.startswith("__")]

View File

@ -19,7 +19,7 @@ from vitrage.common.constants import SyncMode
from vitrage.common.constants import VertexProperties as VProps
from vitrage.entity_graph.initialization_status import InitializationStatus
from vitrage.entity_graph.processor import processor as proc
from vitrage.entity_graph.states.resource_state import ResourceState
from vitrage.entity_graph.states.resource_state import NormalizedResourceState
from vitrage.synchronizer.plugins.nova.instance.transformer import \
InstanceTransformer
from vitrage.tests.functional.entity_graph.base import \
@ -46,7 +46,7 @@ class TestStateManagerFunctional(TestEntityGraphFunctionalBase):
instance_transformer = InstanceTransformer({})
vitrage_id = instance_transformer.extract_key(event)
vertex = processor.entity_graph.get_vertex(vitrage_id)
self.assertEqual(ResourceState.RUNNING,
self.assertEqual(NormalizedResourceState.RUNNING,
vertex[VProps.AGGREGATED_STATE])
def test_state_on_neighbor_update(self):
@ -65,5 +65,5 @@ class TestStateManagerFunctional(TestEntityGraphFunctionalBase):
# test assertions
neighbor_vertex = processor.entity_graph.get_vertex(
neighbors[0].vertex.vertex_id)
self.assertEqual(ResourceState.AVAILABLE,
self.assertEqual(NormalizedResourceState.RUNNING,
neighbor_vertex[VProps.AGGREGATED_STATE])

View File

@ -1,27 +1,27 @@
category: ALARM
states:
- normalized state:
name: UNKNOWN
priority: 50
original states:
- name: UNKNOWN
- normalized state:
name: CRITICAL
priority: 40
priority: 50
original states:
- name: CRITITCAL
- name: DOWN
- normalized state:
name: SEVER
priority: 30
priority: 40
original states:
- normalized state:
name: WARNING
priority: 20
priority: 30
original states:
- name: WARNING
- normalized state:
name: OK
name: UNKNOWN
priority: 20
original states:
- name: UNKNOWN
- normalized state:
name: DISABLED
priority: 10
original states:
- name: OK

View File

@ -2,25 +2,25 @@ category: RESOURCE
states:
- normalized state:
name: TERMINATED
priority: 150
priority: 50
original states:
- name: DELETED
- normalized state:
name: ERROR
priority: 140
priority: 40
original states:
- name: ERROR
- normalized state:
name: UNRECOGNIZED
priority: 130
priority: 30
original states:
- normalized state:
name: SUBOPTIMAL
priority: 40
priority: 20
original states:
- name: SUBOPTIMAL
- normalized state:
name: AVAILABLE
priority: 30
name: RUNNING
priority: 10
original states:
- name: available

View File

@ -2,45 +2,54 @@ category: RESOURCE
states:
- normalized state:
name: TERMINATED
priority: 150
priority: 90
original states:
- name: DELETED
- name: HARD_DELETED
- name: SHELVED_OFFLOADED
- name: SOFT_DELETED
- normalized state:
name: ERROR
priority: 140
priority: 80
original states:
- name: ERROR
- normalized state:
name: UNRECOGNIZED
priority: 130
priority: 70
original states:
- name: UNRECOGNIZED
- normalized state:
name: SUSPENDED
priority: 110
original states:
- name: SUSPENDED
- normalized state:
name: REBUILDING
priority: 60
original states:
- name: REBUILD
- name: SUSPENDED
- name: PAUSED
- name: STOPPED
- name: SHELVED
- normalized state:
name: STARTING
name: RESCUED
priority: 50
original states:
- name: VERIFY_RESIZE
- name: REVERT_RESIZE
- name: PASSWORD
- name: REBOOT
- name: BUILD
- name: HARD_REBOOT
- name: RESCUED
- normalized state:
name: RESIZED
priority: 40
original states:
- name: RESIZED
- normalized state:
name: TRANSIENT
priority: 30
original states:
- name: BUILDING
- name: INITIALIZED
- normalized state:
name: SUBOPTIMAL
priority: 40
priority: 20
original states:
- name: SUBOPTIMAL
- normalized state:
name: RUNNING
priority: 20
priority: 10
original states:
- name: ACTIVE
- name: RESIZED

View File

@ -2,25 +2,25 @@ category: RESOURCE
states:
- normalized state:
name: TERMINATED
priority: 150
priority: 50
original states:
- name: DELETED
- normalized state:
name: ERROR
priority: 140
priority: 40
original states:
- name: ERROR
- normalized state:
name: UNRECOGNIZED
priority: 130
priority: 30
original states:
- normalized state:
name: SUBOPTIMAL
priority: 40
priority: 20
original states:
- name: SUBOPTIMAL
- normalized state:
name: AVAILABLE
priority: 30
name: RUNNING
priority: 10
original states:
- name: available

View File

@ -2,25 +2,25 @@ category: RESOURCE
states:
- normalized state:
name: TERMINATED
priority: 150
priority: 50
original states:
- name: DELETED
- normalized state:
name: ERROR
priority: 140
priority: 40
original states:
- name: ERROR
- normalized state:
name: UNRECOGNIZED
priority: 130
priority: 30
original states:
- normalized state:
name: SUBOPTIMAL
priority: 40
priority: 20
original states:
- name: SUBOPTIMAL
- normalized state:
name: AVAILABLE
priority: 30
name: RUNNING
priority: 10
original states:
- name: available

View File

@ -23,7 +23,7 @@ from vitrage.common.constants import VertexProperties as VProps
from vitrage.common.datetime_utils import utcnow
from vitrage.entity_graph.initialization_status import InitializationStatus
from vitrage.entity_graph.processor import processor as proc
from vitrage.entity_graph.states.resource_state import ResourceState
from vitrage.entity_graph.states.resource_state import NormalizedResourceState
from vitrage.tests.unit.entity_graph.base import TestEntityGraphUnitBase
@ -176,7 +176,7 @@ class TestProcessor(TestEntityGraphUnitBase):
EventAction.UPDATE)
# vitrage state doesn't exist and its updated
del instances[1][0][VProps.STATE]
instances[1][0][VProps.STATE] = None
instances[1][1].entity_graph.update_vertex(instances[1][0])
instances[1][0][VProps.VITRAGE_STATE] = 'SUBOPTIMAL'
instances[1][1]._calculate_aggregated_state(instances[1][0],
@ -188,7 +188,7 @@ class TestProcessor(TestEntityGraphUnitBase):
EventAction.UPDATE)
# vitrage state exists and state changes
del instances[3][0][VProps.STATE]
instances[3][0][VProps.STATE] = None
instances[3][0][VProps.VITRAGE_STATE] = 'SUBOPTIMAL'
instances[3][1].entity_graph.update_vertex(instances[3][0])
instances[3][0][VProps.STATE] = 'SUSPENDED'
@ -209,17 +209,17 @@ class TestProcessor(TestEntityGraphUnitBase):
EventAction.UPDATE)
# test assertions
self.assertEqual(ResourceState.SUSPENDED,
self.assertEqual(NormalizedResourceState.SUSPENDED,
instances[0][0][VProps.AGGREGATED_STATE])
self.assertEqual(ResourceState.SUBOPTIMAL,
self.assertEqual(NormalizedResourceState.SUBOPTIMAL,
instances[1][0][VProps.AGGREGATED_STATE])
self.assertEqual(ResourceState.SUBOPTIMAL,
self.assertEqual(NormalizedResourceState.SUBOPTIMAL,
instances[2][0][VProps.AGGREGATED_STATE])
self.assertEqual(ResourceState.SUSPENDED,
self.assertEqual(NormalizedResourceState.SUSPENDED,
instances[3][0][VProps.AGGREGATED_STATE])
self.assertEqual(ResourceState.SUSPENDED,
self.assertEqual(NormalizedResourceState.SUSPENDED,
instances[4][0][VProps.AGGREGATED_STATE])
self.assertEqual(ResourceState.SUBOPTIMAL,
self.assertEqual(NormalizedResourceState.SUBOPTIMAL,
instances[5][0][VProps.AGGREGATED_STATE])
def _create_and_check_entity(self, properties={}):

View File

@ -14,7 +14,7 @@
from oslo_config import cfg
from vitrage.entity_graph.states.resource_state import ResourceState
from vitrage.entity_graph.states.resource_state import NormalizedResourceState
from vitrage.entity_graph.states.state_manager import StateManager
from vitrage.tests import base
from vitrage.tests.mocks import utils
@ -50,10 +50,10 @@ class TestStateManager(base.BaseTest):
# action
normalized_state = \
state_manager.normalize_state('nova.instance', 'REBUILD')
state_manager.normalize_state('nova.instance', 'BUILDING')
# test assertions
self.assertEqual(ResourceState.REBUILDING, normalized_state)
self.assertEqual(NormalizedResourceState.TRANSIENT, normalized_state)
def test_state_priority(self):
# setup
@ -62,10 +62,10 @@ class TestStateManager(base.BaseTest):
# action
state_priority = \
state_manager.state_priority('nova.instance',
ResourceState.REBUILDING)
NormalizedResourceState.RUNNING)
# test assertions
self.assertEqual(60, state_priority)
self.assertEqual(10, state_priority)
def test_aggregated_state_normalized(self):
# setup
@ -73,16 +73,18 @@ class TestStateManager(base.BaseTest):
# action
aggregated_state_nova_instance_1 = state_manager.aggregated_state(
ResourceState.REBUILDING, ResourceState.SUBOPTIMAL,
NormalizedResourceState.SUSPENDED,
NormalizedResourceState.SUBOPTIMAL,
'nova.instance', True)
aggregated_state_nova_instance_2 = state_manager.aggregated_state(
ResourceState.SUBOPTIMAL, ResourceState.REBUILDING,
NormalizedResourceState.SUBOPTIMAL,
NormalizedResourceState.SUSPENDED,
'nova.instance', True)
# test assertions
self.assertEqual(ResourceState.REBUILDING,
self.assertEqual(NormalizedResourceState.SUSPENDED,
aggregated_state_nova_instance_1)
self.assertEqual(ResourceState.REBUILDING,
self.assertEqual(NormalizedResourceState.SUSPENDED,
aggregated_state_nova_instance_2)
def test_aggregated_state_not_normalized(self):
@ -91,14 +93,14 @@ class TestStateManager(base.BaseTest):
# action
aggregated_state_nova_instance_1 = state_manager.aggregated_state(
'REBOOT', 'REBUILD', 'nova.instance')
'ACTIVE', 'SUSPENDED', 'nova.instance')
aggregated_state_nova_instance_2 = state_manager.aggregated_state(
'REBUILD', 'REBOOT', 'nova.instance')
'SUSPENDED', 'ACTIVE', 'nova.instance')
# test assertions
self.assertEqual(ResourceState.REBUILDING,
self.assertEqual(NormalizedResourceState.SUSPENDED,
aggregated_state_nova_instance_1)
self.assertEqual(ResourceState.REBUILDING,
self.assertEqual(NormalizedResourceState.SUSPENDED,
aggregated_state_nova_instance_2)
def test_aggregated_state_functionalities(self):
@ -114,9 +116,9 @@ class TestStateManager(base.BaseTest):
None, None, 'nova.instance')
# test assertions
self.assertEqual(ResourceState.RUNNING,
self.assertEqual(NormalizedResourceState.RUNNING,
aggregated_state_nova_instance_1)
self.assertEqual(ResourceState.RUNNING,
self.assertEqual(NormalizedResourceState.RUNNING,
aggregated_state_nova_instance_2)
self.assertEqual(ResourceState.UNDEFINED,
self.assertEqual(NormalizedResourceState.UNDEFINED,
aggregated_state_nova_instance_3)