first aodh plugin get-all implementation + some nagios fixes

Change-Id: I53e3ddc62d1617410694d899f81efc38d125b877
implements: blueprint synchronizer-aodh-get-all
This commit is contained in:
Ifat Afek 2016-03-08 06:41:28 +00:00
parent 8ab57009c0
commit 3d9b9659a9
19 changed files with 593 additions and 128 deletions

View File

@ -5,6 +5,7 @@
pbr>=1.6
Babel>=1.3
lxml>=2.3
python-ceilometerclient>=2.2.1 # Apache-2.0
python-dateutil>=2.4.2
python-novaclient>=2.26.0
networkx>=1.10

View File

@ -8,6 +8,7 @@ coverage>=3.6
discover
lxml>=2.3
networkx>=1.10
python-ceilometerclient>=2.2.1 # Apache-2.0
python-novaclient>=2.26.0
python-subunit>=0.0.18
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2

View File

@ -69,6 +69,7 @@ class EntityType(object):
STATIC_PHYSICAL = 'static_physical'
NAGIOS = 'nagios'
VITRAGE = 'vitrage'
AODH = 'aodh'
class EventAction(object):

View File

@ -22,6 +22,7 @@ OPTS = [
'nova.host',
'nova.instance',
'nova.zone',
'static_physical'],
'static_physical',
'aodh'],
help='Names of supported plugins'),
]

View File

@ -0,0 +1,39 @@
# 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
OPTS = [
cfg.StrOpt('transformer',
default='vitrage.synchronizer.plugins.aodh.'
'transformer.AodhTransformer',
help='Aodh plugin transformer class path',
required=True),
cfg.StrOpt('synchronizer',
default='vitrage.synchronizer.plugins.aodh.synchronizer'
'.AodhSynchronizer',
help='Aodh plugin synchronizer class path',
required=True),
cfg.IntOpt('changes_interval',
default=30,
min=30,
help='interval between checking changes in aodh plugin',
required=True),
cfg.StrOpt('user', default='admin', help='Aodh user name'),
cfg.StrOpt('password', default='password', help='Aodh user password'),
cfg.StrOpt('url', default='http://localhost:5000/v2.0/',
help='Aodh authentication url'),
cfg.StrOpt('version', default='2', help='Aodh version'),
cfg.StrOpt('project', default='admin', help='Aodh project'),
]

View File

@ -0,0 +1,38 @@
# 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 AodhProperties(object):
ALARM_ID = 'alarm_id'
DESCRIPTION = 'description'
ENABLED = 'enabled'
EVENT = 'event'
EVENT_TYPE = 'event_type'
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'
TIMESTAMP = 'timestamp'
TYPE = 'type'
class AodhState(object):
OK = 'ok'
ALARM = 'alarm'
INSUFFICIENT_DATA = 'insufficient_data'

View File

@ -0,0 +1,140 @@
# 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.
import traceback
from ceilometerclient import client
from oslo_log import log
from vitrage.common.constants import EntityType
from vitrage.synchronizer.plugins.aodh.properties import AodhProperties \
as AodhProps
from vitrage.synchronizer.plugins.aodh.properties import AodhState
from vitrage.synchronizer.plugins.base.alarm.synchronizer \
import BaseAlarmSynchronizer
LOG = log.getLogger(__name__)
class AodhSynchronizer(BaseAlarmSynchronizer):
def __init__(self, conf):
super(AodhSynchronizer, self).__init__()
version = conf[EntityType.AODH].version
user = conf[EntityType.AODH].user
password = conf[EntityType.AODH].password
project = conf[EntityType.AODH].project
auth_url = conf[EntityType.AODH].url
try:
self.client = client.Client(version,
None,
username=user,
password=password,
tenant_name=project,
auth_url=auth_url)
except Exception:
LOG.error("Failed to initialize ceilometer client. Exception: %s",
traceback.print_exc())
def _sync_type(self):
return EntityType.AODH
def _alarm_key(self, alarm):
return alarm[AodhProps.NAME]
def _get_alarms(self):
return []
# TODO(iafek): enable the code below
# try:
# aodh_alarms = self.client.alarms.list()
# return [_convert_alarm(alarm)
# for alarm in aodh_alarms]
# except Exception:
# LOG.error("Exception: %s", traceback.print_exc())
# return []
def _is_erroneous(self, alarm):
return alarm and alarm[AodhProps.STATE] != AodhState.OK
def _status_changed(self, alarm1, alarm2):
return alarm1 and alarm2 and \
not alarm1[AodhProps.STATE] == alarm2[AodhProps.STATE]
def _is_valid(self, alarm):
return True
@staticmethod
def _convert_event_alarm(alarm):
converted_alarm = AodhSynchronizer._convert_base_alarm(alarm)
event_type, resource_id = \
AodhSynchronizer._parse_event_rule(alarm.event_rule)
converted_alarm[AodhProps.EVENT_TYPE] = event_type
converted_alarm[AodhProps.RESOURCE_ID] = resource_id
return converted_alarm
@staticmethod
def _convert_threshold_alarm(alarm):
converted_alarm = AodhSynchronizer._convert_base_alarm(alarm)
converted_alarm[AodhProps.STATE_TIMESTAMP] = alarm.state_timestamp
converted_alarm[AodhProps.RESOURCE_ID] = \
AodhSynchronizer._parse_threshold_rule(alarm.threshold_rule)
return converted_alarm
@staticmethod
def _convert_base_alarm(alarm):
# TODO(iafek): what if the alarm state is 'insufficient data'
return {
AodhProps.DESCRIPTION: alarm.description,
AodhProps.ENABLED: alarm.enabled,
AodhProps.ALARM_ID: alarm.alarm_id,
AodhProps.NAME: alarm.name,
AodhProps.PROJECT_ID: alarm.project_id,
AodhProps.REPEAT_ACTIONS: alarm.repeat_actions,
AodhProps.SEVERITY: alarm.severity,
AodhProps.STATE: alarm.state,
AodhProps.TIMESTAMP: alarm.timestamp,
AodhProps.TYPE: alarm.type
}
@staticmethod
def _parse_event_rule(rule):
event_type = rule[AodhProps.EVENT_TYPE]
resource_id = \
AodhSynchronizer._parse_resource_id(rule[AodhProps.QUERY])
return event_type, resource_id
@staticmethod
def _parse_threshold_rule(rule):
return AodhSynchronizer._parse_resource_id(rule[AodhProps.QUERY])
@staticmethod
def _parse_resource_id(query_fields):
for query in query_fields:
field = query['field']
if field == AodhProps.RESOURCE_ID:
return query['value']
else:
return None
def _convert_alarm(alarm):
alarm_type = alarm.type
if alarm_type == AodhProps.EVENT:
return AodhSynchronizer._convert_event_alarm(alarm)
elif alarm_type == AodhProps.THRESHOLD:
return AodhSynchronizer._convert_threshold_alarm(alarm)
else:
LOG.info('Unsopported Aodh alarm of type %s' % alarm_type)

View File

@ -0,0 +1,87 @@
# 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_log import log as logging
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import SynchronizerProperties as SyncProps
from vitrage.common.constants import VertexProperties as VProps
from vitrage.common import datetime_utils
import vitrage.graph.utils as graph_utils
from vitrage.synchronizer.plugins.aodh.properties import AodhProperties \
as AodhProps
from vitrage.synchronizer.plugins.base.alarm.properties \
import AlarmProperties as AlarmProps
from vitrage.synchronizer.plugins.base.alarm.transformer \
import BaseAlarmTransformer
from vitrage.synchronizer.plugins import transformer_base as tbase
LOG = logging.getLogger(__name__)
class AodhTransformer(BaseAlarmTransformer):
STATUS_OK = 'ok'
def __init__(self, transformers):
super(AodhTransformer, self).__init__(transformers)
def _create_entity_vertex(self, entity_event):
metadata = {
VProps.NAME: entity_event[AodhProps.NAME],
VProps.SEVERITY: entity_event[AodhProps.SEVERITY],
AodhProps.DESCRIPTION: entity_event[AodhProps.DESCRIPTION],
AodhProps.ENABLED: entity_event[AodhProps.ENABLED],
VProps.PROJECT_ID: entity_event[AodhProps.PROJECT_ID],
AodhProps.REPEAT_ACTIONS: entity_event[AodhProps.REPEAT_ACTIONS],
'alarm_type': entity_event[AodhProps.TYPE]
}
if entity_event[AodhProps.TYPE] == AodhProps.EVENT:
metadata[AodhProps.EVENT_TYPE] = entity_event[AodhProps.EVENT_TYPE]
elif entity_event[AodhProps.TYPE] == AodhProps.THRESHOLD:
metadata[AodhProps.STATE_TIMESTAMP] = \
entity_event[AodhProps.STATE_TIMESTAMP]
return graph_utils.create_vertex(
self.extract_key(entity_event),
entity_id=entity_event[AodhProps.ALARM_ID],
entity_category=EntityCategory.ALARM,
entity_type=entity_event[SyncProps.SYNC_TYPE],
entity_state=AlarmProps.ALARM_STATE,
update_timestamp=AodhTransformer._timestamp(entity_event),
metadata=metadata)
def _create_neighbors(self, entity_event):
# TODO(iafek): get neighbour resource by its id
return []
def _ok_status(self, entity_event):
return entity_event[AodhProps.STATE] == self.STATUS_OK
def extract_key(self, entity_event):
sync_type = entity_event[SyncProps.SYNC_TYPE]
alarm_name = entity_event[AodhProps.NAME]
resource_id = entity_event[AodhProps.RESOURCE_ID]
return (tbase.build_key(self.key_values([sync_type,
resource_id,
alarm_name])) if resource_id
else tbase.build_key(self.key_values([sync_type, alarm_name])))
@staticmethod
def _timestamp(entity_event):
return datetime_utils.change_time_str_format(
entity_event[AodhProps.TIMESTAMP],
'%Y-%m-%dT%H:%M:%S.%f',
tbase.TIMESTAMP_FORMAT)

View File

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

View File

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

View File

@ -0,0 +1,18 @@
# 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.
__author__ = 'stack'
class AlarmProperties(object):
ALARM_STATE = 'Active'

View File

@ -0,0 +1,122 @@
# 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_log import log
from vitrage.synchronizer.plugins.synchronizer_base import SynchronizerBase
LOG = log.getLogger(__name__)
class BaseAlarmSynchronizer(SynchronizerBase):
def __init__(self):
super(SynchronizerBase, self).__init__()
self.cache = dict()
def _sync_type(self):
"""Return the type of the plugin """
pass
def _alarm_key(self, alarm):
"""Return a unique key of the alarm, to identify it in the cache """
pass
def _get_alarms(self):
"""Return the list of alarms of this plugin """
pass
def _enrich_alarms(self, alarms):
"""Optionally add more data to the alarms
:param alarms: list of alarms to be enriched
:return:
"""
pass
def _is_erroneous(self, alarm):
"""Check if the state of the alarm is erroneous
:param alarm:
:return: True/False based on the alarm state
"""
pass
def _status_changed(self, alarm1, alarm2):
"""Check if the status of the two alarms is different
:param alarm1:
:param alarm2:
:return: True/False based on the alarms states
"""
pass
def _is_valid(self, alarm):
"""Check if the alarm is valid
:param alarm: an alarm to check
:return: True/False
"""
pass
def get_all(self, sync_mode):
return self.make_pickleable(self._get_all_alarms(),
self._sync_type(),
sync_mode)
def get_changes(self, sync_mode):
return self.make_pickleable(self._get_changed_alarms(),
self._sync_type(),
sync_mode)
def _get_all_alarms(self):
alarms = self._get_alarms()
self._enrich_alarms(alarms)
return self._filter_and_cache_alarms(
alarms,
BaseAlarmSynchronizer._filter_get_all)
def _get_changed_alarms(self):
alarms = self._get_alarms()
self._enrich_alarms(alarms)
return self._filter_and_cache_alarms(
alarms,
BaseAlarmSynchronizer._filter_get_changes)
def _filter_and_cache_alarms(self, alarms, filter_):
alarms_to_update = []
for alarm in alarms:
alarm_key = self._alarm_key(alarm)
old_alarm = self.cache.get(alarm_key, None)
if filter_(self, alarm, old_alarm):
alarms_to_update.append(alarm)
self.cache[alarm_key] = alarm
return alarms_to_update
def _filter_get_all(self, alarm, old_alarm):
return alarm \
if self._is_valid(alarm) and \
(self._is_erroneous(alarm) or self._is_erroneous(old_alarm)) \
else None
def _filter_get_changes(self, alarm, old_alarm):
if not self._is_valid(alarm):
return None
if self._status_changed(alarm, old_alarm):
return alarm
elif not old_alarm and self._is_erroneous(alarm):
return alarm
else:
return None

View File

@ -0,0 +1,50 @@
# 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_log import log as logging
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import EventAction
from vitrage.common.constants import SynchronizerProperties as SyncProps
from vitrage.common.constants import SyncMode
from vitrage.common.exception import VitrageTransformerError
from vitrage.synchronizer.plugins import transformer_base as tbase
LOG = logging.getLogger(__name__)
class BaseAlarmTransformer(tbase.TransformerBase):
def __init__(self, transformers):
self.transformers = transformers
def _ok_status(self, entity_event):
pass
def create_placeholder_vertex(self, properties={}):
LOG.info('An alarm cannot be a placeholder')
pass
def _extract_action_type(self, entity_event):
sync_mode = entity_event[SyncProps.SYNC_MODE]
if sync_mode in (SyncMode.UPDATE, SyncMode.SNAPSHOT):
if self._ok_status(entity_event):
return EventAction.DELETE_ENTITY
else:
return EventAction.UPDATE_ENTITY
if SyncMode.INIT_SNAPSHOT == sync_mode:
return EventAction.CREATE_ENTITY
raise VitrageTransformerError('Invalid sync mode: (%s)' % sync_mode)
def key_values(self, mutable_fields=[]):
return [EntityCategory.ALARM] + mutable_fields

View File

@ -13,7 +13,6 @@
# under the License.
# TODO(ifat_afek): unite with nagios transformer properties
class NagiosProperties(object):
NUM_COLUMNS = 7
RESOURCE_TYPE = 'resource_type'

View File

@ -21,50 +21,33 @@ from vitrage.common.constants import EntityType
from vitrage.common.constants import SynchronizerProperties as SyncProps
from vitrage.i18n import _LE
from vitrage.i18n import _LW
from vitrage.synchronizer.plugins.base.alarm.synchronizer \
import BaseAlarmSynchronizer
from vitrage.synchronizer.plugins.nagios.config import NagiosConfig
from vitrage.synchronizer.plugins.nagios.parser import NagiosParser
from vitrage.synchronizer.plugins.nagios.properties import NagiosProperties \
as NagiosProps
from vitrage.synchronizer.plugins.nagios.properties import NagiosStatus
from vitrage.synchronizer.plugins.synchronizer_base import SynchronizerBase
LOG = log.getLogger(__name__)
class NagiosSynchronizer(SynchronizerBase):
class NagiosSynchronizer(BaseAlarmSynchronizer):
ServiceKey = namedtuple('ServiceKey', ['host_name', 'service'])
def __init__(self, conf):
super(NagiosSynchronizer, self).__init__()
self.conf = conf
self.cache = dict()
self.config = NagiosConfig(conf)
def get_all(self, sync_mode):
return self.make_pickleable(self._get_all_services(),
EntityType.NAGIOS,
sync_mode)
def _sync_type(self):
return EntityType.NAGIOS
def get_changes(self, sync_mode):
return self.make_pickleable(self._get_changed_services(),
EntityType.NAGIOS,
sync_mode)
def _alarm_key(self, alarm):
return self.ServiceKey(host_name=alarm[NagiosProps.RESOURCE_NAME],
service=alarm[NagiosProps.SERVICE])
def _get_all_services(self):
nagios_services = self._get_services_from_nagios()
self._enrich_services(nagios_services)
return self._filter_and_cache_services(
nagios_services,
NagiosSynchronizer._filter_get_all)
def _get_changed_services(self):
nagios_services = self._get_services_from_nagios()
self._enrich_services(nagios_services)
return self._filter_and_cache_services(
nagios_services,
NagiosSynchronizer._filter_get_changes)
def _get_services_from_nagios(self):
def _get_alarms(self):
nagios_user = self.conf.nagios.user
nagios_password = self.conf.nagios.password
nagios_url = self.conf.nagios.url
@ -95,59 +78,27 @@ class NagiosSynchronizer(SynchronizerBase):
response.status_code)
return []
def _enrich_services(self, nagios_services):
for service in nagios_services:
def _enrich_alarms(self, alarms):
for alarm in alarms:
# based on nagios configuration file, convert nagios host name
# to vitrage resource type and name
service[SyncProps.SYNC_TYPE] = NagiosProps.NAGIOS
alarm[SyncProps.SYNC_TYPE] = NagiosProps.NAGIOS
nagios_host = service[NagiosProps.RESOURCE_NAME]
nagios_host = alarm[NagiosProps.RESOURCE_NAME]
vitrage_resource = self.config.get_vitrage_resource(nagios_host)
service[NagiosProps.RESOURCE_TYPE] = \
alarm[NagiosProps.RESOURCE_TYPE] = \
vitrage_resource[0] if vitrage_resource else None
service[NagiosProps.RESOURCE_NAME] = \
vitrage_resource[1] if vitrage_resource \
else service[NagiosProps.RESOURCE_NAME]
alarm[NagiosProps.RESOURCE_NAME] = \
vitrage_resource[1] if vitrage_resource else None
def _filter_and_cache_services(self, nagios_services, filter_):
services_to_update = []
def _is_erroneous(self, alarm):
return alarm and alarm[NagiosProps.STATUS] != NagiosStatus.OK
for service in nagios_services:
service_key = self.ServiceKey(
host_name=service[NagiosProps.RESOURCE_NAME],
service=service[NagiosProps.SERVICE])
def _status_changed(self, alarm1, alarm2):
return alarm1 and alarm2 and \
not alarm1[NagiosProps.STATUS] == alarm2[NagiosProps.STATUS]
old_service = self.cache.get(service_key, None)
if filter_(service, old_service):
services_to_update.append(service)
self.cache[service_key] = service
return services_to_update
@staticmethod
def _filter_get_all(service, old_service):
return service \
if (NagiosSynchronizer._is_erroneous(service) or
NagiosSynchronizer._is_erroneous(old_service)) \
else None
@staticmethod
def _filter_get_changes(service, old_service):
if NagiosSynchronizer._status_changed(service, old_service):
return service
elif not old_service and NagiosSynchronizer._is_erroneous(service):
return service
else:
return None
@staticmethod
def _is_erroneous(service):
return service and service[NagiosProps.STATUS] != NagiosStatus.OK
@staticmethod
def _status_changed(service1, service2):
return service1 and service2 and \
not service1[NagiosProps.STATUS] == service2[NagiosProps.STATUS]
def _is_valid(self, alarm):
return alarm[NagiosProps.RESOURCE_TYPE] is not None and \
alarm[NagiosProps.RESOURCE_NAME] is not None

View File

@ -16,29 +16,26 @@ from oslo_log import log as logging
from vitrage.common.constants import EdgeLabels
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import EntityType
from vitrage.common.constants import EventAction
from vitrage.common.constants import SynchronizerProperties as SyncProps
from vitrage.common.constants import SyncMode
from vitrage.common.constants import VertexProperties as VProps
from vitrage.common import datetime_utils
from vitrage.common.exception import VitrageTransformerError
import vitrage.graph.utils as graph_utils
from vitrage.synchronizer.plugins.base.alarm.properties \
import AlarmProperties as AlarmProps
from vitrage.synchronizer.plugins.base.alarm.transformer \
import BaseAlarmTransformer
from vitrage.synchronizer.plugins.nagios.properties import NagiosProperties
from vitrage.synchronizer.plugins import transformer_base as tbase
LOG = logging.getLogger(__name__)
class NagiosTransformer(tbase.TransformerBase):
class NagiosTransformer(BaseAlarmTransformer):
STATUS_OK = 'OK'
NAGIOS_ALARM_STATE = 'Active'
def __init__(self, transformers):
self.transformers = transformers
def create_placeholder_vertex(self, properties={}):
LOG.info('Nagios alarm cannot be a placeholder')
super(NagiosTransformer, self).__init__(transformers)
def _create_entity_vertex(self, entity_event):
@ -57,7 +54,7 @@ class NagiosTransformer(tbase.TransformerBase):
self.extract_key(entity_event),
entity_category=EntityCategory.ALARM,
entity_type=entity_event[SyncProps.SYNC_TYPE],
entity_state=self.NAGIOS_ALARM_STATE,
entity_state=AlarmProps.ALARM_STATE,
update_timestamp=timestamp,
metadata=metadata)
@ -100,16 +97,8 @@ class NagiosTransformer(tbase.TransformerBase):
LOG.warning('Cannot transform host, host transformer does not exist')
return None
def _extract_action_type(self, entity_event):
sync_mode = entity_event[SyncProps.SYNC_MODE]
if sync_mode in (SyncMode.UPDATE, SyncMode.SNAPSHOT):
if entity_event[NagiosProperties.STATUS] == self.STATUS_OK:
return EventAction.DELETE_ENTITY
else:
return EventAction.UPDATE_ENTITY
if SyncMode.INIT_SNAPSHOT == sync_mode:
return EventAction.CREATE_ENTITY
raise VitrageTransformerError('Invalid sync mode: (%s)' % sync_mode)
def _ok_status(self, entity_event):
return entity_event[NagiosProperties.STATUS] == self.STATUS_OK
def extract_key(self, entity_event):
@ -119,6 +108,3 @@ class NagiosTransformer(tbase.TransformerBase):
return tbase.build_key(self.key_values([sync_type,
resource_name,
alarm_name]))
def key_values(self, mutable_fields=[]):
return [EntityCategory.ALARM] + mutable_fields

View File

@ -30,7 +30,7 @@ class NagiosSynchronizerWithMockData(NagiosSynchronizer):
def set_service_datas(self, service_datas):
self.service_datas = service_datas
def _get_services_from_nagios(self):
def _get_alarms(self):
alarms = []
for service_data in self.service_datas:
generators = mock_sync.simple_nagios_alarm_generators(

View File

@ -20,6 +20,8 @@ from vitrage.common.constants import EventAction
from vitrage.common.constants import SynchronizerProperties as SyncProps
from vitrage.common.constants import SyncMode
from vitrage.common.constants import VertexProperties as VProps
from vitrage.synchronizer.plugins.base.alarm.properties \
import AlarmProperties as AlarmProps
from vitrage.synchronizer.plugins.nagios.properties import NagiosProperties
from vitrage.synchronizer.plugins.nagios.transformer import NagiosTransformer
from vitrage.synchronizer.plugins.nova.host.transformer import HostTransformer
@ -102,8 +104,7 @@ class NagiosTransformerTest(base.BaseTest):
self.assertEqual(EntityCategory.ALARM, vertex[VProps.CATEGORY])
self.assertEqual(event[SyncProps.SYNC_TYPE], vertex[VProps.TYPE])
self.assertEqual(event[NagiosProperties.SERVICE], vertex[VProps.NAME])
self.assertEqual(NagiosTransformer.NAGIOS_ALARM_STATE,
vertex[VProps.STATE])
self.assertEqual(AlarmProps.ALARM_STATE, vertex[VProps.STATE])
self.assertEqual(event[NagiosProperties.STATUS],
vertex[VProps.SEVERITY])

View File

@ -28,11 +28,11 @@ LOG = logging.getLogger(__name__)
class NagiosSynchronizerTest(NagiosBaseTest):
OPTS = [
cfg.StrOpt(
'config_file',
default=utils.get_resources_dir() + '/nagios/nagios_conf.yaml',
help='Nagios configuation file'
),
cfg.StrOpt('config_file',
default=utils.get_resources_dir() +
'/nagios/nagios_conf.yaml',
help='Nagios configuation file'
),
]
@classmethod
@ -65,7 +65,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
# Services with status OK should not be returned
@ -87,7 +87,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -109,7 +109,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -132,7 +132,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
# The services of service_data1/2 should be returned although their
@ -143,7 +143,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self._assert_contains(service_data2, services)
# Action
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
# Calling get_services again should not return anything, since all
@ -176,7 +176,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
# Services with status OK should not be returned
@ -198,7 +198,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -220,7 +220,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -243,7 +243,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -265,7 +265,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -274,7 +274,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self._assert_contains(service_data2, services)
# Action
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'services is None')
@ -301,7 +301,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -309,7 +309,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self._assert_contains(service_data1, services)
# Action
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
# Calling get_changes for the second time should return nothing
@ -317,7 +317,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self.assertEqual(0, len(services))
# Action
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -325,7 +325,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self._assert_contains(service_data1, services)
# Action
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
# Calling get_all for the second time should return the same results
@ -348,7 +348,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -357,7 +357,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self._assert_contains(service_data2, services)
# Action
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
# Calling get_changes after get_all should return nothing
@ -365,7 +365,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self.assertEqual(0, len(services))
# Action
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
# Calling get_all for the second time should return the same results
@ -389,7 +389,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -412,7 +412,7 @@ class NagiosSynchronizerTest(NagiosBaseTest):
service_data2,
service_data3])
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'No services returned')
@ -420,14 +420,14 @@ class NagiosSynchronizerTest(NagiosBaseTest):
self._assert_contains(service_data1, services)
# Action
services = nagios_synchronizer._get_changed_services()
services = nagios_synchronizer._get_changed_alarms()
# Test assertions
self.assertIsNotNone(services, 'services is None')
self.assertEqual(0, len(services))
# Action
services = nagios_synchronizer._get_all_services()
services = nagios_synchronizer._get_all_alarms()
# Test assertions
# Calling get_all for the second time should return the same results