Rearrange state_manager

Decouple the aggregated and operational values
Rename statemanager to datasource_info_mapper

Change-Id: Ied6220c08f10b6684e21dd22e011af246ec28d3
This commit is contained in:
Alexey Weyl 2016-05-25 08:26:41 +03:00
parent eafde06dbc
commit 7b21a4a985
41 changed files with 813 additions and 763 deletions

View File

@ -40,7 +40,7 @@ The alarm severity configuration files configure how the severity of each
alarm is normalized. There are several guidelines for creating a config file:
- Normalized alarm values which can be mapped to can be found in
normalized_alarm_severity.py (NormalizedAlarmSeverity class).
normalized_alarm_severity.py (OperationalAlarmSeverity class).
- Each normalized severity also comes with a priority, so
that if an alarm is given different severities from different sources (e.g.,
a host alarm raised both by nagios and Vitrage), the severity with the

View File

@ -40,7 +40,7 @@ The resource state configuration files configure how the state of each
resource is normalized. Some guidelines for creating a config file:
- Normalized state values, to which states should be mapped, can be found in
normalized_resource_state.py (NormalizedResourceState class).
normalized_resource_state.py (OperationalResourceState class).
- Each normalized state also comes with a priority, so
that if a resource is given different states from different sources (e.g.,
a host state set both by nagios and Vitrage), the state with the

View File

@ -1,28 +1,29 @@
category: ALARM
values:
- normalized value:
name: CRITICAL
priority: 50
original values:
- name: critical
- normalized value:
name: SEVERE
- aggregated values:
priority: 40
original values:
- name: moderate
- normalized value:
name: WARNING
- name: critical
operational_value: CRITICAL
- aggregated values:
priority: 30
original values:
- name: moderate
operational_value: SEVERE
- aggregated values:
priority: 20
original values:
- name: low
- normalized value:
name: UNKNOWN
operational_value: WARNING
- aggregated values:
priority: 20
original values:
- name: insufficient data
- normalized value:
name: DISABLED
operational_value: N/A
- aggregated values:
priority: 10
original values:
- name: OK
operational_value: OK
- name: UP
operational_value: OK

View File

@ -1,36 +1,40 @@
category: RESOURCE
values:
- normalized value:
name: ERROR
priority: 50
original values:
- name: ERROR
- name: ERROR_DELETING
- name: ERROR_RESTORING
- name: ERROR_EXTENDING
- normalized value:
name: UNRECOGNIZED
- aggregated values:
priority: 40
original values:
- name: UNRECOGNIZED
- normalized value:
name: TRANSIENT
- name: ERROR
operational_value: ERROR
- name: ERROR_DELETING
operational_value: ERROR
- name: ERROR_RESTORING
operational_value: ERROR
- name: ERROR_EXTENDING
operational_value: ERROR
- aggregated values:
priority: 30
original values:
- name: CREATING
operational_value: TRANSIENT
- name: ATTACHING
operational_value: TRANSIENT
- name: DELETING
operational_value: TRANSIENT
- name: RESTORING-BACKUP
operational_value: TRANSIENT
- name: BACKING-UP
operational_value: TRANSIENT
- name: DETACHING
- normalized value:
name: SUBOPTIMAL
operational_value: TRANSIENT
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: IN-USE
- name: AVAILABLE
operational_value: OK
- name: IN-USE
operational_value: OK

View File

@ -1,28 +1,26 @@
category: ALARM
values:
- normalized value:
name: CRITICAL
priority: 50
original values:
- name: CRITICAL
- name: DOWN
- normalized value:
name: SEVERE
- aggregated values:
priority: 40
original values:
- normalized value:
name: WARNING
- name: CRITICAL
operational_value: CRITICAL
- name: DOWN
operational_value: CRITICAL
- aggregated values:
priority: 30
original values:
- name: WARNING
- normalized value:
name: UNKNOWN
operational_value: WARNING
- aggregated values:
priority: 20
original values:
- name: UNKNOWN
- normalized value:
name: DISABLED
operational_value: N/A
- aggregated values:
priority: 10
original values:
- name: OK
operational_value: OK
- name: UP
operational_value: OK

View File

@ -1,32 +1,27 @@
category: RESOURCE
values:
- normalized value:
name: ERROR
priority: 60
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- aggregated values:
priority: 50
original values:
- name: UNRECOGNIZED
- normalized value:
name: SUSPENDED
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 40
original values:
- name: DOWN
- normalized value:
name: TRANSIENT
operational_value: ERROR
- aggregated values:
priority: 30
original values:
- name: BUILD
- normalized value:
name: SUBOPTIMAL
operational_value: TRANSIENT
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: ACTIVE
operational_value: OK

View File

@ -1,37 +1,32 @@
category: RESOURCE
values:
- normalized value:
name: ERROR
priority: 70
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- aggregated values:
priority: 60
original values:
- name: UNRECOGNIZED
- normalized value:
name: SUSPENDED
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 50
original values:
- name: DOWN
- normalized value:
name: TRANSIENT
operational_value: ERROR
- aggregated values:
priority: 40
original values:
- name: BUILD
- normalized value:
name: UNDEFINED
operational_value: TRANSIENT
- aggregated values:
priority: 30
original values:
- name: 'N/A'
- normalized value:
name: SUBOPTIMAL
operational_value: N/A
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: ACTIVE
operational_value: OK

View File

@ -1,26 +1,22 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 50
original values:
- name: DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 40
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- normalized value:
name: SUBOPTIMAL
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: available
- name: AVAILABLE
operational_value: OK

View File

@ -1,55 +1,56 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 90
original values:
- name: DELETED
- name: HARD_DELETED
- name: SHELVED_OFFLOADED
- name: SOFT_DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 80
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- name: HARD_DELETED
operational_value: DELETED
- name: SHELVED_OFFLOADED
operational_value: DELETED
- name: SOFT_DELETED
operational_value: DELETED
- aggregated values:
priority: 70
original values:
- name: UNRECOGNIZED
- normalized value:
name: SUSPENDED
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 60
original values:
- name: SUSPENDED
operational_value: SUBOPTIMAL
- name: PAUSED
operational_value: SUBOPTIMAL
- name: STOPPED
operational_value: SUBOPTIMAL
- name: SHELVED
- normalized value:
name: RESCUED
operational_value: SUBOPTIMAL
- aggregated values:
priority: 50
original values:
- name: RESCUED
- normalized value:
name: RESIZED
- name: RESIZED
operational_value: SUBOPTIMAL
- aggregated values:
priority: 40
original values:
- name: RESIZED
- normalized value:
name: TRANSIENT
- name: BUILDING
operational_value: TRANSIENT
- name: INITIALIZED
operational_value: TRANSIENT
- aggregated values:
priority: 30
original values:
- name: BUILDING
- name: INITIALIZED
- normalized value:
name: SUBOPTIMAL
- name: SUBOPTIMAL
operational_value: SUBOPTIMAL
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
- name: RESCUED
operational_value: OK
- aggregated values:
priority: 10
original values:
- name: ACTIVE
- name: RESIZED
operational_value: OK

View File

@ -1,26 +1,22 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 50
original values:
- name: DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 40
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- normalized value:
name: SUBOPTIMAL
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: available
- name: AVAILABLE
operational_value: OK

View File

@ -1,26 +1,22 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 50
original values:
- name: DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 40
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- normalized value:
name: SUBOPTIMAL
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: available
- name: AVAILABLE
operational_value: OK

View File

@ -1,6 +1,22 @@
category: RESOURCE
values:
- normalized value:
name: UNRECOGNIZED
- aggregated values:
priority: 40
original values:
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: AVAILABLE
operational_value: OK

View File

@ -1,26 +1,22 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 50
original values:
- name: DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 40
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- normalized value:
name: SUBOPTIMAL
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: available
operational_value: OK

View File

@ -1,27 +1,31 @@
category: ALARM
values:
- normalized value:
name: CRITICAL
- aggregated values:
priority: 50
original values:
- name: CRITICAL
- normalized value:
name: SEVERE
operational_value: CRITICAL
- aggregated values:
priority: 40
original values:
- name: SEVERE
- normalized value:
name: WARNING
operational_value: SEVERE
- name: MAJOR
operational_value: SEVERE
- aggregated values:
priority: 30
original values:
- name: WARNING
- normalized value:
name: UNKNOWN
operational_value: WARNING
- name: MINOR
operational_value: WARNING
- aggregated values:
priority: 20
original values:
- name: UNKNOWN
- normalized value:
name: DISABLED
operational_value: N/A
- aggregated values:
priority: 10
original values:
- name: OK
operational_value: OK

View File

@ -22,13 +22,15 @@ class VertexProperties(object):
STATE = 'state'
VITRAGE_STATE = 'vitrage_state'
AGGREGATED_STATE = 'aggregated_state'
OPERATIONAL_STATE = 'operational_state'
PROJECT_ID = 'project_id'
UPDATE_TIMESTAMP = 'update_timestamp'
SAMPLE_TIMESTAMP = 'sample_timestamp'
NAME = 'name'
IS_PLACEHOLDER = 'is_placeholder'
SEVERITY = 'severity'
NORMALIZED_SEVERITY = 'normalized_severity'
AGGREGATED_SEVERITY = 'aggregated_severity'
OPERATIONAL_SEVERITY = 'operational_severity'
VITRAGE_ID = 'vitrage_id'
INFO = 'info'
GRAPH_INDEX = 'graph_index'

View File

@ -0,0 +1,42 @@
# Copyright 2016 - Nokia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from vitrage.common.constants import VertexProperties as VProps
from vitrage.entity_graph.mappings.handler_base import HandlerBase
from vitrage.entity_graph.mappings.operational_alarm_severity \
import OperationalAlarmSeverity
class AlarmHandler(HandlerBase):
def __init__(self):
super(AlarmHandler, self).__init__()
def undefined_property(self):
return OperationalAlarmSeverity.NA
def value_properties(self):
return [VProps.SEVERITY]
def set_operational_value(self, new_vertex, operational_value):
new_vertex[VProps.OPERATIONAL_SEVERITY] = operational_value
def set_aggregated_value(self, new_vertex, aggregated_value):
new_vertex[VProps.AGGREGATED_SEVERITY] = aggregated_value
def default_values(self):
return [(None, OperationalAlarmSeverity.NA, 0)]
def get_value_class_instance(self):
return OperationalAlarmSeverity()

View File

@ -0,0 +1,225 @@
# Copyright 2016 - Nokia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
from oslo_log import log
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import VertexProperties as VProps
from vitrage.common import file_utils
from vitrage.entity_graph.mappings.alarm_handler import AlarmHandler
from vitrage.entity_graph.mappings.resource_handler import \
ResourceHandler
LOG = log.getLogger(__name__)
class DatasourceInfoMapper(object):
OPERATIONAL_VALUES = 'operational_values'
PRIORITY_VALUES = 'priority_values'
UNDEFINED_DATASOURCE = 'undefined datasource'
def __init__(self, conf):
self.conf = conf
self.category_normalizer = self._init_category_normalizer()
self.datasources_state_confs = self._load_state_configurations()
def operational_state(self, datasource_name, state):
return self._get_state_data(datasource_name,
state,
self.OPERATIONAL_VALUES)
def state_priority(self, datasource_name, state):
return self._get_state_data(datasource_name,
state,
self.PRIORITY_VALUES)
def aggregated_state(self, new_vertex, graph_vertex):
datasource_name = new_vertex[VProps.TYPE] if \
VProps.TYPE in new_vertex.properties else \
graph_vertex[VProps.TYPE]
category = new_vertex[VProps.CATEGORY] if \
VProps.CATEGORY in new_vertex.properties else \
graph_vertex[VProps.CATEGORY]
if datasource_name in self.datasources_state_confs:
value_properties = \
self.category_normalizer[category].value_properties()
operational_state, aggregated_state, state_priority = \
self._find_operational_state_and_priority(new_vertex,
graph_vertex,
value_properties[0],
datasource_name)
value_properties.pop(0)
for property_ in value_properties:
t_operational_state, t_aggregated_state, t_state_priority = \
self._find_operational_state_and_priority(new_vertex,
graph_vertex,
property_,
datasource_name)
if t_state_priority > state_priority:
operational_state = t_operational_state
aggregated_state = t_aggregated_state
state_priority = t_state_priority
self.category_normalizer[category].set_aggregated_value(
new_vertex, aggregated_state)
self.category_normalizer[category].set_operational_value(
new_vertex, operational_state)
else:
self.category_normalizer[category].set_aggregated_value(
new_vertex, self.UNDEFINED_DATASOURCE)
self.category_normalizer[category].set_operational_value(
new_vertex, self.UNDEFINED_DATASOURCE)
@staticmethod
def _init_category_normalizer():
return {
EntityCategory.RESOURCE: ResourceHandler(),
EntityCategory.ALARM: AlarmHandler()
}
def _load_state_configurations(self):
valid_datasources_conf = {}
erroneous_datasources_conf = []
files = file_utils.load_files(
self.conf.entity_graph.datasources_values_dir, '.yaml')
for file_name in files:
try:
full_path = self.conf.entity_graph.datasources_values_dir \
+ '/' + file_name
operational_values, priority_values = \
self._retrieve_states_and_priorities_from_file(full_path)
valid_datasources_conf[os.path.splitext(file_name)[0]] = {
self.OPERATIONAL_VALUES: operational_values,
self.PRIORITY_VALUES: priority_values
}
except Exception as e:
LOG.exception("Exception: %s", e)
datasource = os.path.splitext(file_name)[0]
LOG.error('erroneous data sources is %s',
erroneous_datasources_conf.append(datasource))
self._check_state_confs_exists(
[key for key in valid_datasources_conf.keys()],
erroneous_datasources_conf)
return valid_datasources_conf
def _retrieve_states_and_priorities_from_file(self, full_path):
states = {}
priorities = {}
config = file_utils.load_yaml_file(full_path, with_exception=True)
category = config['category']
for item in config['values']:
aggregated_values = item['aggregated values']
priority_value = int(aggregated_values['priority'])
# original to operational value
for original_state in aggregated_values['original values']:
original_value = original_state['name']
operational_value = original_state['operational_value']
states[original_value.upper()] = operational_value
priorities[original_value.upper()] = priority_value
self._check_validity(category, states, priorities, full_path)
self._add_default_states(states, priorities, category)
return states, priorities
def _add_default_states(self, states, priorities, category):
default_values = self.category_normalizer[category].default_values()
for original_val, operational_val, priority_val in default_values:
states[original_val] = operational_val
priorities[original_val] = priority_val
def _check_validity(self, category, states, priorities, full_path):
# check that all the operational values exists
state_class_instance = \
self.category_normalizer[category].get_value_class_instance()
operational_values = DatasourceInfoMapper.\
_get_all_local_variables_of_class(state_class_instance)
for operational_value in states.values():
if operational_value not in operational_values:
raise ValueError('operational value %s for %s is not in %s',
operational_value, full_path,
state_class_instance.__class__.__name__)
def _get_state_data(self, datasource_name, state, data_type):
try:
upper_state = state if not state else state.upper()
if datasource_name in self.datasources_state_confs:
values_conf = self.datasources_state_confs[
datasource_name][data_type]
return values_conf[upper_state] if upper_state in values_conf \
else values_conf[None]
else:
return self.UNDEFINED_DATASOURCE
except Exception:
LOG.error('Exception in datasource: %s', datasource_name)
raise
def _find_operational_state_and_priority(self,
new_vertex,
graph_vertex,
property_,
datasource_name):
state = self._get_updated_property(new_vertex,
graph_vertex,
property_)
upper_state = state if not state else state.upper()
operational_state = self.operational_state(datasource_name,
upper_state)
state_priority = self.state_priority(datasource_name,
upper_state)
return operational_state, upper_state, state_priority
@staticmethod
def _get_all_local_variables_of_class(class_instance):
return [getattr(class_instance, attr) for attr in dir(class_instance)
if not callable(attr) and not attr.startswith("__")]
def _check_state_confs_exists(self,
ok_datasources,
error_datasources):
datasource_types = self.conf.datasources.types
datasources_with_state_conf = ok_datasources + error_datasources
for datasource_type in datasource_types:
if datasource_type not in datasources_with_state_conf:
LOG.info("No state configuration file for: %s",
datasource_type)
@staticmethod
def _get_updated_property(new_vertex, graph_vertex, prop):
if new_vertex and prop in new_vertex.properties:
return new_vertex[prop]
elif graph_vertex and prop in graph_vertex.properties:
return graph_vertex[prop]
return None

View File

@ -13,40 +13,36 @@
# under the License.
import abc
from collections import namedtuple
import six
ImportantStates = namedtuple('ImportantStates', ['unknown', 'undefined'])
@six.add_metaclass(abc.ABCMeta)
class NormalizatorBase(object):
class HandlerBase(object):
def __init__(self):
pass
@abc.abstractmethod
def important_states(self):
def undefined_property(self):
pass
@abc.abstractmethod
def state_properties(self):
def value_properties(self):
pass
@abc.abstractmethod
def set_aggregated_state(self, new_vertex, normalized_state):
def set_aggregated_value(self, new_vertex, aggregated_value):
pass
@abc.abstractmethod
def set_undefined_state(self, new_vertex):
def set_operational_value(self, new_vertex, operational_value):
pass
@abc.abstractmethod
def default_states(self):
def default_values(self):
pass
@abc.abstractmethod
def get_state_class_instance(self):
def get_value_class_instance(self):
pass

View File

@ -13,10 +13,9 @@
# under the License.
class NormalizedAlarmSeverity(object):
class OperationalAlarmSeverity(object):
CRITICAL = 'CRITICAL'
SEVERE = 'SEVERE'
WARNING = 'WARNING'
DISABLED = 'DISABLED'
UNKNOWN = 'UNKNOWN'
UNDEFINED = 'UNDEFINED'
NA = 'N/A'
OK = 'OK'

View File

@ -13,14 +13,10 @@
# under the License.
class NormalizedResourceState(object):
TERMINATED = 'TERMINATED'
ERROR = 'ERROR'
UNRECOGNIZED = 'UNRECOGNIZED'
SUSPENDED = 'SUSPENDED'
RESCUED = 'RESCUED'
RESIZED = 'RESIZED'
class OperationalResourceState(object):
NA = 'N/A'
OK = 'OK'
TRANSIENT = 'TRANSIENT'
SUBOPTIMAL = 'SUBOPTIMAL'
RUNNING = 'RUNNING'
UNDEFINED = 'UNDEFINED'
ERROR = 'ERROR'
DELETED = 'DELETED'

View File

@ -0,0 +1,42 @@
# Copyright 2016 - Nokia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from vitrage.common.constants import VertexProperties as VProps
from vitrage.entity_graph.mappings.handler_base import HandlerBase
from vitrage.entity_graph.mappings.operational_resource_state \
import OperationalResourceState
class ResourceHandler(HandlerBase):
def __init__(self):
super(ResourceHandler, self).__init__()
def undefined_property(self):
return OperationalResourceState.NA
def value_properties(self):
return [VProps.STATE, VProps.VITRAGE_STATE]
def set_operational_value(self, new_vertex, operational_value):
new_vertex[VProps.OPERATIONAL_STATE] = operational_value
def set_aggregated_value(self, new_vertex, aggregated_value):
new_vertex[VProps.AGGREGATED_STATE] = aggregated_value
def default_values(self):
return [(None, OperationalResourceState.NA, 0)]
def get_value_class_instance(self):
return OperationalResourceState()

View File

@ -18,11 +18,12 @@ from oslo_log import log
from vitrage.common.constants import EventAction
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.transformer_base import TransformerBase
from vitrage.entity_graph.mappings.datasource_info_mapper import \
DatasourceInfoMapper
from vitrage.entity_graph.processor import base as processor
from vitrage.entity_graph.processor import entity_graph
from vitrage.entity_graph.processor.notifier import DeducedAlarmNotifier
from vitrage.entity_graph.processor import processor_utils as PUtils
from vitrage.entity_graph.states.state_manager import StateManager
from vitrage.entity_graph.transformer_manager import TransformerManager
from vitrage.graph import Direction
@ -35,7 +36,7 @@ class Processor(processor.ProcessorBase):
super(Processor, self).__init__()
self.conf = conf
self.transformer_manager = TransformerManager(self.conf)
self.state_manager = StateManager(self.conf)
self.state_manager = DatasourceInfoMapper(self.conf)
self._initialize_events_actions()
self.initialization_status = initialization_status
self.entity_graph = entity_graph.EntityGraph("Entity Graph") if \

View File

@ -1,45 +0,0 @@
# Copyright 2016 - Nokia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from vitrage.common.constants import VertexProperties as VProps
from vitrage.entity_graph.states.normalizator_base import ImportantStates
from vitrage.entity_graph.states.normalizator_base import NormalizatorBase
from vitrage.entity_graph.states.normalized_alarm_severity \
import NormalizedAlarmSeverity
class AlarmNormalizator(NormalizatorBase):
def __init__(self):
super(AlarmNormalizator, self).__init__()
def important_states(self):
return ImportantStates(NormalizedAlarmSeverity.UNKNOWN,
NormalizedAlarmSeverity.UNDEFINED)
def state_properties(self):
return [VProps.SEVERITY]
def set_aggregated_state(self, new_vertex, normalized_state):
new_vertex[VProps.NORMALIZED_SEVERITY] = normalized_state
def set_undefined_state(self, new_vertex):
new_vertex[VProps.NORMALIZED_SEVERITY] = \
NormalizedAlarmSeverity.UNDEFINED
def default_states(self):
return [(NormalizedAlarmSeverity.UNDEFINED, 0)]
def get_state_class_instance(self):
return NormalizedAlarmSeverity()

View File

@ -1,44 +0,0 @@
# Copyright 2016 - Nokia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from vitrage.common.constants import VertexProperties as VProps
from vitrage.entity_graph.states.normalizator_base import ImportantStates
from vitrage.entity_graph.states.normalizator_base import NormalizatorBase
from vitrage.entity_graph.states.normalized_resource_state \
import NormalizedResourceState
class ResourceNormalizator(NormalizatorBase):
def __init__(self):
super(ResourceNormalizator, self).__init__()
def important_states(self):
return ImportantStates(NormalizedResourceState.UNRECOGNIZED,
NormalizedResourceState.UNDEFINED)
def state_properties(self):
return [VProps.STATE, VProps.VITRAGE_STATE]
def set_undefined_state(self, new_vertex):
new_vertex[VProps.AGGREGATED_STATE] = NormalizedResourceState.UNDEFINED
def set_aggregated_state(self, new_vertex, normalized_state):
new_vertex[VProps.AGGREGATED_STATE] = normalized_state
def default_states(self):
return [(NormalizedResourceState.UNDEFINED, 0)]
def get_state_class_instance(self):
return NormalizedResourceState()

View File

@ -1,244 +0,0 @@
# Copyright 2016 - Nokia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
from oslo_log import log
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import VertexProperties as VProps
from vitrage.common import file_utils
from vitrage.entity_graph.states.alarm_normalizator import AlarmNormalizator
from vitrage.entity_graph.states.normalized_resource_state \
import NormalizedResourceState
from vitrage.entity_graph.states.resource_normalizator import \
ResourceNormalizator
LOG = log.getLogger(__name__)
class StateManager(object):
VALUES = 'values'
PRIORITIES = 'priorities'
def __init__(self, conf):
self.conf = conf
self.category_normalizator = self._init_category_normalizator()
self.datasources_state_confs = self._load_state_configurations()
def normalize_state(self, category, datasource_name, state):
try:
upper_state = state if not state else state.upper()
important_states = \
self.category_normalizator[category].important_states()
if datasource_name in self.datasources_state_confs:
states_conf = self.datasources_state_confs[datasource_name]
return states_conf[self.VALUES][upper_state] \
if upper_state in states_conf[self.VALUES] \
else states_conf[self.VALUES][important_states.unknown]
else:
return important_states.undefined
except Exception:
LOG.error('Exception in datasource: %s', datasource_name)
raise
def state_priority(self, datasource_name, normalized_state):
try:
# no need to check if normalized_state exists, cause it exists for
# sure
upper_state = normalized_state if not normalized_state else \
normalized_state.upper()
if datasource_name in self.datasources_state_confs:
states_conf = self.datasources_state_confs[datasource_name]
return states_conf[self.PRIORITIES][upper_state]
else:
# default UNDEFINED priority
return 0
except Exception:
LOG.error('Exception in datasource: %s', datasource_name)
raise
def aggregated_state(self, new_vertex, graph_vertex, is_normalized=False):
datasource_name = new_vertex[VProps.TYPE] if \
VProps.TYPE in new_vertex.properties else \
graph_vertex[VProps.TYPE]
category = new_vertex[VProps.CATEGORY] if \
VProps.CATEGORY in new_vertex.properties else \
graph_vertex[VProps.CATEGORY]
if datasource_name in self.datasources_state_confs:
state_properties = \
self.category_normalizator[category].state_properties()
normalized_state, state_priority = \
self._find_normalized_state_and_priority(new_vertex,
graph_vertex,
state_properties[0],
category,
datasource_name,
is_normalized)
state_properties.pop(0)
for property_ in state_properties:
tmp_normalized_state, tmp_state_priority = \
self._find_normalized_state_and_priority(new_vertex,
graph_vertex,
property_,
category,
datasource_name,
is_normalized)
if tmp_state_priority > state_priority:
normalized_state = tmp_normalized_state
state_priority = tmp_state_priority
self.category_normalizator[category].set_aggregated_state(
new_vertex, normalized_state)
else:
self.category_normalizator[category].set_undefined_state(
new_vertex)
@staticmethod
def _init_category_normalizator():
return {
EntityCategory.RESOURCE: ResourceNormalizator(),
EntityCategory.ALARM: AlarmNormalizator()
}
def _load_state_configurations(self):
ok_datasources = {}
erroneous_datasources = []
files = file_utils.load_files(
self.conf.entity_graph.datasources_values_dir, '.yaml')
for file_name in files:
try:
full_path = self.conf.entity_graph.datasources_values_dir \
+ '/' + file_name
states, priorities = \
self._retrieve_states_and_priorities_from_file(full_path)
ok_datasources[os.path.splitext(file_name)[0]] = {
self.VALUES: states,
self.PRIORITIES: priorities
}
except Exception as e:
LOG.exception("Exception: %s", e)
datasource = os.path.splitext(file_name)[0]
LOG.error('erroneous data sources is %s',
erroneous_datasources.append(datasource))
self._check_state_confs_exists(
[key for key in ok_datasources.keys()],
erroneous_datasources)
return ok_datasources
def _retrieve_states_and_priorities_from_file(self, full_path):
states = {}
priorities = {}
config = file_utils.load_yaml_file(full_path, with_exception=True)
category = config['category']
for item in config[self.VALUES]:
normalized_state = item['normalized value']
# original to normalized value
normalized_state_name = normalized_state['name']
for original_state in normalized_state['original values']:
states[original_state['name'].upper()] = normalized_state_name
self._add_default_states(states, priorities, category)
# normalized value priority
priorities[normalized_state_name] = \
int(normalized_state['priority'])
self.check_validity(category, priorities, full_path)
return states, priorities
def _add_default_states(self, states, priorities, category):
default_values = self.category_normalizator[category].default_states()
for state, priority in default_values:
states[None] = state
priorities[NormalizedResourceState.UNDEFINED] = priority
def check_validity(self, category, priorities, full_path):
important_states = \
self.category_normalizator[category].important_states()
if important_states.unknown not in priorities:
raise ValueError('%s state is not defined in %s',
important_states.unknown, full_path)
# check that all the normalized values exists
state_class_instance = \
self.category_normalizator[category].get_state_class_instance()
normalized_values = StateManager._get_all_local_variables_of_class(
state_class_instance)
for key in priorities.keys():
if key not in normalized_values:
raise ValueError('normalized value %s for %s is not in %s',
key, full_path,
state_class_instance.__class__.__name__)
def _find_normalized_state_and_priority(self,
new_vertex,
graph_vertex,
property_,
category,
datasource_name,
is_normalized=False):
state = self._get_updated_property(new_vertex,
graph_vertex,
property_)
upper_state1 = state if not state else state.upper()
normalized_state = upper_state1 if is_normalized else \
self.normalize_state(category, datasource_name, upper_state1)
state_priority = self.state_priority(datasource_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("__")]
def _check_state_confs_exists(self,
ok_datasources,
error_datasources):
datasource_types = self.conf.datasources.types
datasources_with_state_conf = ok_datasources + error_datasources
for datasource_type in datasource_types:
if datasource_type not in datasources_with_state_conf:
LOG.info("No state configuration file for: %s",
datasource_type)
@staticmethod
def _get_updated_property(new_vertex, graph_vertex, prop):
if new_vertex and prop in new_vertex.properties:
return new_vertex[prop]
elif graph_vertex and prop in graph_vertex.properties:
return graph_vertex[prop]
return None

View File

@ -17,8 +17,8 @@ from vitrage import clients
from vitrage.common.constants import NotifierEventTypes
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.aodh.properties import AodhState
from vitrage.entity_graph.states.normalized_alarm_severity import \
NormalizedAlarmSeverity
from vitrage.entity_graph.mappings.operational_alarm_severity import \
OperationalAlarmSeverity
from vitrage.notifier.plugins.base import NotifierBase
@ -26,9 +26,9 @@ LOG = logging.getLogger(__name__)
severity_translation = {
NormalizedAlarmSeverity.CRITICAL: 'critical',
NormalizedAlarmSeverity.SEVERE: 'moderate',
NormalizedAlarmSeverity.WARNING: 'low',
OperationalAlarmSeverity.CRITICAL: 'critical',
OperationalAlarmSeverity.SEVERE: 'moderate',
OperationalAlarmSeverity.WARNING: 'low',
}

View File

@ -19,18 +19,18 @@ from vitrage.common.constants import SyncMode
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.nova.instance.transformer import InstanceTransformer
from vitrage.entity_graph.initialization_status import InitializationStatus
from vitrage.entity_graph.mappings.operational_resource_state import \
OperationalResourceState
from vitrage.entity_graph.processor import processor as proc
from vitrage.entity_graph.states.normalized_resource_state import \
NormalizedResourceState
from vitrage.tests.functional.base import TestFunctionalBase
class TestStateManagerFunctional(TestFunctionalBase):
class TestDatasourceInfoMapperFunctional(TestFunctionalBase):
# noinspection PyAttributeOutsideInit,PyPep8Naming
@classmethod
def setUpClass(cls):
super(TestStateManagerFunctional, cls).setUpClass()
super(TestDatasourceInfoMapperFunctional, cls).setUpClass()
cls.conf = cfg.ConfigOpts()
cls.conf.register_opts(cls.PROCESSOR_OPTS, group='entity_graph')
cls.conf.register_opts(cls.DATASOURCES_OPTS, group='datasources')
@ -49,8 +49,9 @@ class TestStateManagerFunctional(TestFunctionalBase):
instance_transformer = InstanceTransformer({})
vitrage_id = instance_transformer._create_entity_key(event)
vertex = processor.entity_graph.get_vertex(vitrage_id)
self.assertEqual(NormalizedResourceState.RUNNING,
vertex[VProps.AGGREGATED_STATE])
self.assertEqual('ACTIVE', vertex[VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.OK,
vertex[VProps.OPERATIONAL_STATE])
def test_state_on_neighbor_update(self):
# setup
@ -68,5 +69,6 @@ class TestStateManagerFunctional(TestFunctionalBase):
# test assertions
neighbor_vertex = processor.entity_graph.get_vertex(
neighbors[0].vertex.vertex_id)
self.assertEqual(NormalizedResourceState.RUNNING,
neighbor_vertex[VProps.AGGREGATED_STATE])
self.assertEqual('AVAILABLE', neighbor_vertex[VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.OK,
neighbor_vertex[VProps.OPERATIONAL_STATE])

View File

@ -23,8 +23,8 @@ from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.alarm_properties import AlarmProperties as AlarmProps
from vitrage.datasources.nagios import NAGIOS_DATASOURCE
from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
from vitrage.entity_graph.states.normalized_resource_state import \
NormalizedResourceState
from vitrage.entity_graph.mappings.operational_resource_state import \
OperationalResourceState
from vitrage.evaluator.actions.action_executor import ActionExecutor
from vitrage.evaluator.actions.base import ActionMode
from vitrage.evaluator.actions.base import ActionType
@ -62,7 +62,7 @@ class TestActionExecutor(TestFunctionalBase):
host_vertex_before = host_vertices[0]
targets = {TFields.TARGET: host_vertex_before}
props = {TFields.STATE: NormalizedResourceState.SUBOPTIMAL}
props = {TFields.STATE: OperationalResourceState.SUBOPTIMAL}
action_spec = ActionSpecs(ActionType.SET_STATE, targets, props)
event_queue = queue.Queue()
@ -77,13 +77,14 @@ class TestActionExecutor(TestFunctionalBase):
# Test Assertions
agg_state_before = host_vertex_before.get(VProps.AGGREGATED_STATE)
self.assertTrue(agg_state_before != NormalizedResourceState.SUBOPTIMAL)
self.assertTrue(agg_state_before !=
OperationalResourceState.SUBOPTIMAL)
self.assertFalse(VProps.VITRAGE_STATE in host_vertex_before.properties)
agg_state_after = host_vertex_after.get(VProps.AGGREGATED_STATE)
self.assertEqual(agg_state_after, NormalizedResourceState.SUBOPTIMAL)
self.assertEqual(agg_state_after, OperationalResourceState.SUBOPTIMAL)
v_state_after = host_vertex_after.get(VProps.VITRAGE_STATE)
self.assertEqual(v_state_after, NormalizedResourceState.SUBOPTIMAL)
self.assertEqual(v_state_after, OperationalResourceState.SUBOPTIMAL)
# Test Action - undo
action_executor.execute(action_spec, ActionMode.UNDO)
@ -197,10 +198,11 @@ class TestActionExecutor(TestFunctionalBase):
self.assertEqual(alarm.properties[VProps.CATEGORY],
EntityCategory.ALARM)
self.assertEqual(alarm.properties[VProps.TYPE], VITRAGE_TYPE)
self.assertEqual(alarm.properties[VProps.TYPE],
VITRAGE_TYPE)
self.assertEqual(alarm.properties[VProps.SEVERITY],
props[TFields.SEVERITY])
self.assertEqual(alarm.properties[VProps.NORMALIZED_SEVERITY],
self.assertEqual(alarm.properties[VProps.OPERATIONAL_SEVERITY],
props[TFields.SEVERITY])
self.assertEqual(alarm.properties[VProps.STATE],
AlarmProps.ALARM_ACTIVE_STATE)

View File

@ -62,7 +62,7 @@ class TestScenarioEvaluator(TestFunctionalBase):
target_host = 'host-2'
host_v = self._get_host_from_graph(target_host, processor.entity_graph)
self.assertEqual('RUNNING', host_v[VProps.AGGREGATED_STATE],
self.assertEqual('AVAILABLE', host_v[VProps.AGGREGATED_STATE],
'host should be RUNNING when starting')
nagios_event = {'last_check': '2016-02-07 15:26:04',
@ -89,7 +89,7 @@ class TestScenarioEvaluator(TestFunctionalBase):
processor.process_event(event_queue.get())
host_v = self._get_host_from_graph(target_host, processor.entity_graph)
self.assertEqual('RUNNING', host_v[VProps.AGGREGATED_STATE],
self.assertEqual('AVAILABLE', host_v[VProps.AGGREGATED_STATE],
'host should be RUNNING when starting')
@staticmethod

View File

@ -1,28 +1,28 @@
category: ALARM
values:
- normalized value:
name: CRITICAL
priority: 50
original values:
- name: CRITICAL
- name: DOWN
- normalized value:
name: SEVERE
- aggregated values:
priority: 40
original values:
- normalized value:
name: WARNING
- name: CRITICAL
operational_value: CRITICAL
- name: DOWN
operational_value: CRITICAL
- aggregated values:
priority: 30
original values:
- name: WARNING
- normalized value:
name: UNKNOWN
operational_value: WARNING
- aggregated values:
priority: 20
original values:
- name: UNKNOWN
- normalized value:
name: DISABLED
operational_value: N/A
- name: UNDEFINED
operational_value: N/A
- aggregated values:
priority: 10
original values:
- name: OK
operational_value: OK
- name: UP
operational_value: OK

View File

@ -1,23 +1,22 @@
# erroneous yaml file - missing normalized UNRECOGNIZED value
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 50
original values:
- name: DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 40
original values:
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- name: ERROR
- normalized value:
name: SUBOPTIMAL
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: available
- name: AVAILABLE
operational_value: OK

View File

@ -1,56 +1,57 @@
# erroneous yaml file - parsing error in DELETED value
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 90
original values:
- name: DELETED
- name: HARD_DELETED
- name: SHELVED_OFFLOADED
- name: SOFT_DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 80
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- name: HARD_DELETED
operational_value: DELETED
- name: SHELVED_OFFLOADED
operational_value: DELETED
- name: SOFT_DELETED
operational_value: DELETED
- aggregated values:
priority: 70
original values:
- name: UNRECOGNIZED
- normalized value:
name: SUSPENDED
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 60
original values:
- name: SUSPENDED
operational_value: SUBOPTIMAL
- name: PAUSED
operational_value: SUBOPTIMAL
- name: STOPPED
operational_value: SUBOPTIMAL
- name: SHELVED
- normalized value:
name: RESCUED
operational_value: SUBOPTIMAL
- aggregated values:
priority: 50
original values:
- name: RESCUED
- normalized value:
name: RESIZED
- name: RESIZED
operational_value: SUBOPTIMAL
- aggregated values:
priority: 40
original values:
- name: RESIZED
- normalized value:
name: TRANSIENT
- name: BUILDING
operational_value: TRANSIENT
- name: INITIALIZED
operational_value: TRANSIENT
- aggregated values:
priority: 30
original values:
- name: BUILDING
- name: INITIALIZED
- normalized value:
name: SUBOPTIMAL
- name: SUBOPTIMAL
operational_value: SUBOPTIMAL
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
- name: RESCUED
operational_value: OK
- aggregated values:
priority: 10
original values:
- name: ACTIVE
- name: RESIZED
operational_value: OK

View File

@ -1,28 +1,26 @@
category: ALARM
values:
- normalized value:
name: CRITICAL
priority: 50
original values:
- name: CRITICAL
- name: DOWN
- normalized value:
name: SEVERE
- aggregated values:
priority: 40
original values:
- normalized value:
name: WARNING
- name: CRITICAL
operational_value: CRITICAL
- name: DOWN
operational_value: CRITICAL
- aggregated values:
priority: 30
original values:
- name: WARNING
- normalized value:
name: UNKNOWN
operational_value: WARNING
- aggregated values:
priority: 20
original values:
- name: UNKNOWN
- normalized value:
name: DISABLED
operational_value: N/A
- aggregated values:
priority: 10
original values:
- name: OK
operational_value: OK
- name: UP
operational_value: OK

View File

@ -1,26 +1,22 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 50
original values:
- name: DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 40
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- normalized value:
name: SUBOPTIMAL
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: available
- name: AVAILABLE
operational_value: OK

View File

@ -1,55 +1,56 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 90
original values:
- name: DELETED
- name: HARD_DELETED
- name: SHELVED_OFFLOADED
- name: SOFT_DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 80
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- name: HARD_DELETED
operational_value: DELETED
- name: SHELVED_OFFLOADED
operational_value: DELETED
- name: SOFT_DELETED
operational_value: DELETED
- aggregated values:
priority: 70
original values:
- name: UNRECOGNIZED
- normalized value:
name: SUSPENDED
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 60
original values:
- name: SUSPENDED
operational_value: SUBOPTIMAL
- name: PAUSED
operational_value: SUBOPTIMAL
- name: STOPPED
operational_value: SUBOPTIMAL
- name: SHELVED
- normalized value:
name: RESCUED
operational_value: SUBOPTIMAL
- aggregated values:
priority: 50
original values:
- name: RESCUED
- normalized value:
name: RESIZED
- name: RESIZED
operational_value: SUBOPTIMAL
- aggregated values:
priority: 40
original values:
- name: RESIZED
- normalized value:
name: TRANSIENT
- name: BUILDING
operational_value: TRANSIENT
- name: INITIALIZED
operational_value: TRANSIENT
- aggregated values:
priority: 30
original values:
- name: BUILDING
- name: INITIALIZED
- normalized value:
name: SUBOPTIMAL
- name: SUBOPTIMAL
operational_value: SUBOPTIMAL
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
- name: RESCUED
operational_value: OK
- aggregated values:
priority: 10
original values:
- name: ACTIVE
- name: RESIZED
operational_value: OK

View File

@ -1,26 +1,22 @@
category: RESOURCE
values:
- normalized value:
name: TERMINATED
priority: 50
original values:
- name: DELETED
- normalized value:
name: ERROR
- aggregated values:
priority: 40
original values:
- name: ERROR
- normalized value:
name: UNRECOGNIZED
- name: DELETED
operational_value: DELETED
- aggregated values:
priority: 30
original values:
- normalized value:
name: SUBOPTIMAL
- name: ERROR
operational_value: ERROR
- aggregated values:
priority: 20
original values:
- name: SUBOPTIMAL
- normalized value:
name: RUNNING
operational_value: SUBOPTIMAL
- aggregated values:
priority: 10
original values:
- name: available
- name: AVAILABLE
operational_value: OK

View File

@ -1,29 +1,31 @@
category: ALARM
values:
- normalized value:
name: CRITICAL
- aggregated values:
priority: 50
original values:
- name: CRITICAL
- normalized value:
name: SEVERE
operational_value: CRITICAL
- aggregated values:
priority: 40
original values:
- name: SEVERE
operational_value: SEVERE
- name: MAJOR
- normalized value:
name: WARNING
operational_value: SEVERE
- aggregated values:
priority: 30
original values:
- name: WARNING
operational_value: WARNING
- name: MINOR
- normalized value:
name: UNKNOWN
operational_value: WARNING
- aggregated values:
priority: 20
original values:
- name: UNKNOWN
- normalized value:
name: DISABLED
operational_value: N/A
- aggregated values:
priority: 10
original values:
- name: OK
operational_value: OK

View File

@ -21,9 +21,9 @@ from vitrage.common.constants import VertexProperties as VProps
from vitrage.common.datetime_utils import utcnow
from vitrage.datasources.transformer_base import Neighbor
from vitrage.entity_graph.initialization_status import InitializationStatus
from vitrage.entity_graph.mappings.operational_resource_state import \
OperationalResourceState
from vitrage.entity_graph.processor import processor as proc
from vitrage.entity_graph.states.normalized_resource_state import \
NormalizedResourceState
import vitrage.graph.utils as graph_utils
from vitrage.tests.unit.entity_graph.base import TestEntityGraphUnitBase
@ -273,18 +273,30 @@ class TestProcessor(TestEntityGraphUnitBase):
EventAction.UPDATE_ENTITY)
# test assertions
self.assertEqual(NormalizedResourceState.SUSPENDED,
self.assertEqual('SUSPENDED',
instances[0][0][VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.SUBOPTIMAL,
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
instances[0][0][VProps.OPERATIONAL_STATE])
self.assertEqual('SUBOPTIMAL',
instances[1][0][VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.SUBOPTIMAL,
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
instances[1][0][VProps.OPERATIONAL_STATE])
self.assertEqual('SUBOPTIMAL',
instances[2][0][VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.SUSPENDED,
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
instances[2][0][VProps.OPERATIONAL_STATE])
self.assertEqual('SUSPENDED',
instances[3][0][VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.SUSPENDED,
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
instances[3][0][VProps.OPERATIONAL_STATE])
self.assertEqual('SUSPENDED',
instances[4][0][VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.SUBOPTIMAL,
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
instances[4][0][VProps.OPERATIONAL_STATE])
self.assertEqual('SUBOPTIMAL',
instances[5][0][VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
instances[5][0][VProps.OPERATIONAL_STATE])
def _create_and_check_entity(self, processor=None, **kwargs):
# create instance event with host neighbor

View File

@ -20,16 +20,17 @@ from vitrage.datasources.nagios import NAGIOS_DATASOURCE
from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
from vitrage.datasources.nova.zone import NOVA_ZONE_DATASOURCE
from vitrage.entity_graph.states.normalized_resource_state import \
NormalizedResourceState
from vitrage.entity_graph.states.state_manager import StateManager
from vitrage.entity_graph.mappings.datasource_info_mapper import \
DatasourceInfoMapper
from vitrage.entity_graph.mappings.operational_resource_state import \
OperationalResourceState
from vitrage.graph.utils import create_vertex
from vitrage.service import load_datasource
from vitrage.tests import base
from vitrage.tests.mocks import utils
class TestStateManager(base.BaseTest):
class TestDatasourceInfoMapper(base.BaseTest):
ENTITY_GRAPH_OPTS = [
cfg.StrOpt('datasources_values_dir',
@ -57,7 +58,7 @@ class TestStateManager(base.BaseTest):
# noinspection PyAttributeOutsideInit,PyPep8Naming
@classmethod
def setUpClass(cls):
super(TestStateManager, cls).setUpClass()
super(TestDatasourceInfoMapper, cls).setUpClass()
cls.conf = cfg.ConfigOpts()
cls.conf.register_opts(cls.ENTITY_GRAPH_OPTS, group='entity_graph')
cls.conf.register_opts(cls.DATASOURCES_OPTS, group='datasources')
@ -65,7 +66,7 @@ class TestStateManager(base.BaseTest):
def test_load_datasource_state_without_errors(self):
# action
state_manager = StateManager(self.conf)
state_manager = DatasourceInfoMapper(self.conf)
# test assertions
@ -87,44 +88,92 @@ class TestStateManager(base.BaseTest):
self._load_datasources(conf)
# action
state_manager = StateManager(conf)
state_manager = DatasourceInfoMapper(conf)
# test assertions
missing_states = 1
erroneous_values = 2
erroneous_values = 1
num_valid_datasources = len(state_manager.datasources_state_confs) + \
missing_states + erroneous_values
self.assertEqual(len(conf.datasources.types),
num_valid_datasources)
self.assertEqual(num_valid_datasources, len(conf.datasources.types))
def test_normalize_state(self):
def test_operational_state_exists(self):
# setup
state_manager = StateManager(self.conf)
state_manager = DatasourceInfoMapper(self.conf)
# action
normalized_state = \
state_manager.normalize_state(EntityCategory.RESOURCE,
NOVA_INSTANCE_DATASOURCE,
operational_state = \
state_manager.operational_state(NOVA_INSTANCE_DATASOURCE,
'BUILDING')
# test assertions
self.assertEqual(NormalizedResourceState.TRANSIENT, normalized_state)
self.assertEqual(OperationalResourceState.TRANSIENT, operational_state)
def test_operational_state_not_exists(self):
# setup
state_manager = DatasourceInfoMapper(self.conf)
# action
operational_state = \
state_manager.operational_state(NOVA_INSTANCE_DATASOURCE,
'NON EXISTING STATE')
# test assertions
self.assertEqual(OperationalResourceState.NA, operational_state)
def test_operational_state_datasource_not_exists(self):
# setup
state_manager = DatasourceInfoMapper(self.conf)
# action
operational_state = \
state_manager.operational_state('NON EXISTING DATASOURCE',
'BUILDING')
# test assertions
self.assertEqual(DatasourceInfoMapper.UNDEFINED_DATASOURCE,
operational_state)
def test_state_priority(self):
# setup
state_manager = StateManager(self.conf)
state_manager = DatasourceInfoMapper(self.conf)
# action
state_priority = \
state_manager.state_priority(NOVA_INSTANCE_DATASOURCE,
NormalizedResourceState.RUNNING)
'ACTIVE')
# test assertions
self.assertEqual(10, state_priority)
def test_aggregated_state_not_normalized(self):
def test_state_priority_not_exists(self):
# setup
state_manager = StateManager(self.conf)
state_manager = DatasourceInfoMapper(self.conf)
# action
state_priority = \
state_manager.state_priority(NOVA_INSTANCE_DATASOURCE,
'NON EXISTING STATE')
# test assertions
self.assertEqual(0, state_priority)
def test_state_priority_datasource_not_exists(self):
# setup
state_manager = DatasourceInfoMapper(self.conf)
# action
state_priority = \
state_manager.state_priority('NON EXISTING DATASOURCE',
'ACTIVE')
# test assertions
self.assertEqual(DatasourceInfoMapper.UNDEFINED_DATASOURCE,
state_priority)
def test_aggregated_state(self):
# setup
state_manager = DatasourceInfoMapper(self.conf)
metadata1 = {VProps.VITRAGE_STATE: 'SUSPENDED'}
new_vertex1 = create_vertex('12345',
entity_state='ACTIVE',
@ -143,14 +192,16 @@ class TestStateManager(base.BaseTest):
state_manager.aggregated_state(new_vertex2, None)
# test assertions
self.assertEqual(NormalizedResourceState.SUSPENDED,
new_vertex1[VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.SUSPENDED,
new_vertex2[VProps.AGGREGATED_STATE])
self.assertEqual('SUSPENDED', new_vertex1[VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
new_vertex1[VProps.OPERATIONAL_STATE])
self.assertEqual('SUSPENDED', new_vertex2[VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
new_vertex2[VProps.OPERATIONAL_STATE])
def test_aggregated_state_functionalities(self):
# setup
state_manager = StateManager(self.conf)
state_manager = DatasourceInfoMapper(self.conf)
new_vertex1 = create_vertex('12345',
entity_state='ACTIVE',
entity_category=EntityCategory.RESOURCE,
@ -160,12 +211,16 @@ class TestStateManager(base.BaseTest):
entity_category=EntityCategory.RESOURCE,
entity_type=NOVA_INSTANCE_DATASOURCE,
metadata=metadata2)
metadata3 = {VProps.VITRAGE_STATE: 'SUBOPTIMAL'}
new_vertex3 = create_vertex('34567',
entity_state='ACTIVE',
entity_category=EntityCategory.RESOURCE,
entity_type=NOVA_INSTANCE_DATASOURCE)
graph_vertex3 = create_vertex('45678',
graph_vertex3 = create_vertex('34567',
entity_state='SUSPENDED',
entity_category=EntityCategory.RESOURCE,
entity_type=NOVA_INSTANCE_DATASOURCE)
entity_type=NOVA_INSTANCE_DATASOURCE,
metadata=metadata3)
# action
state_manager.aggregated_state(new_vertex1,
@ -176,9 +231,31 @@ class TestStateManager(base.BaseTest):
graph_vertex3)
# test assertions
self.assertEqual(NormalizedResourceState.RUNNING,
new_vertex1[VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.SUBOPTIMAL,
new_vertex2[VProps.AGGREGATED_STATE])
self.assertEqual(NormalizedResourceState.UNDEFINED,
new_vertex3[VProps.AGGREGATED_STATE])
self.assertEqual('ACTIVE', new_vertex1[VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.OK,
new_vertex1[VProps.OPERATIONAL_STATE])
self.assertEqual('SUBOPTIMAL', new_vertex2[VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
new_vertex2[VProps.OPERATIONAL_STATE])
self.assertEqual('SUBOPTIMAL', new_vertex3[VProps.AGGREGATED_STATE])
self.assertEqual(OperationalResourceState.SUBOPTIMAL,
new_vertex3[VProps.OPERATIONAL_STATE])
def test_aggregated_state_datasource_not_exists(self):
# setup
state_manager = DatasourceInfoMapper(self.conf)
metadata = {VProps.VITRAGE_STATE: 'SUSPENDED'}
new_vertex = create_vertex('12345',
entity_state='ACTIVE',
entity_category=EntityCategory.RESOURCE,
entity_type='NON EXISTING DATASOURCE',
metadata=metadata)
# action
state_manager.aggregated_state(new_vertex, None)
# test assertions
self.assertEqual(DatasourceInfoMapper.UNDEFINED_DATASOURCE,
new_vertex[VProps.AGGREGATED_STATE])
self.assertEqual(DatasourceInfoMapper.UNDEFINED_DATASOURCE,
new_vertex[VProps.OPERATIONAL_STATE])

View File

@ -67,18 +67,14 @@ def run_vitrage_command(command, conf):
project_name_param, auth_url_param)
LOG.info('Full command: %s', full_command)
p = subprocess.Popen(full_command,
shell=True,
executable="/bin/bash",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if stderr != '':
LOG.error("The command output error is : " + stderr)
if stdout != '':
LOG.debug("The command output is : \n" + stdout)
return stdout
return None
def get_property_value(environment_name, conf_name, default_value, conf):