Merge "add aodh transformer unit test"

This commit is contained in:
Jenkins 2016-12-06 12:53:24 +00:00 committed by Gerrit Code Review
commit 357fe8c793
5 changed files with 314 additions and 1 deletions

View File

@ -129,3 +129,32 @@ def simple_zone_generators(zone_num, snapshot_events=0, snap_vals=None):
}
]
return tg.get_trace_generators(test_entity_spec_list)
def simple_aodh_alarm_generators(alarm_num,
snapshot_events=0, snap_vals=None):
"""A simple function for returning aodh alarm generators.
Returns generators for a given number of alarms.
:param alarm_num: number of alarms
:param snapshot_events: number of snapshot events
:param snap_vals: values of snapshot
:return: generators for alarm_num alarms as specified
"""
mapping = [('alarm-{0}'.format(ind), 'resource-{0}'.format(ind))
for ind in range(alarm_num)
]
test_entity_spec_list = [
{tg.DYNAMIC_INFO_FKEY: tg.TRANS_AODH_SNAPSHOT_D,
tg.DYNAMIC_INFO_FPATH: tg.MOCK_TRANSFORMER_PATH,
tg.STATIC_INFO_FKEY: None,
tg.MAPPING_KEY: mapping,
tg.EXTERNAL_INFO_KEY: snap_vals,
tg.NAME_KEY: 'Aodh snapshot generator',
tg.NUM_EVENTS: snapshot_events
}
]
return tg.get_trace_generators(test_entity_spec_list)

View File

@ -30,6 +30,7 @@ from vitrage.tests.mocks.entity_model import BasicEntityModel as Bem
import vitrage.tests.mocks.utils as utils
DYNAMIC_INFO_FKEY = 'filename'
DYNAMIC_INFO_FPATH = 'filepath'
STATIC_INFO_FKEY = 'static_filename'
NAME_KEY = 'name'
MAPPING_KEY = 'mapping'
@ -41,6 +42,8 @@ GENERATOR = 'generator'
# specification files for input types
# Mock driver specs
MOCK_DRIVER_PATH = '%s/mock_configurations/driver' % \
utils.get_resources_dir()
DRIVER_HOST_SNAPSHOT_D = 'driver_host_snapshot_dynamic.json'
DRIVER_INST_SNAPSHOT_D = 'driver_inst_snapshot_dynamic.json'
DRIVER_INST_SNAPSHOT_S = 'driver_inst_snapshot_static.json'
@ -58,6 +61,9 @@ DRIVER_ZONE_SNAPSHOT_D = 'driver_zone_snapshot_dynamic.json'
# Mock transformer Specs (i.e., what the transformer outputs)
MOCK_TRANSFORMER_PATH = '%s/mock_configurations/transformer' % \
utils.get_resources_dir()
TRANS_AODH_SNAPSHOT_D = 'transformer_aodh_snapshot_dynamic.json'
TRANS_INST_SNAPSHOT_D = 'transformer_inst_snapshot_dynamic.json'
TRANS_INST_SNAPSHOT_S = 'transformer_inst_snapshot_static.json'
TRANS_HOST_SNAPSHOT_D = 'transformer_host_snapshot_dynamic.json'
@ -113,11 +119,15 @@ class EventTraceGenerator(object):
DRIVER_CONSISTENCY_UPDATE_D:
_get_consistency_update_driver_values,
TRANS_AODH_SNAPSHOT_D: _get_trans_aodh_alarm_snapshot_values,
TRANS_INST_SNAPSHOT_D: _get_trans_vm_snapshot_values,
TRANS_HOST_SNAPSHOT_D: _get_trans_host_snapshot_values,
TRANS_ZONE_SNAPSHOT_D: _get_trans_zone_snapshot_values}
dynam_specs = utils.load_specs(spec[DYNAMIC_INFO_FKEY])
target_folder = spec[DYNAMIC_INFO_FPATH] \
if spec.get(DYNAMIC_INFO_FPATH) else None
dynam_specs = utils.load_specs(spec[DYNAMIC_INFO_FKEY],
target_folder=target_folder)
dynamic_spec_filename = spec[DYNAMIC_INFO_FKEY].split('/')[-1]
static_specs = static_info_parsers[dynamic_spec_filename](spec)
self.name = spec.get(NAME_KEY, 'generator')
@ -569,6 +579,31 @@ def _get_trans_zone_snapshot_values(spec):
return static_values
def _get_trans_aodh_alarm_snapshot_values(spec):
"""Generates the static transformer values for each vm.
:param spec: specification of event generation.
:type spec: dict
:return: list of static transformer values for each vm.
:rtype: list
"""
alarm_resources_mapping = spec[MAPPING_KEY]
static_info_re = None
if spec[STATIC_INFO_FKEY] is not None:
static_info_re = utils.load_specs(spec[STATIC_INFO_FKEY])
static_values = []
for alarm_id, resource_id in alarm_resources_mapping:
mapping = {'alarm_id': alarm_id,
'resource_id': resource_id,
'graph_query_result': [{'id': resource_id}]}
static_values.append(combine_data(
static_info_re, mapping, spec.get(EXTERNAL_INFO_KEY, None)
))
return static_values
def combine_data(static_info_re, mapping_info, external_info):
if external_info:
mapping_info = utils.merge_vals(mapping_info, external_info)

View File

@ -0,0 +1,37 @@
{
"alarm_id": "21127fbd-7633-494e-8e5c-fdf415cdec0c",
"description": "test",
"enabled": "True",
"name": "test",
"project_id": "f0895991f44044ccba8e62b201b70360",
"repeat_actions": "False",
"severity": "low",
"state": "alarm",
"timestamp": "2016-11-29T06:31:50.094836",
"state_timestamp": "2016-11-11T01:58:36.054090",
"type": "event",
"event_type": "compute.instance.*",
"resource_id": "3dcee183-ca42-4ccb-84af-9f0196b2e160",
"vitrage_event_type": "alarm.creation",
"vitrage_entity_type": "aodh",
"vitrage_datasource_action": "snapshot",
"vitrage_sample_date": "2016-11-29T06:31:50.094836",
"graph_query_result": [
{
"category": "RESOURCE",
"is_placeholder": false,
"is_deleted": false,
"name": "dwj",
"update_timestamp": "2016-12-02 07:18:05.628479+00:00",
"sample_timestamp": "2016-12-02 07:18:05.628479+00:00",
"operational_state": "OK",
"aggregated_state": "ACTIVE",
"state": "ACTIVE",
"graph_index": 3,
"project_id": "f0895991f44044ccba8e62b201b70360",
"type": "nova.instance",
"id": "3dcee183-ca42-4ccb-84af-9f0196b2e160"
}
]
}

View File

@ -0,0 +1,15 @@
# Copyright 2016 - ZTE
#
# 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.
__author__ = 'stack'

View File

@ -0,0 +1,197 @@
# Copyright 2016 - ZTE, 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 oslo_config import cfg
from oslo_log import log as logging
from vitrage.common.constants import DatasourceAction
from vitrage.common.constants import DatasourceProperties as DSProps
from vitrage.common.constants import EdgeLabel
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import GraphAction
from vitrage.common.constants import UpdateMethod
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.alarm_properties import AlarmProperties as AlarmProps
from vitrage.datasources.aodh import AODH_DATASOURCE
from vitrage.datasources.aodh.properties import AodhProperties as AodhProps
from vitrage.datasources.aodh.properties import AodhState
from vitrage.datasources.aodh.transformer import AodhTransformer
from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
from vitrage.datasources.transformer_base import TransformerBase
from vitrage.graph.driver.elements import Vertex
from vitrage.tests import base
from vitrage.tests.mocks import mock_transformer as mock_sync
LOG = logging.getLogger(__name__)
class TestAodhAlarmTransformer(base.BaseTest):
OPTS = [
cfg.StrOpt('update_method',
default=UpdateMethod.PUSH),
]
@classmethod
def setUpClass(cls):
cls.transformers = {}
cls.conf = cfg.ConfigOpts()
cls.conf.register_opts(cls.OPTS, group=AODH_DATASOURCE)
cls.transformers[AODH_DATASOURCE] = \
AodhTransformer(cls.transformers, cls.conf)
def test_key_values_with_vitrage_alarm(self):
LOG.debug('Aodh transformer test: get key values(vitrage_alarm)')
# Test setup
entity = {AodhProps.VITRAGE_ID: 'test',
DSProps.ENTITY_TYPE: AODH_DATASOURCE,
AodhProps.ALARM_ID: '12345'}
transformer = self.transformers[AODH_DATASOURCE]
# Test action
observed_key_fields = transformer._create_entity_key(entity)
# Test assertions
self.assertEqual('test', observed_key_fields)
def test_key_values(self):
LOG.debug('Aodh transformer test: get key values(aodh alarm)')
# Test setup
entity = {DSProps.ENTITY_TYPE: AODH_DATASOURCE,
AodhProps.ALARM_ID: '12345'}
transformer = self.transformers[AODH_DATASOURCE]
# Test action
entity_key_fields = transformer._create_entity_key(entity).split(":")
# Test assertions
self.assertEqual(EntityCategory.ALARM, entity_key_fields[0])
self.assertEqual(AODH_DATASOURCE, entity_key_fields[1])
self.assertEqual(entity[AodhProps.ALARM_ID], entity_key_fields[2])
def test_snapshot_transform(self):
LOG.debug('Aodh alarm transformer test: transform entity event '
'snapshot')
# Test setup
spec_list = mock_sync.simple_aodh_alarm_generators(alarm_num=3,
snapshot_events=3)
static_events = mock_sync.generate_random_events_list(spec_list)
for event in static_events:
# convert neighbor from dict to vertex object
neighbors = event[TransformerBase.QUERY_RESULT]
vertices = []
for neighbor in neighbors:
vertices.append(self._convert_dist_to_vertex(neighbor))
event[TransformerBase.QUERY_RESULT] = vertices
# Test action
wrapper = self.transformers[AODH_DATASOURCE].transform(event)
# Test assertions
vertex = wrapper.vertex
self._validate_aodh_vertex_props(vertex, event)
neighbors = wrapper.neighbors
self.assertEqual(1, len(neighbors))
self._validate_neighbors(neighbors, vertex.vertex_id, event)
self._validate_action(event, wrapper)
def _validate_aodh_vertex_props(self, vertex, event):
self.assertEqual(EntityCategory.ALARM, vertex[VProps.CATEGORY])
self.assertEqual(event[DSProps.ENTITY_TYPE], vertex[VProps.TYPE])
self.assertEqual(event[AodhProps.NAME], vertex[VProps.NAME])
self.assertEqual(event[AodhProps.SEVERITY], vertex[VProps.SEVERITY])
self.assertEqual(event[AodhProps.DESCRIPTION],
vertex[AodhProps.DESCRIPTION])
self.assertEqual(event[AodhProps.ENABLED], vertex[AodhProps.ENABLED])
self.assertEqual(event[AodhProps.PROJECT_ID],
vertex[VProps.PROJECT_ID])
self.assertEqual(event[AodhProps.REPEAT_ACTIONS],
vertex[AodhProps.REPEAT_ACTIONS])
self.assertEqual(event[AodhProps.TYPE], vertex['alarm_type'])
if event[AodhProps.TYPE] == AodhProps.EVENT:
self.assertEqual(event[AodhProps.EVENT_TYPE],
vertex[AodhProps.EVENT_TYPE])
elif event[AodhProps.TYPE] == AodhProps.THRESHOLD:
self.assertEqual(event[AodhProps.STATE_TIMESTAMP],
vertex[AodhProps.STATE_TIMESTAMP])
self.assertEqual(event[DSProps.SAMPLE_DATE],
vertex[VProps.SAMPLE_TIMESTAMP])
event_status = event[AodhProps.STATE]
if event_status == AodhState.OK:
self.assertEqual(AlarmProps.INACTIVE_STATE,
vertex[VProps.STATE])
else:
self.assertEqual(AlarmProps.ACTIVE_STATE,
vertex[VProps.STATE])
self.assertFalse(vertex[VProps.IS_PLACEHOLDER])
self.assertFalse(vertex[VProps.IS_DELETED])
def _validate_action(self, alarm, wrapper):
if DSProps.EVENT_TYPE in alarm \
and alarm[DSProps.EVENT_TYPE] in GraphAction.__dict__.values():
self.assertEqual(alarm[DSProps.EVENT_TYPE], wrapper.action)
return
ds_action = alarm[DSProps.DATASOURCE_ACTION]
if ds_action in (DatasourceAction.SNAPSHOT, DatasourceAction.UPDATE):
self.assertEqual(GraphAction.UPDATE_ENTITY, wrapper.action)
else:
self.assertEqual(GraphAction.CREATE_ENTITY, wrapper.action)
def _validate_neighbors(self, neighbors, alarm_id, event):
resource_counter = 0
for neighbor in neighbors:
resource_id = event[AodhProps.RESOURCE_ID]
self._validate_instance_neighbor(neighbor,
resource_id,
alarm_id)
resource_counter += 1
self.assertEqual(1,
resource_counter,
'Alarm can be belonged to only one resource')
def _validate_instance_neighbor(self,
alarm_neighbor,
resource_id,
alarm_vertex_id):
# validate neighbor vertex
self.assertEqual(EntityCategory.RESOURCE,
alarm_neighbor.vertex[VProps.CATEGORY])
self.assertEqual(NOVA_INSTANCE_DATASOURCE,
alarm_neighbor.vertex[VProps.TYPE])
self.assertEqual(resource_id, alarm_neighbor.vertex[VProps.ID])
self.assertFalse(alarm_neighbor.vertex[VProps.IS_PLACEHOLDER])
self.assertFalse(alarm_neighbor.vertex[VProps.IS_DELETED])
# Validate neighbor edge
edge = alarm_neighbor.edge
self.assertEqual(edge.target_id, alarm_neighbor.vertex.vertex_id)
self.assertEqual(edge.source_id, alarm_vertex_id)
self.assertEqual(edge.label, EdgeLabel.ON)
def _convert_dist_to_vertex(self, neighbor):
ver_id = neighbor[VProps.CATEGORY] + \
TransformerBase.KEY_SEPARATOR + neighbor[VProps.TYPE] + \
TransformerBase.KEY_SEPARATOR + neighbor[VProps.ID]
return Vertex(vertex_id=ver_id, properties=neighbor)