From c9b93cbdccedb9b000d647673e27331e7ea35259 Mon Sep 17 00:00:00 2001 From: Anna Reznikov Date: Tue, 6 Jun 2017 14:09:27 +0000 Subject: [PATCH] for ML - add resource details: id and type to alarms this was done by adding type and category to alarms neighbors in raise_alarm and evaluator_event_transformer, and using it later in the processor. the tests also was modified accordingly. those detailes will be needed later to recognize alarm uniquely in order to compute the total time an alarms was active. Change-Id: Id6db43de1595d2bf73db5a4db83472e6c2a14a8e --- vitrage/api_handler/apis/alarm.py | 2 - vitrage/api_handler/apis/base.py | 20 -------- vitrage/api_handler/apis/rca.py | 1 - vitrage/api_handler/apis/topology.py | 1 - vitrage/common/constants.py | 2 + vitrage/entity_graph/processor/processor.py | 21 ++++++++ .../actions/evaluator_event_transformer.py | 7 +-- .../evaluator/actions/recipes/raise_alarm.py | 3 +- .../evaluator/test_action_executor.py | 49 +++++++++++-------- .../evaluator/recipes/test_raise_alarm.py | 23 +++++++-- 10 files changed, 77 insertions(+), 52 deletions(-) diff --git a/vitrage/api_handler/apis/alarm.py b/vitrage/api_handler/apis/alarm.py index 9c88231f2..5d9a1d204 100644 --- a/vitrage/api_handler/apis/alarm.py +++ b/vitrage/api_handler/apis/alarm.py @@ -53,8 +53,6 @@ class AlarmApis(EntityGraphApisBase): vertex_attr_filter={VProps.CATEGORY: EntityCategory.ALARM, VProps.IS_DELETED: False}) - self._add_resource_details_to_alarms(alarms) - return json.dumps({'alarms': [v.properties for v in alarms]}) def _get_alarms(self, project_id, is_admin_project): diff --git a/vitrage/api_handler/apis/base.py b/vitrage/api_handler/apis/base.py index 5ca168e69..7e3742f94 100644 --- a/vitrage/api_handler/apis/base.py +++ b/vitrage/api_handler/apis/base.py @@ -14,7 +14,6 @@ from oslo_log import log -from vitrage.common.constants import EdgeLabel from vitrage.common.constants import EdgeProperties as EProps from vitrage.common.constants import EntityCategory from vitrage.common.constants import VertexProperties as VProps @@ -199,25 +198,6 @@ class EntityGraphApisBase(object): else: return None - def _add_resource_details_to_alarms(self, alarms): - for alarm in alarms: - try: - resources = self.entity_graph.neighbors( - v_id=alarm.vertex_id, - edge_attr_filter={EProps.RELATIONSHIP_TYPE: EdgeLabel.ON}, - direction=Direction.OUT) - - resource = self._get_first(resources) - if resource: - alarm["resource_id"] = resource.get(VProps.ID, '') - alarm["resource_type"] = resource.get(VProps.TYPE, '') - else: - alarm["resource_id"] = '' - alarm["resource_type"] = '' - - except ValueError as ve: - LOG.error('Alarm %s\nException %s', alarm, ve) - def _is_project_admin(self, project_id): keystone_client = ks_client(self.conf) project = keystone_client.projects.get(project_id) diff --git a/vitrage/api_handler/apis/rca.py b/vitrage/api_handler/apis/rca.py index c5a6e1029..70d8546e6 100644 --- a/vitrage/api_handler/apis/rca.py +++ b/vitrage/api_handler/apis/rca.py @@ -60,7 +60,6 @@ class RcaApis(EntityGraphApisBase): is_admin_project) alarms = unified_graph.get_vertices(query_dict=ALARMS_ALL_QUERY) - self._add_resource_details_to_alarms(alarms) unified_graph.update_vertices(alarms) json_graph = unified_graph.json_output_graph( diff --git a/vitrage/api_handler/apis/topology.py b/vitrage/api_handler/apis/topology.py index 86c1039e9..8bc775736 100644 --- a/vitrage/api_handler/apis/topology.py +++ b/vitrage/api_handler/apis/topology.py @@ -75,7 +75,6 @@ class TopologyApis(EntityGraphApisBase): root) alarms = graph.get_vertices(query_dict=ALARMS_ALL_QUERY) - self._add_resource_details_to_alarms(alarms) graph.update_vertices(alarms) return graph.json_output_graph() diff --git a/vitrage/common/constants.py b/vitrage/common/constants.py index 4bda0c73d..7ba4a7e46 100644 --- a/vitrage/common/constants.py +++ b/vitrage/common/constants.py @@ -37,6 +37,8 @@ class VertexProperties(object): GRAPH_INDEX = 'graph_index' RAWTEXT = 'rawtext' RESOURCE_ID = 'resource_id' + VITRAGE_RESOURCE_ID = 'vitrage_resource_id' + VITRAGE_RESOURCE_TYPE = 'vitrage_resource_type' RESOURCE = 'resource' IS_REAL_VITRAGE_ID = 'is_real_vitrage_id' diff --git a/vitrage/entity_graph/processor/processor.py b/vitrage/entity_graph/processor/processor.py index bec6d7de5..1833ab247 100644 --- a/vitrage/entity_graph/processor/processor.py +++ b/vitrage/entity_graph/processor/processor.py @@ -17,6 +17,7 @@ from oslo_log import log from oslo_utils import uuidutils +from vitrage.common.constants import EntityCategory from vitrage.common.constants import GraphAction from vitrage.common.constants import VertexProperties as VProps from vitrage.common.exception import VitrageError @@ -83,6 +84,7 @@ class Processor(processor.ProcessorBase): # _find_and_fix_graph_vertex method call to the process_event method # so it will be done in one central place self._find_and_fix_graph_vertex(new_vertex, neighbors) + self._add_resource_details_to_alarm(new_vertex, neighbors) self.entity_graph.add_vertex(new_vertex) self._connect_neighbors(neighbors, set(), GraphAction.CREATE_ENTITY) @@ -107,6 +109,7 @@ class Processor(processor.ProcessorBase): if (not graph_vertex) or \ PUtils.is_newer_vertex(graph_vertex, updated_vertex): + self._add_resource_details_to_alarm(updated_vertex, neighbors) PUtils.update_entity_graph_vertex(self.entity_graph, graph_vertex, updated_vertex) @@ -426,6 +429,24 @@ class Processor(processor.ProcessorBase): edge.source_id = vitrage_id edge.target_id = neighbor_vertex.vertex_id + def _add_resource_details_to_alarm(self, vertex, neighbors): + + if not vertex.get(VProps.CATEGORY) == EntityCategory.ALARM \ + or not neighbors: + return + + # for the possibility that alarm doesn't have resource + vertex.properties[VProps.VITRAGE_RESOURCE_ID] = None + vertex.properties[VProps.VITRAGE_RESOURCE_TYPE] = None + + for neighbor in neighbors: + + if neighbor.vertex.get(VProps.CATEGORY) == EntityCategory.RESOURCE: + vertex.properties[VProps.VITRAGE_RESOURCE_ID] = \ + neighbor.vertex.vertex_id + vertex.properties[VProps.VITRAGE_RESOURCE_TYPE] = \ + neighbor.vertex.get(VProps.TYPE) + def _get_single_graph_vertex_by_props(self, vertex, include_deleted=False): """Returns a single vertex by it's defining properties diff --git a/vitrage/evaluator/actions/evaluator_event_transformer.py b/vitrage/evaluator/actions/evaluator_event_transformer.py index 9a36a3d4d..9875ee795 100644 --- a/vitrage/evaluator/actions/evaluator_event_transformer.py +++ b/vitrage/evaluator/actions/evaluator_event_transformer.py @@ -104,6 +104,7 @@ class EvaluatorEventTransformer(transformer_base.TransformerBase): return self._create_vitrage_neighbors(event) def _create_vitrage_neighbors(self, event): + event_type = event[EVALUATOR_EVENT_TYPE] timestamp = transformer_base.convert_timestamp_format( @@ -112,7 +113,6 @@ class EvaluatorEventTransformer(transformer_base.TransformerBase): ) if event_type in [ADD_EDGE, REMOVE_EDGE]: - relation_edge = graph_utils.create_edge( source_id=event[TFields.SOURCE], target_id=event[TFields.TARGET], @@ -122,7 +122,6 @@ class EvaluatorEventTransformer(transformer_base.TransformerBase): return [Neighbor(None, relation_edge)] if event_type == ADD_VERTEX: - relation_edge = graph_utils.create_edge( source_id=self._create_entity_key(event), target_id=event[TFields.TARGET], @@ -133,7 +132,9 @@ class EvaluatorEventTransformer(transformer_base.TransformerBase): VProps.IS_PLACEHOLDER: True, VProps.UPDATE_TIMESTAMP: timestamp, VProps.SAMPLE_TIMESTAMP: event[VProps.SAMPLE_TIMESTAMP], - VProps.IS_REAL_VITRAGE_ID: True + VProps.IS_REAL_VITRAGE_ID: True, + VProps.TYPE: event[VProps.VITRAGE_RESOURCE_TYPE], + VProps.CATEGORY: EntityCategory.RESOURCE, } neighbor = Vertex(event[TFields.TARGET], neighbor_props) return [Neighbor(neighbor, relation_edge)] diff --git a/vitrage/evaluator/actions/recipes/raise_alarm.py b/vitrage/evaluator/actions/recipes/raise_alarm.py index d77efa001..d2577c015 100644 --- a/vitrage/evaluator/actions/recipes/raise_alarm.py +++ b/vitrage/evaluator/actions/recipes/raise_alarm.py @@ -57,7 +57,8 @@ class RaiseAlarm(base.Recipe): target_resource = action_spec.targets[TFields.TARGET] add_vertex_params = { - TFields.TARGET: target_resource.vertex_id + TFields.TARGET: target_resource.vertex_id, + VProps.VITRAGE_RESOURCE_TYPE: target_resource[VProps.TYPE], } add_vertex_params.update(action_spec.properties) diff --git a/vitrage/tests/functional/evaluator/test_action_executor.py b/vitrage/tests/functional/evaluator/test_action_executor.py index c5fa586be..5ef0f74ea 100644 --- a/vitrage/tests/functional/evaluator/test_action_executor.py +++ b/vitrage/tests/functional/evaluator/test_action_executor.py @@ -16,11 +16,14 @@ from oslo_config import cfg from six.moves import queue +from vitrage.common.constants import DatasourceProperties as DSProp from vitrage.common.constants import EdgeLabel from vitrage.common.constants import EntityCategory +from vitrage.common.constants import TemplateTopologyFields as TTFields 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.nagios.properties import NagiosProperties as NProps from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.entity_graph.mappings.operational_resource_state import \ OperationalResourceState @@ -233,6 +236,11 @@ class TestActionExecutor(TestFunctionalBase): props[TFields.SEVERITY]) self.assertEqual(alarm.properties[VProps.STATE], AlarmProps.ACTIVE_STATE) + self.assertEqual(alarm.properties[VProps.VITRAGE_RESOURCE_ID], + action_spec.targets + [TTFields.TARGET][VProps.VITRAGE_ID]), + self.assertEqual(alarm.properties[VProps.VITRAGE_RESOURCE_TYPE], + NOVA_HOST_DATASOURCE) def test_execute_add_and_remove_vertex(self): @@ -283,27 +291,28 @@ class TestActionExecutor(TestFunctionalBase): @staticmethod def _get_nagios_event(resource_name, resource_type): - return {'last_check': '2016-02-07 15:26:04', - 'resource_name': resource_name, - 'resource_type': resource_type, - 'service': 'Check_MK', - 'status': 'CRITICAL', - 'status_info': 'test test test', - 'vitrage_datasource_action': 'snapshot', - 'vitrage_entity_type': 'nagios', - 'vitrage_sample_date': '2016-02-07 15:26:04'} + return {NProps.LAST_CHECK: '2016-02-07 15:26:04', + NProps.RESOURCE_NAME: resource_name, + NProps.RESOURCE_TYPE: resource_type, + NProps.SERVICE: 'Check_MK', + NProps.STATUS: 'CRITICAL', + NProps.STATUS_INFO: 'test test test', + DSProp.DATASOURCE_ACTION: 'snapshot', + DSProp.ENTITY_TYPE: 'nagios', + DSProp.SAMPLE_DATE: '2016-02-07 15:26:04'} @staticmethod def _get_vitrage_add_vertex_event(target_vertex, alarm_name, severity): - return {'target': target_vertex.vertex_id, - 'update_timestamp': '2016-03-17 11:33:32.443002', - 'vitrage_datasource_action': 'update', - 'alarm_name': alarm_name, - 'state': 'Active', - 'type': 'add_vertex', - 'vitrage_entity_type': 'vitrage', - 'severity': 'CRITICAL', - 'vitrage_id': 'mock_vitrage_id', - 'category': 'RESOURCE', - 'sample_timestamp': '2016-03-17 11:33:32.443002+00:00'} + return {TTFields.TARGET: target_vertex.vertex_id, + VProps.UPDATE_TIMESTAMP: '2016-03-17 11:33:32.443002', + DSProp.DATASOURCE_ACTION: 'update', + TFields.ALARM_NAME: alarm_name, + VProps.STATE: 'Active', + VProps.TYPE: 'add_vertex', + DSProp.ENTITY_TYPE: 'vitrage', + VProps.SEVERITY: 'CRITICAL', + VProps.VITRAGE_ID: 'mock_vitrage_id', + VProps.VITRAGE_RESOURCE_TYPE: 'nova.host', + VProps.CATEGORY: 'ALARM', + VProps.SAMPLE_TIMESTAMP: '2016-03-17 11:33:32.443002+00:00'} diff --git a/vitrage/tests/unit/evaluator/recipes/test_raise_alarm.py b/vitrage/tests/unit/evaluator/recipes/test_raise_alarm.py index 8360e64c3..728fdaf34 100644 --- a/vitrage/tests/unit/evaluator/recipes/test_raise_alarm.py +++ b/vitrage/tests/unit/evaluator/recipes/test_raise_alarm.py @@ -12,7 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. +from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.alarm_properties import AlarmProperties +from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.evaluator.actions.base import ActionType from vitrage.evaluator.actions.recipes.action_steps import ADD_VERTEX from vitrage.evaluator.actions.recipes.action_steps import REMOVE_VERTEX @@ -29,7 +31,9 @@ class RaiseAlarmRecipeTest(base.BaseTest): @classmethod def setUpClass(cls): - cls.target_vertex = Vertex('RESOURCE:nova.host:test1') + cls.target_props = {VProps.TYPE: NOVA_HOST_DATASOURCE} + cls.target_vertex = Vertex('RESOURCE:nova.host:test1', + cls.target_props) cls.targets = {TFields.TARGET: cls.target_vertex} cls.props = {TFields.ALARM_NAME: 'VM_CPU_SUBOPTIMAL_PERFORMANCE'} @@ -49,7 +53,7 @@ class RaiseAlarmRecipeTest(base.BaseTest): self.assertEqual(ADD_VERTEX, action_steps[0].type) add_vertex_step_params = action_steps[0].params - self.assertEqual(3, len(add_vertex_step_params)) + self.assertEqual(4, len(add_vertex_step_params)) alarm_name = add_vertex_step_params[TFields.ALARM_NAME] self.assertEqual(self.props[TFields.ALARM_NAME], alarm_name) @@ -60,6 +64,11 @@ class RaiseAlarmRecipeTest(base.BaseTest): alarm_state = add_vertex_step_params[TFields.STATE] self.assertEqual(alarm_state, AlarmProperties.ACTIVE_STATE) + alarm_vitrage_resource_type = \ + add_vertex_step_params[VProps.VITRAGE_RESOURCE_TYPE] + self.assertEqual(self.target_vertex.properties[VProps.TYPE], + alarm_vitrage_resource_type) + def test_get_undo_recipe(self): # Test Action @@ -73,8 +82,9 @@ class RaiseAlarmRecipeTest(base.BaseTest): self.assertEqual(REMOVE_VERTEX, action_steps[0].type) remove_vertex_step_params = action_steps[0].params - # remove_vertex expects three params: alarm name, state and target - self.assertEqual(3, len(remove_vertex_step_params)) + # remove_vertex expects four params: alarm name, state, target, + # and type + self.assertEqual(4, len(remove_vertex_step_params)) alarm_name = remove_vertex_step_params[TFields.ALARM_NAME] self.assertEqual(self.props[TFields.ALARM_NAME], alarm_name) @@ -84,3 +94,8 @@ class RaiseAlarmRecipeTest(base.BaseTest): alarm_state = remove_vertex_step_params[TFields.STATE] self.assertEqual(alarm_state, AlarmProperties.INACTIVE_STATE) + + alarm_vitrage_resource_type = \ + remove_vertex_step_params[VProps.VITRAGE_RESOURCE_TYPE] + self.assertEqual(self.target_vertex.properties[VProps.TYPE], + alarm_vitrage_resource_type)