Remove Ceilometer datasource

... because it depends on Ceilometer API and ceilometerclient, which
were already retired.

Change-Id: I9f99eaf637d1250140059e17e140dda5925dd700
This commit is contained in:
Takashi Kajinami 2022-08-21 02:52:05 +09:00
parent 9a9710558b
commit df3c414919
13 changed files with 5 additions and 1465 deletions

View File

@ -0,0 +1,5 @@
---
upgrade:
- |
The ceilometer datasource has been removed, because it depends on
Ceilometer API which was already removed.

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 oslo_config import cfg
from vitrage.common.constants import DatasourceOpts as DSOpts
from vitrage.common.constants import UpdateMethod
CEILOMETER_DATASOURCE = 'ceilometer'
OPTS = [
cfg.StrOpt(DSOpts.TRANSFORMER,
default='vitrage.datasources.ceilometer.'
'transformer.CeilometerTransformer',
help='Ceilometer transformer class path',
required=True),
cfg.StrOpt(DSOpts.DRIVER,
default='vitrage.datasources.ceilometer.'
'driver.CeilometerDriver',
help='ceilometer driver class path',
required=True),
cfg.StrOpt(DSOpts.UPDATE_METHOD,
default=UpdateMethod.PUSH,
help='None: updates only via Vitrage periodic snapshots.'
'Pull: updates every [changes_interval] seconds.'
'Push: updates by getting notifications from the'
' datasource itself.',
required=True),
cfg.IntOpt(DSOpts.CHANGES_INTERVAL,
default=10,
min=10,
help='interval between checking changes'
'in ceilometer data source'),
]

View File

@ -1,387 +0,0 @@
# Copyright 2016 - Alcatel-Lucent
#
# 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_log import log
from vitrage.common.constants import DatasourceAction
from vitrage.common.constants import DatasourceProperties as DSProps
from vitrage.datasources.alarm_driver_base import AlarmDriverBase
from vitrage.datasources.ceilometer import CEILOMETER_DATASOURCE
from vitrage.datasources.ceilometer.properties \
import CeilometerEventType as CeilEventType
from vitrage.datasources.ceilometer.properties \
import CeilometerProperties as CeilProps
from vitrage.datasources.ceilometer.properties \
import CeilometerState as CeilState
from vitrage import os_clients
from vitrage.utils import datetime as datetime_utils
LOG = log.getLogger(__name__)
class CeilometerDriver(AlarmDriverBase):
def __init__(self):
super(CeilometerDriver, self).__init__()
self._client = None
self._init_aodh_event_actions()
self._cache_all_alarms()
@property
def client(self):
if not self._client:
self._client = os_clients.ceilometer_client()
return self._client
def _vitrage_type(self):
return CEILOMETER_DATASOURCE
def _alarm_key(self, alarm):
return alarm[CeilProps.ALARM_ID]
def _cache_all_alarms(self):
alarms = self._get_alarms()
self._filter_and_cache_alarms(alarms,
self._filter_get_valid)
def _get_alarms(self):
try:
aodh_alarms = self.client.alarms.list()
return [self._convert_alarm(alarm) for alarm in
aodh_alarms if alarm is not None]
except Exception:
LOG.exception("Failed to get all alarms.")
return []
def _is_erroneous(self, alarm):
return alarm and alarm[CeilProps.STATE] == CeilState.ALARM
def _status_changed(self, alarm1, alarm2):
return alarm1 and alarm2 and \
not alarm1[CeilProps.STATE] == alarm2[CeilProps.STATE]
def _is_valid(self, alarm):
return True
@classmethod
def _convert_event_alarm(cls, alarm):
res = cls._convert_base_alarm(alarm)
res[CeilProps.EVENT_TYPE] = alarm.event_rule[CeilProps.EVENT_TYPE],
res[CeilProps.RESOURCE_ID] = _parse_query(alarm.event_rule,
CeilProps.EVENT_RESOURCE_ID)
return res
@classmethod
def _convert_threshold_alarm(cls, alarm):
res = cls._convert_base_alarm(alarm)
res[CeilProps.STATE_TIMESTAMP] = alarm.state_timestamp
res[CeilProps.RESOURCE_ID] = _parse_query(alarm.threshold_rule,
CeilProps.RESOURCE_ID)
return res
@classmethod
def _convert_gnocchi_resources_threshold(cls, alarm):
res = cls._convert_base_alarm_gnocchi(alarm)
if type(alarm) is not dict:
alarm = alarm.to_dict()
res[CeilProps.STATE_TIMESTAMP] = \
alarm.get(CeilProps.STATE_TIMESTAMP)
res[CeilProps.RESOURCE_ID] = \
alarm.get(CeilProps.GNOCCHI_RESOURCES_THRESHOLD_RULE,
{}).get(CeilProps.RESOURCE_ID)
else:
res[CeilProps.STATE_TIMESTAMP] = \
alarm.get(CeilProps.DETAIL, {}).get(CeilProps.STATE_TIMESTAMP)
res[CeilProps.RESOURCE_ID] = \
alarm.get(CeilProps.DETAIL,
{}).get(CeilProps.RULE,
{}).get(CeilProps.RESOURCE_ID)
return res
@classmethod
def _convert_vitrage_alarm(cls, alarm):
res = cls._convert_base_alarm(alarm)
res[CeilProps.VITRAGE_ID] = _parse_query(alarm.event_rule,
CeilProps.VITRAGE_ID)
res[CeilProps.RESOURCE_ID] = _parse_query(alarm.event_rule,
CeilProps.RESOURCE_ID)
return res
@staticmethod
def _convert_base_dict_alarm_gnocchi(alarm):
detail = alarm.get(CeilProps.DETAIL)
return {
CeilProps.SEVERITY: alarm.get(CeilProps.SEVERITY),
CeilProps.PROJECT_ID: alarm.get(CeilProps.PROJECT_ID),
CeilProps.TIMESTAMP: alarm.get(CeilProps.TIMESTAMP),
CeilProps.TYPE: alarm.get(CeilProps.TYPE),
CeilProps.ALARM_ID: alarm.get(CeilProps.ALARM_ID),
CeilProps.DESCRIPTION: detail.get(CeilProps.DESCRIPTION),
CeilProps.ENABLED: detail.get(CeilProps.ENABLED),
CeilProps.NAME: detail.get(CeilProps.NAME),
CeilProps.REPEAT_ACTIONS: detail.get(CeilProps.REPEAT_ACTIONS),
CeilProps.STATE: detail.get(CeilProps.STATE)
}
@staticmethod
def _convert_base_non_dict_alarm_gnocchi(alarm):
alarm = alarm.to_dict()
return {
CeilProps.SEVERITY: alarm.get(CeilProps.SEVERITY),
CeilProps.DESCRIPTION: alarm.get(CeilProps.DESCRIPTION),
CeilProps.ENABLED: alarm.get(CeilProps.ENABLED),
CeilProps.ALARM_ID: alarm.get(CeilProps.ALARM_ID),
CeilProps.NAME: alarm.get(CeilProps.NAME),
CeilProps.PROJECT_ID: alarm.get(CeilProps.PROJECT_ID),
CeilProps.REPEAT_ACTIONS: alarm.get(CeilProps.REPEAT_ACTIONS),
CeilProps.STATE: alarm.get(CeilProps.STATE),
CeilProps.TIMESTAMP: alarm.get(CeilProps.TIMESTAMP),
CeilProps.TYPE: alarm.get(CeilProps.TYPE)
}
@classmethod
def _convert_base_alarm_gnocchi(cls, alarm):
"""distinguish between alarm received by notification (type dict)
to alarm received by _get_alarms() (type alarm).
"""
if type(alarm) is dict:
return cls._convert_base_dict_alarm_gnocchi(alarm)
return cls._convert_base_non_dict_alarm_gnocchi(alarm)
@staticmethod
def _convert_base_alarm(alarm):
return {
CeilProps.SEVERITY: alarm.severity,
CeilProps.DESCRIPTION: alarm.description,
CeilProps.ENABLED: alarm.enabled,
CeilProps.ALARM_ID: alarm.alarm_id,
CeilProps.NAME: alarm.name,
CeilProps.PROJECT_ID: alarm.project_id,
CeilProps.REPEAT_ACTIONS: alarm.repeat_actions,
CeilProps.STATE: alarm.state,
CeilProps.TIMESTAMP: alarm.timestamp,
CeilProps.TYPE: alarm.type
}
@classmethod
def _convert_alarm(cls, alarm):
alarm_type = alarm.type
if alarm_type == CeilProps.EVENT and \
_is_vitrage_alarm(alarm.event_rule):
return cls._convert_vitrage_alarm(alarm)
elif alarm_type == CeilProps.EVENT:
return cls._convert_event_alarm(alarm)
elif alarm_type == CeilProps.THRESHOLD:
return cls._convert_threshold_alarm(alarm)
elif alarm_type == CeilProps.GNOCCHI_RESOURCES_THRESHOLD:
return cls._convert_gnocchi_resources_threshold(alarm)
else:
LOG.warning('Unsupported Ceilometer alarm type %s' % alarm_type)
@staticmethod
def get_event_types():
# Add event_types to receive notifications about
return [CeilEventType.CREATION,
CeilEventType.STATE_TRANSITION,
CeilEventType.RULE_CHANGE,
CeilEventType.DELETION]
def enrich_event(self, event, event_type):
if event_type in self.actions:
entity = self.actions[event_type](event)
else:
LOG.warning('Unsupported Ceilometer event type %s' % event_type)
return None
# Don't need to update entity, only update the cache
if entity is None:
return None
entity[DSProps.EVENT_TYPE] = event_type
return CeilometerDriver.make_pickleable(
[entity], CEILOMETER_DATASOURCE,
DatasourceAction.UPDATE)[0]
def _init_aodh_event_actions(self):
self.actions = {
CeilEventType.CREATION:
self._convert_alarm_creation_event,
CeilEventType.RULE_CHANGE:
self._convert_alarm_rule_change_event,
CeilEventType.STATE_TRANSITION:
self._convert_alarm_state_transition_event,
CeilEventType.DELETION:
self._convert_alarm_deletion_event
}
@classmethod
def _convert_base_event(cls, event):
return {
CeilProps.PROJECT_ID: event[CeilProps.PROJECT_ID],
CeilProps.ALARM_ID: event[CeilProps.ALARM_ID],
CeilProps.SEVERITY: event[CeilProps.SEVERITY],
CeilProps.TIMESTAMP: event[CeilProps.TIMESTAMP],
CeilProps.USER_ID: event[CeilProps.USER_ID]
}
@classmethod
def _convert_vitrage_alarm_rule(cls, rule):
return {
CeilProps.VITRAGE_ID: _parse_query(rule, CeilProps.VITRAGE_ID),
CeilProps.RESOURCE_ID: _parse_query(rule, CeilProps.RESOURCE_ID)
}
@classmethod
def _convert_threshold_alarm_rule(cls, rule):
return {
CeilProps.RESOURCE_ID: _parse_query(rule, CeilProps.RESOURCE_ID),
}
@classmethod
def _convert_gnocchi_resources_threshold_alarm_rule(cls, rule):
return {
CeilProps.RESOURCE_ID: _parse_query(rule, CeilProps.RESOURCE_ID),
}
@classmethod
def _convert_event_alarm_rule(cls, rule):
return {
CeilProps.EVENT_TYPE: rule[CeilProps.EVENT_TYPE],
CeilProps.RESOURCE_ID:
_parse_query(rule, CeilProps.EVENT_RESOURCE_ID)
}
@classmethod
def _convert_detail_event(cls, event):
alarm_info = event[CeilProps.DETAIL]
alarm_rule = alarm_info[CeilProps.RULE]
entity_detail = {
CeilProps.DESCRIPTION: alarm_info[CeilProps.DESCRIPTION],
CeilProps.ENABLED: alarm_info[CeilProps.ENABLED],
CeilProps.NAME: alarm_info[CeilProps.NAME],
CeilProps.STATE: alarm_info[CeilProps.STATE],
CeilProps.REPEAT_ACTIONS: alarm_info[CeilProps.REPEAT_ACTIONS],
CeilProps.TYPE: alarm_info[CeilProps.TYPE],
CeilProps.STATE_TIMESTAMP: alarm_info[CeilProps.STATE_TIMESTAMP],
CeilProps.STATE_REASON: alarm_info[CeilProps.STATE_REASON]
}
if _is_vitrage_alarm(alarm_rule):
entity_detail.update(cls._convert_vitrage_alarm_rule(alarm_rule))
elif entity_detail[CeilProps.TYPE] == CeilProps.EVENT:
entity_detail.update(cls._convert_event_alarm_rule(alarm_rule))
elif entity_detail[CeilProps.TYPE] == CeilProps.THRESHOLD:
entity_detail.update(
cls._convert_threshold_alarm_rule(alarm_rule))
elif entity_detail[CeilProps.TYPE] == \
CeilProps.GNOCCHI_RESOURCES_THRESHOLD:
entity_detail.update(
cls._convert_gnocchi_resources_threshold_alarm_rule(
alarm_rule))
return entity_detail
@classmethod
def _parse_changed_rule(cls, change_rule):
entity = {}
if CeilProps.EVENT_TYPE in change_rule:
entity[CeilProps.EVENT_TYPE] = change_rule[CeilProps.EVENT_TYPE]
if 'query' in change_rule:
event_resource_id = \
_parse_query(change_rule, CeilProps.EVENT_RESOURCE_ID)
resource_id = \
_parse_query(change_rule, CeilProps.RESOURCE_ID)
if event_resource_id or resource_id:
entity[CeilProps.RESOURCE_ID] = event_resource_id if \
event_resource_id is not None else resource_id
return entity
@staticmethod
def should_delete_outdated_entities():
return True
def _convert_alarm_creation_event(self, event):
entity = self._convert_base_event(event)
detail = self._convert_detail_event(event)
entity.update(detail)
return self._filter_and_cache_alarm(entity, None,
self._filter_get_erroneous,
datetime_utils.utcnow(False))
def _convert_alarm_rule_change_event(self, event):
"""handle alarm rule change notification
example of changed rule:
"detail": {"severity": "critical",
"rule":
{"query": [{"field": "traits.resource_id",
"type": "",
"value": "1",
"op": "eq"}],
"event_type": "instance.update"}}
"""
old_alarm = self._old_alarm(event)
entity = old_alarm.copy()
changed_rule = event[CeilProps.DETAIL]
for (changed_type, changed_info) in changed_rule.items():
# handle changed rule which may effect the neighbor
if changed_type == CeilProps.RULE:
entity.update(self._parse_changed_rule(
changed_rule[changed_type]))
# handle other changed alarm properties
elif changed_type in vars(CeilProps).values():
entity[changed_type] = changed_info
return self._filter_and_cache_alarm(entity, old_alarm,
self._filter_get_erroneous,
datetime_utils.utcnow(False))
def _convert_alarm_state_transition_event(self, event):
old_alarm = self._old_alarm(event)
entity = old_alarm.copy()
try:
entity[CeilProps.STATE] = event[CeilProps.DETAIL][CeilProps.STATE]
except Exception:
LOG.exception("Failed to Convert alarm state transition event.")
return self._filter_and_cache_alarm(entity, old_alarm,
self._filter_get_change,
datetime_utils.utcnow(False))
def _convert_alarm_deletion_event(self, event):
alarm_key = self._alarm_key(event)
alarm = self.cache.pop(alarm_key)[0]
return alarm if self._is_erroneous(alarm) else None
def _parse_query(data, key):
query_fields = data.get(CeilProps.QUERY, {})
for query in query_fields:
field = query['field']
if field == key:
return query['value']
return None
def _is_vitrage_alarm(rule):
return _parse_query(rule, CeilProps.VITRAGE_ID) is not None

View File

@ -1,54 +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.
class CeilometerProperties(object):
ALARM_ID = 'alarm_id'
DESCRIPTION = 'description'
ENABLED = 'enabled'
EVENT = 'event'
EVENT_TYPE = 'event_type'
EVENT_RESOURCE_ID = 'traits.resource_id'
NAME = 'name'
STATE = 'state'
PROJECT_ID = 'project_id'
QUERY = 'query'
REPEAT_ACTIONS = 'repeat_actions'
RESOURCE_ID = 'resource_id'
SEVERITY = 'severity'
STATE_TIMESTAMP = 'state_timestamp'
THRESHOLD = 'threshold'
GNOCCHI_RESOURCES_THRESHOLD = 'gnocchi_resources_threshold'
TIMESTAMP = 'timestamp'
TYPE = 'type'
VITRAGE_ID = 'vitrage_id'
DETAIL = 'detail'
RULE = 'rule'
GNOCCHI_RESOURCES_THRESHOLD_RULE = 'gnocchi_resources_threshold_rule'
USER_ID = 'user_id'
STATE_REASON = 'state_reason'
TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
class CeilometerState(object):
OK = 'ok'
ALARM = 'alarm'
INSUFFICIENT_DATA = 'insufficient_data'
class CeilometerEventType(object):
CREATION = 'alarm.creation'
RULE_CHANGE = 'alarm.rule_change'
STATE_TRANSITION = 'alarm.state_transition'
DELETION = 'alarm.deletion'

View File

@ -1,164 +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 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 VertexProperties as VProps
from vitrage.datasources.alarm_transformer_base import AlarmTransformerBase
from vitrage.datasources.ceilometer import CEILOMETER_DATASOURCE
from vitrage.datasources.ceilometer.properties \
import CeilometerEventType as CeilEventType
from vitrage.datasources.ceilometer.properties \
import CeilometerProperties as CeilProps
from vitrage.datasources.ceilometer.properties \
import CeilometerState as CeilState
from vitrage.datasources import transformer_base as tbase
from vitrage.datasources.transformer_base import Neighbor
from vitrage.datasources.transformer_base import TransformerBase
from vitrage.evaluator.actions.evaluator_event_transformer \
import VITRAGE_DATASOURCE
import vitrage.graph.utils as graph_utils
from vitrage.utils import datetime as datetime_utils
class CeilometerTransformer(AlarmTransformerBase):
# Event types which need to refer them differently
GRAPH_ACTION_MAPPING = {
CeilEventType.DELETION: GraphAction.DELETE_ENTITY,
}
def _create_snapshot_entity_vertex(self, entity_event):
if _is_vitrage_alarm(entity_event):
return self._create_merge_alarm_vertex(entity_event)
return self._create_vertex(entity_event)
def _create_update_entity_vertex(self, entity_event):
if _is_vitrage_alarm(entity_event):
return self._create_merge_alarm_vertex(entity_event)
return self._create_vertex(entity_event)
def _create_vertex(self, entity_event):
metadata = {
VProps.NAME: entity_event[CeilProps.NAME],
VProps.SEVERITY: entity_event[CeilProps.SEVERITY],
CeilProps.DESCRIPTION: entity_event[CeilProps.DESCRIPTION],
CeilProps.ENABLED: entity_event[CeilProps.ENABLED],
VProps.PROJECT_ID: entity_event.get(CeilProps.PROJECT_ID, None),
CeilProps.REPEAT_ACTIONS: entity_event[CeilProps.REPEAT_ACTIONS],
VProps.RESOURCE_ID: entity_event[CeilProps.RESOURCE_ID],
'alarm_type': entity_event[CeilProps.TYPE]
}
# TODO(annarez): convert EVENT_TYPE to tuple
if entity_event[CeilProps.TYPE] == CeilProps.EVENT:
metadata[CeilProps.EVENT_TYPE] = \
entity_event[CeilProps.EVENT_TYPE]
elif entity_event[CeilProps.TYPE] == CeilProps.THRESHOLD:
metadata[CeilProps.STATE_TIMESTAMP] = \
entity_event[CeilProps.STATE_TIMESTAMP]
vitrage_sample_timestamp = entity_event[DSProps.SAMPLE_DATE]
update_timestamp = self._format_update_timestamp(
CeilometerTransformer._timestamp(entity_event),
vitrage_sample_timestamp)
return graph_utils.create_vertex(
self._create_entity_key(entity_event),
vitrage_category=EntityCategory.ALARM,
vitrage_type=entity_event[DSProps.ENTITY_TYPE],
vitrage_sample_timestamp=vitrage_sample_timestamp,
entity_id=entity_event[CeilProps.ALARM_ID],
entity_state=self._get_alarm_state(entity_event),
update_timestamp=update_timestamp,
metadata=metadata)
def _create_snapshot_neighbors(self, entity_event):
return self._create_aodh_neighbors(entity_event)
def _create_update_neighbors(self, entity_event):
return self._create_aodh_neighbors(entity_event)
def _create_aodh_neighbors(self, entity_event):
graph_neighbors = entity_event.get(self.QUERY_RESULT, [])
result = []
for vertex in graph_neighbors:
edge = graph_utils.create_edge(
source_id=TransformerBase.uuid_from_deprecated_vitrage_id(
self._create_entity_key(entity_event)),
target_id=vertex.vertex_id,
relationship_type=EdgeLabel.ON)
result.append(Neighbor(vertex, edge))
return result
def _create_merge_alarm_vertex(self, entity_event):
"""Handle an alarm that already has a vitrage_id
This is a deduced alarm created in aodh by vitrage, so it already
exists in the graph.
This function will update the exiting vertex (and not create a new one)
"""
metadata = {
CeilProps.DESCRIPTION: entity_event[CeilProps.DESCRIPTION],
VProps.PROJECT_ID: entity_event[CeilProps.PROJECT_ID],
}
vitrage_sample_timestamp = entity_event[DSProps.SAMPLE_DATE]
update_timestamp = self._format_update_timestamp(
CeilometerTransformer._timestamp(entity_event),
vitrage_sample_timestamp)
return graph_utils.create_vertex(
self._create_entity_key(entity_event),
vitrage_category=EntityCategory.ALARM,
vitrage_type=VITRAGE_DATASOURCE,
vitrage_sample_timestamp=vitrage_sample_timestamp,
entity_id=entity_event.get(CeilProps.ALARM_ID),
update_timestamp=update_timestamp,
metadata=metadata)
def _ok_status(self, entity_event):
return entity_event[CeilProps.STATE] != CeilState.ALARM
def _create_entity_key(self, entity_event):
if _is_vitrage_alarm(entity_event):
return entity_event.get(CeilProps.VITRAGE_ID)
entity_type = entity_event[DSProps.ENTITY_TYPE]
alarm_id = entity_event[CeilProps.ALARM_ID]
return tbase.build_key((EntityCategory.ALARM, entity_type, alarm_id))
@staticmethod
def _timestamp(entity_event):
return datetime_utils.change_time_str_format(
entity_event[CeilProps.TIMESTAMP],
CeilProps.TIME_FORMAT,
tbase.TIMESTAMP_FORMAT)
@staticmethod
def get_enrich_query(event):
affected_resource_id = event.get(CeilProps.RESOURCE_ID, None)
if not affected_resource_id:
return None
return {VProps.ID: affected_resource_id}
def get_vitrage_type(self):
return CEILOMETER_DATASOURCE
def _is_vitrage_alarm(entity_event):
return entity_event.get(CeilProps.VITRAGE_ID) is not None

View File

@ -23,7 +23,6 @@ LOG = log.getLogger(__name__)
OPTS = [
cfg.StrOpt('aodh_version', default='2', help='Aodh version'),
cfg.StrOpt('ceilometer_version', default='2', help='Ceilometer version'),
cfg.StrOpt('nova_version', default='2.11', help='Nova version'),
cfg.StrOpt('cinder_version', default='3', help='Cinder version'),
cfg.StrOpt('glance_version', default='2', help='Glance version'),
@ -43,7 +42,6 @@ OPTS = [
_client_modules = {
'aodh': 'aodhclient.client',
'ceilometer': 'ceilometerclient.client',
'nova': 'novaclient.client',
'cinder': 'cinderclient.client',
'glance': 'glanceclient.client',
@ -87,20 +85,6 @@ def aodh_client():
LOG.exception('Create Aodh client - Got Exception.')
def ceilometer_client():
"""Get an instance of ceilometer client"""
try:
cm_client = driver_module('ceilometer')
client = cm_client.get_client(
version=CONF.ceilometer_version,
session=keystone_client.get_session(),
)
LOG.info('Ceilometer client created')
return client
except Exception:
LOG.exception('Create Ceilometer client - Got Exception.')
def nova_client():
"""Get an instance of nova client"""
try:

View File

@ -1,100 +0,0 @@
# 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 testtools import matchers
from vitrage.common.constants import DatasourceProperties as DSProp
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.ceilometer import CEILOMETER_DATASOURCE
from vitrage.datasources.ceilometer.properties \
import CeilometerProperties as CeilProps
from vitrage.datasources import NOVA_HOST_DATASOURCE
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
from vitrage.datasources import NOVA_ZONE_DATASOURCE
from vitrage.datasources.transformer_base import TransformerBase
from vitrage.tests.functional.datasources.base import \
TestDataSourcesBase
from vitrage.tests.mocks import mock_transformer
class TestCeilometerAlarms(TestDataSourcesBase):
DATASOURCES_OPTS = [
cfg.ListOpt('types',
default=[CEILOMETER_DATASOURCE,
NOVA_HOST_DATASOURCE,
NOVA_INSTANCE_DATASOURCE,
NOVA_ZONE_DATASOURCE],
help='Names of supported driver data sources'),
cfg.ListOpt('path',
default=['vitrage.datasources'],
help='base path for data sources')
]
def setUp(self):
super(TestCeilometerAlarms, self).setUp()
self.cfg_fixture.config(group='datasources',
types=[
CEILOMETER_DATASOURCE,
NOVA_HOST_DATASOURCE,
NOVA_INSTANCE_DATASOURCE,
NOVA_ZONE_DATASOURCE])
self.load_datasources()
def test_ceilometer_alarms_validity(self):
# Setup
processor = self._create_processor_with_graph()
self.assertThat(processor.entity_graph,
matchers.HasLength(
self._num_total_expected_vertices())
)
detail = {TransformerBase.QUERY_RESULT: '',
DSProp.ENTITY_TYPE: CEILOMETER_DATASOURCE}
spec_list = \
mock_transformer.simple_aodh_alarm_generators(alarm_num=1,
snapshot_events=1,
snap_vals=detail)
static_events = mock_transformer.generate_random_events_list(spec_list)
aodh_event = static_events[0]
aodh_event[CeilProps.RESOURCE_ID] = \
self._find_entity_id_by_type(processor.entity_graph,
NOVA_HOST_DATASOURCE)
# Action
processor.process_event(aodh_event)
# Test assertions
self.assertThat(processor.entity_graph,
matchers.HasLength(
self._num_total_expected_vertices() + 1)
)
aodh_vertices = processor.entity_graph.get_vertices(
vertex_attr_filter={
VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: CEILOMETER_DATASOURCE
})
self.assertThat(aodh_vertices, matchers.HasLength(1))
aodh_neighbors = processor.entity_graph.neighbors(
aodh_vertices[0].vertex_id)
self.assertThat(aodh_neighbors, matchers.HasLength(1))
self.assertEqual(NOVA_HOST_DATASOURCE,
aodh_neighbors[0][VProps.VITRAGE_TYPE])

View File

@ -1,119 +0,0 @@
# Copyright 2017 - 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 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 VertexProperties as VProps
from vitrage.datasources.alarm_properties import AlarmProperties as AlarmProps
from vitrage.datasources.ceilometer.properties \
import CeilometerProperties as CeilProps
from vitrage.datasources.ceilometer.properties import CeilometerState
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
class CeilometerTransformerBaseTest(base.BaseTest):
def _validate_aodh_vertex_props(self, vertex, event):
self.assertEqual(EntityCategory.ALARM,
vertex[VProps.VITRAGE_CATEGORY])
self.assertEqual(event[DSProps.ENTITY_TYPE],
vertex[VProps.VITRAGE_TYPE])
self.assertEqual(event[CeilProps.NAME], vertex[VProps.NAME])
self.assertEqual(event[CeilProps.SEVERITY],
vertex[VProps.SEVERITY])
self.assertEqual(event[CeilProps.DESCRIPTION],
vertex[CeilProps.DESCRIPTION])
self.assertEqual(event[CeilProps.ENABLED],
vertex[CeilProps.ENABLED])
self.assertEqual(event[CeilProps.PROJECT_ID],
vertex[VProps.PROJECT_ID])
self.assertEqual(event[CeilProps.REPEAT_ACTIONS],
vertex[CeilProps.REPEAT_ACTIONS])
self.assertEqual(event[CeilProps.TYPE], vertex['alarm_type'])
if event[CeilProps.TYPE] == CeilProps.EVENT:
self.assertEqual(event[CeilProps.EVENT_TYPE],
vertex[CeilProps.EVENT_TYPE])
elif event[CeilProps.TYPE] == CeilProps.THRESHOLD:
self.assertEqual(event[CeilProps.STATE_TIMESTAMP],
vertex[CeilProps.STATE_TIMESTAMP])
self.assertEqual(event[DSProps.SAMPLE_DATE],
vertex[VProps.VITRAGE_SAMPLE_TIMESTAMP])
event_status = event[CeilProps.STATE]
if event_status == CeilometerState.OK:
self.assertEqual(AlarmProps.INACTIVE_STATE,
vertex[VProps.STATE])
else:
self.assertEqual(AlarmProps.ACTIVE_STATE,
vertex[VProps.STATE])
self.assertFalse(vertex[VProps.VITRAGE_IS_PLACEHOLDER])
self.assertFalse(vertex[VProps.VITRAGE_IS_DELETED])
def _validate_action(self, alarm, wrapper):
if DSProps.EVENT_TYPE in alarm \
and alarm[DSProps.EVENT_TYPE] in vars(GraphAction).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[CeilProps.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.VITRAGE_CATEGORY])
self.assertEqual(NOVA_INSTANCE_DATASOURCE,
alarm_neighbor.vertex[VProps.VITRAGE_TYPE])
self.assertEqual(resource_id, alarm_neighbor.vertex[VProps.ID])
self.assertFalse(alarm_neighbor.vertex[VProps.VITRAGE_IS_PLACEHOLDER])
self.assertFalse(alarm_neighbor.vertex[VProps.VITRAGE_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.VITRAGE_CATEGORY] + \
TransformerBase.KEY_SEPARATOR + neighbor[VProps.VITRAGE_TYPE] + \
TransformerBase.KEY_SEPARATOR + neighbor[VProps.ID]
return Vertex(vertex_id=ver_id, properties=neighbor)

View File

@ -1,24 +0,0 @@
# Copyright 2017 - 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.datasources.ceilometer.driver import CeilometerDriver
class MockCeilometerDriver(CeilometerDriver):
"""A aodh driver for tests.
"""
def _cache_all_alarms(self):
pass

View File

@ -1,391 +0,0 @@
# Copyright 2017 - 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
import testtools
from vitrage.common.constants import DatasourceOpts as DSOpts
from vitrage.common.constants import DatasourceProperties as DSProps
from vitrage.common.constants import UpdateMethod
from vitrage.datasources.ceilometer import CEILOMETER_DATASOURCE
from vitrage.datasources.ceilometer.properties import CeilometerEventType
from vitrage.datasources.ceilometer.properties \
import CeilometerProperties as CeilProps
from vitrage.tests import base
from vitrage.tests.mocks import mock_driver
from vitrage.tests.unit.datasources.ceilometer.mock_driver \
import MockCeilometerDriver
@testtools.skip("skip for now")
class CeilometerDriverTest(base.BaseTest):
OPTS = [
cfg.StrOpt(DSOpts.UPDATE_METHOD,
default=UpdateMethod.PUSH),
]
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
super(CeilometerDriverTest, cls).setUpClass()
cls.conf = cfg.ConfigOpts()
cls.conf.register_opts(cls.OPTS, group=CEILOMETER_DATASOURCE)
def test_event_alarm_notifications(self):
aodh_driver = MockCeilometerDriver()
# 1. alarm creation with 'ok' state
# prepare data
detail_data = {"type": "creation",
CeilProps.DETAIL: self._create_alarm_data_type_event(),
}
generators = \
mock_driver.simple_aodh_alarm_notification_generators(
alarm_num=1,
update_events=1,
update_vals=detail_data)
alarm = mock_driver.generate_sequential_events_list(generators)[0]
alarm_info = alarm.copy()
# action
entity = aodh_driver.enrich_event(alarm, CeilometerEventType.CREATION)
# Test assertions
# alarm with status OK should not be handled
self.assertIsNone(entity)
# 2.alarm state transition from 'ok' to 'alarm'
detail_data = {"type": "state transition",
CeilProps.DETAIL: {CeilProps.STATE: "alarm"}}
alarm.update(detail_data)
entity = aodh_driver.enrich_event(alarm,
CeilometerEventType.STATE_TRANSITION)
# Test assertions
# alarm state change: ok->alarm, need to be added
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[CeilProps.STATE],
alarm[CeilProps.DETAIL][CeilProps.STATE])
self.assertEqual(entity[CeilProps.SEVERITY],
alarm[CeilProps.SEVERITY])
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.STATE_TRANSITION)
# 3. delete alarm which is 'alarm' state
# prepare data
detail_data = {"type": "deletion"}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.DELETION)
# Test assertions
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.DELETION)
# 4. alarm creation with 'alarm' state
# prepare data
detail_data = {"type": "creation",
CeilProps.DETAIL:
self._create_alarm_data_type_event(state="alarm")}
generators = \
mock_driver.simple_aodh_alarm_notification_generators(
alarm_num=1,
update_events=1,
update_vals=detail_data)
alarm = mock_driver.generate_sequential_events_list(generators)[0]
alarm_info = alarm.copy()
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.CREATION)
# Test assertions
# alarm with status 'alarm' need to be added
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[CeilProps.STATE],
alarm[CeilProps.DETAIL][CeilProps.STATE])
self.assertEqual(entity[CeilProps.SEVERITY],
alarm[CeilProps.SEVERITY])
self.assertIsNone(entity[CeilProps.RESOURCE_ID])
self.assertEqual("*", entity[CeilProps.EVENT_TYPE])
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.CREATION)
# 5. alarm rule change
# prepare data
detail_data = {"type": "rule change",
CeilProps.DETAIL: {
"severity": "critical",
CeilProps.RULE:
{"query": [{"field": "traits.resource_id",
"type": "",
"value": "1",
"op": "eq"}],
"event_type": "instance.update"}}}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.RULE_CHANGE)
# Test assertions
# alarm rule change: need to be update
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[CeilProps.SEVERITY],
alarm[CeilProps.DETAIL][CeilProps.SEVERITY])
self.assertEqual(
entity[CeilProps.EVENT_TYPE],
alarm[CeilProps.DETAIL][CeilProps.RULE][CeilProps.EVENT_TYPE])
self.assertEqual("1", entity[CeilProps.RESOURCE_ID])
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.RULE_CHANGE)
# 6. alarm state change from 'alarm' to 'ok'
# prepare data
detail_data = {"type": "state transition",
CeilProps.DETAIL: {CeilProps.STATE: "ok"}}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.STATE_TRANSITION)
# Test assertions
# alarm state change: alarm->OK, need to be deleted
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.STATE_TRANSITION)
# 7. delete alarm which is 'ok' state
# prepare data
detail_data = {"type": "deletion"}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.DELETION)
# Test assertions
self.assertIsNone(entity)
def test_gnocchi_threshold_alarm_notifications(self):
aodh_driver = MockCeilometerDriver()
# 1. alarm creation with 'ok' state
# prepare data
detail_data = {"type": "gnocchi_resources_threshold",
CeilProps.DETAIL: self._create_alarm_data_gnocchi()}
generators = \
mock_driver.simple_aodh_alarm_notification_generators(
alarm_num=1,
update_events=1,
update_vals=detail_data)
alarm = mock_driver.generate_sequential_events_list(generators)[0]
alarm_info = alarm.copy()
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.CREATION)
# Test assertions
# alarm with status OK should not be handled
self.assertIsNone(entity)
# 2.alarm state transition from 'ok' to 'alarm'
detail_data = {"type": "state transition",
CeilProps.DETAIL: {CeilProps.STATE: "alarm"}}
alarm.update(detail_data)
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.STATE_TRANSITION)
# Test assertions
# alarm state change: ok->alarm, need to be added
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[CeilProps.STATE],
alarm[CeilProps.DETAIL][CeilProps.STATE])
self.assertEqual(entity[CeilProps.SEVERITY],
alarm[CeilProps.SEVERITY])
# 3. delete alarm which is 'alarm' state
# prepare data
detail_data = {"type": "deletion"}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.DELETION)
# Test assertions
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.DELETION)
# 4. alarm creation with 'alarm' state
# prepare data
detail_data = {"type": "gnocchi_resources_threshold",
CeilProps.DETAIL:
self._create_alarm_data_gnocchi(state="alarm")}
generators = \
mock_driver.simple_aodh_alarm_notification_generators(
alarm_num=1,
update_events=1,
update_vals=detail_data)
alarm = mock_driver.generate_sequential_events_list(generators)[0]
alarm_info = alarm.copy()
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.CREATION)
# Test assertions
# alarm with status 'alarm' need to be added
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[CeilProps.STATE],
alarm[CeilProps.DETAIL][CeilProps.STATE])
self.assertEqual(entity[CeilProps.SEVERITY],
alarm[CeilProps.SEVERITY])
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.CREATION)
# 5. alarm rule change
# prepare data
detail_data = {"type": "rule change",
CeilProps.DETAIL: {
"severity": "critical",
CeilProps.RULE:
{"granularity": "300",
"threshold": "0.0123",
"comparison_operator": "eq"}}}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.RULE_CHANGE)
# Test assertions
# alarm rule change: need to be update
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[CeilProps.SEVERITY],
alarm[CeilProps.DETAIL][CeilProps.SEVERITY])
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.RULE_CHANGE)
# 6. alarm state change from 'alarm' to 'ok'
# prepare data
detail_data = {"type": "state transition",
CeilProps.DETAIL: {CeilProps.STATE: "ok"}}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm,
CeilometerEventType.STATE_TRANSITION)
# Test assertions
# alarm state change: alarm->OK, need to be deleted
self.assertIsNotNone(entity)
self._validate_aodh_entity_comm_props(entity, alarm_info)
self.assertEqual(entity[DSProps.EVENT_TYPE],
CeilometerEventType.STATE_TRANSITION)
# 7. delete alarm which is 'ok' state
# prepare data
detail_data = {"type": "deletion"}
alarm.update(detail_data)
# action
entity = aodh_driver.enrich_event(
alarm, CeilometerEventType.DELETION)
# Test assertions
self.assertIsNone(entity)
def _create_alarm_data_gnocchi(self,
state="ok",
type="gnocchi_resources_threshold",
rule=None):
if rule is None:
rule = {"granularity": "300",
"threshold": "0.001",
"comparison_operator": "gt",
"resource_type": "instance"
}
return {CeilProps.DESCRIPTION: "test",
CeilProps.TIMESTAMP: "2016-11-09T01:39:13.839584",
CeilProps.ENABLED: True,
CeilProps.STATE_TIMESTAMP: "2016-11-09T01:39:13.839584",
CeilProps.ALARM_ID: "7e5c3754-e2eb-4782-ae00-7da5ded8568b",
CeilProps.REPEAT_ACTIONS: False,
CeilProps.PROJECT_ID: "c365d18fcc03493187016ae743f0cc4d",
CeilProps.NAME: "test",
CeilProps.SEVERITY: "low",
CeilProps.RESOURCE_ID: "88cd2d1d-8af4-4d00-9b5e-f82f8c8b0f8d",
CeilProps.TYPE: type,
CeilProps.STATE: state,
CeilProps.RULE: rule,
CeilProps.STATE_REASON: 'for test'}
def _create_alarm_data_type_event(self,
state="ok",
type="event",
rule=None):
if rule is None:
rule = {"query": [], "event_type": "*"}
return {CeilProps.DESCRIPTION: "test",
CeilProps.TIMESTAMP: "2016-11-09T01:39:13.839584",
CeilProps.ENABLED: True,
CeilProps.STATE_TIMESTAMP: "2016-11-09T01:39:13.839584",
CeilProps.ALARM_ID: "7e5c3754-e2eb-4782-ae00-7da5ded8568b",
CeilProps.REPEAT_ACTIONS: False,
CeilProps.PROJECT_ID: "c365d18fcc03493187016ae743f0cc4d",
CeilProps.NAME: "test",
CeilProps.SEVERITY: "low",
CeilProps.TYPE: type,
CeilProps.STATE: state,
CeilProps.RULE: rule,
CeilProps.STATE_REASON: 'for test'}
def _validate_aodh_entity_comm_props(self, entity, alarm):
self.assertEqual(entity[CeilProps.ALARM_ID],
alarm[CeilProps.ALARM_ID])
self.assertEqual(entity[CeilProps.PROJECT_ID],
alarm[CeilProps.PROJECT_ID])
self.assertEqual(entity[CeilProps.TIMESTAMP],
alarm[CeilProps.TIMESTAMP])
self.assertEqual(entity[CeilProps.DESCRIPTION],
alarm[CeilProps.DETAIL][CeilProps.DESCRIPTION])
self.assertEqual(entity[CeilProps.ENABLED],
alarm[CeilProps.DETAIL][CeilProps.ENABLED])
self.assertEqual(entity[CeilProps.NAME],
alarm[CeilProps.DETAIL][CeilProps.NAME])
self.assertEqual(entity[CeilProps.REPEAT_ACTIONS],
alarm[CeilProps.DETAIL][CeilProps.REPEAT_ACTIONS])
self.assertEqual(entity[CeilProps.TYPE],
alarm[CeilProps.DETAIL][CeilProps.TYPE])

View File

@ -1,166 +0,0 @@
# 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 testtools import matchers
from vitrage.common.constants import DatasourceOpts as DSOpts
from vitrage.common.constants import DatasourceProperties as DSProps
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import UpdateMethod
from vitrage.datasources.ceilometer import CEILOMETER_DATASOURCE
from vitrage.datasources.ceilometer.properties \
import CeilometerProperties as CeilProps
from vitrage.datasources.ceilometer.transformer import CeilometerTransformer
from vitrage.datasources.transformer_base import TransformerBase
from vitrage.tests.mocks import mock_transformer as mock_sync
from vitrage.tests.unit.datasources.ceilometer.\
ceilometer_transformer_base_test \
import CeilometerTransformerBaseTest
LOG = logging.getLogger(__name__)
class TestCeilometerAlarmTransformer(CeilometerTransformerBaseTest):
OPTS = [
cfg.StrOpt(DSOpts.UPDATE_METHOD,
default=UpdateMethod.PULL),
]
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
super(TestCeilometerAlarmTransformer, cls).setUpClass()
cls.transformers = {}
cls.conf = cfg.ConfigOpts()
cls.conf.register_opts(cls.OPTS, group=CEILOMETER_DATASOURCE)
cls.transformers[CEILOMETER_DATASOURCE] = \
CeilometerTransformer(cls.transformers)
def test_key_values_with_vitrage_alarm(self):
LOG.debug('Ceilometer transformer test: '
'get key values(vitrage_alarm)')
# Test setup
entity = {CeilProps.VITRAGE_ID: 'test',
DSProps.ENTITY_TYPE: CEILOMETER_DATASOURCE,
CeilProps.ALARM_ID: '12345'}
transformer = self.transformers[CEILOMETER_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('Ceilometer transformer test: get key values(aodh alarm)')
# Test setup
entity = {DSProps.ENTITY_TYPE: CEILOMETER_DATASOURCE,
CeilProps.ALARM_ID: '12345'}
transformer = self.transformers[CEILOMETER_DATASOURCE]
# Test action
entity_key_fields = transformer._create_entity_key(entity).split(":")
# Test assertions
self.assertEqual(EntityCategory.ALARM, entity_key_fields[0])
self.assertEqual(CEILOMETER_DATASOURCE, entity_key_fields[1])
self.assertEqual(entity[CeilProps.ALARM_ID], entity_key_fields[2])
def test_snapshot_transform(self):
LOG.debug('Ceilometer 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:
neighbor_vertex = self._convert_dist_to_vertex(neighbor)
vertices.append(self.transformers[CEILOMETER_DATASOURCE].
update_uuid_in_vertex(neighbor_vertex))
event[TransformerBase.QUERY_RESULT] = vertices
# Test action
wrapper = self.transformers[CEILOMETER_DATASOURCE].transform(event)
# Test assertions
vertex = wrapper.vertex
self._validate_aodh_vertex_props(vertex, event)
neighbors = wrapper.neighbors
self.assertThat(neighbors, matchers.HasLength(1))
self._validate_neighbors(neighbors, vertex.vertex_id, event)
self._validate_action(event, wrapper)
class TestCeilometerAlarmPushTransformer(CeilometerTransformerBaseTest):
OPTS = [
cfg.StrOpt(DSOpts.UPDATE_METHOD,
default=UpdateMethod.PUSH),
]
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
super(TestCeilometerAlarmPushTransformer, cls).setUpClass()
cls.transformers = {}
cls.conf = cfg.ConfigOpts()
cls.conf.register_opts(cls.OPTS, group=CEILOMETER_DATASOURCE)
cls.transformers[CEILOMETER_DATASOURCE] = \
CeilometerTransformer(cls.transformers)
def test_update_transform(self):
LOG.debug('Ceilometer update alarm transformer test:'
'transform entity event update')
# Test setup
spec_list = \
mock_sync.simple_aodh_update_alarm_generators(alarm_num=5,
update_events=5)
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:
neighbor_vertex = self._convert_dist_to_vertex(neighbor)
vertices.append(self.transformers[CEILOMETER_DATASOURCE].
update_uuid_in_vertex(neighbor_vertex))
event[TransformerBase.QUERY_RESULT] = vertices
# Test action
wrapper = self.transformers[CEILOMETER_DATASOURCE].transform(event)
# Test assertions
vertex = wrapper.vertex
self._validate_aodh_vertex_props(vertex, event)
neighbors = wrapper.neighbors
self.assertThat(neighbors, matchers.HasLength(1))
self._validate_neighbors(neighbors, vertex.vertex_id, event)
self._validate_action(event, wrapper)