From b5458fccb8e2991f1aa812418f74499abc9c2869 Mon Sep 17 00:00:00 2001 From: Noam Bloom Date: Mon, 25 Jul 2016 11:27:25 +0000 Subject: [PATCH] Zabbix to Vitrage notifications Change-Id: Ifff3c49b3dd38e9196ac96bb45ae93477334e321 --- doc/source/zabbix_vitrage.rst | 72 +++++ vitrage/common/datetime_utils.py | 5 + vitrage/datasources/zabbix/__init__.py | 3 + vitrage/datasources/zabbix/auxiliary/readme | 76 +++++ .../zabbix/auxiliary/zabbix_vitrage.py | 103 ++++++ vitrage/datasources/zabbix/driver.py | 91 +++--- vitrage/datasources/zabbix/properties.py | 32 +- vitrage/datasources/zabbix/transformer.py | 62 ++-- .../driver_zabbix_snapshot_dynamic.json | 4 +- .../zabbix/test_zabbix_configuration.py | 7 - .../datasources/zabbix/test_zabbix_driver.py | 302 ++++++++++-------- .../zabbix/test_zabbix_transformer.py | 42 ++- 12 files changed, 585 insertions(+), 214 deletions(-) create mode 100644 doc/source/zabbix_vitrage.rst create mode 100644 vitrage/datasources/zabbix/auxiliary/readme create mode 100644 vitrage/datasources/zabbix/auxiliary/zabbix_vitrage.py diff --git a/doc/source/zabbix_vitrage.rst b/doc/source/zabbix_vitrage.rst new file mode 100644 index 000000000..b66e30f53 --- /dev/null +++ b/doc/source/zabbix_vitrage.rst @@ -0,0 +1,72 @@ +Zabbix-Vitrage Gateway +====================== + +Consolidate Zabbix alerts from across multiple sites into a single "at-a-glance" console by using a custom Zabbix [alertscript](https://www.zabbix.com/documentation/3.0/manual/config/notifications/media/script). + + +Installation +------------ + +Copy the `zabbix_vitrage.py` script into the Zabbix servers' `AlertScriptsPath` directory which is by default `/etc/zabbix/alertscripts` and make it executable: + +| $ wget https://github.com/openstack/vitrage/tree/master/vitrage/datasources/zabbix/auxiliary/zabbix_vitrage.py +| $ cp zabbix_vitrage.py /etc/zabbix/alertscripts/ +| $ chmod 755 /etc/zabbix/alertscripts/zabbix_vitrage.py + +Configuration +------------- + +To forward zabbix events to Vitrage a new media script needs to be created and associated with a user. Follow the steps below as a Zabbix Admin user: + +1. Create a new media type [Admininstration > Media Types > Create Media Type] + + + | Name: Vitrage Notifications + | Type: Script + | Script name: zabbix_vitrage.py + | Script parameters: + | 1st: {ALERT.SENDTO} + | 2nd: {ALERT.SUBJECT} + | 3rd: {ALERT.MESSAGE} + + +2. Modify the Media for the Admin user [Administration > Users] + + | Type: vitrage Notifications + | Send to: rabbit://rabbit_user:rabbit_pass@127.0.0.1:5672/ <--- Vitrage message bus url + | When active: 1-7,00:00-24:00 + | Use if severity: (all) + | Status: Enabled + +3. Configure Action [Configuration > Actions > Create Action > Action] + + | Name: Forward to Vitrage + | Default Subject: {TRIGGER.STATUS} + + | Default Message: + + | host={HOST.NAME1} + | hostid={HOST.ID1} + | hostip={HOST.IP1} + | id={TRIGGER.ID} + | description={TRIGGER.NAME} + | rawtext={TRIGGER.NAME.ORIG} + | expression={TRIGGER.EXPRESSION} + | value={TRIGGER.VALUE} + | priority={TRIGGER.NSEVERITY} + | lastchange={EVENT.DATE} {EVENT.TIME} + +For a full list of trigger macros see https://www.zabbix.com/documentation/3.0/manual/appendix/macros/supported_by_location + +To send events add under the Conditions tab: + +(A) Maintenance status not in `maintenance` + +Finally, add an operation: + +Send to Users: Admin +Send only to: Vitrage Notifications + +DONE +---- + diff --git a/vitrage/common/datetime_utils.py b/vitrage/common/datetime_utils.py index 930230ada..2ae899a78 100644 --- a/vitrage/common/datetime_utils.py +++ b/vitrage/common/datetime_utils.py @@ -23,3 +23,8 @@ def utcnow(with_timezone=True): def change_time_str_format(timestamp_str, old_format, new_format): utc = datetime.strptime(timestamp_str, old_format) return utc.strftime(new_format) + + +def format_unix_timestamp(timestamp, date_format): + return datetime.fromtimestamp(float(timestamp)) \ + .strftime(date_format) diff --git a/vitrage/datasources/zabbix/__init__.py b/vitrage/datasources/zabbix/__init__.py index 19fca6626..fba50697c 100644 --- a/vitrage/datasources/zabbix/__init__.py +++ b/vitrage/datasources/zabbix/__init__.py @@ -39,4 +39,7 @@ OPTS = [ help='Zabbix url'), cfg.StrOpt('config_file', default='/etc/vitrage/zabbix_conf.yaml', help='Zabbix configuration file'), + cfg.StrOpt('notification_topic', + default='vitrage_notifications', + help='Zabbix configured notifications topic for Vitrage'), ] diff --git a/vitrage/datasources/zabbix/auxiliary/readme b/vitrage/datasources/zabbix/auxiliary/readme new file mode 100644 index 000000000..0a1e20675 --- /dev/null +++ b/vitrage/datasources/zabbix/auxiliary/readme @@ -0,0 +1,76 @@ +Zabbix-Vitrage Gateway +====================== + +Consolidate Zabbix alerts from across multiple sites into a single "at-a-glance" +console by using a custom Zabbix [alertscript]. +(https://www.zabbix.com/documentation/3.0/manual/config/notifications/media/script) + + +Installation +------------ + +Copy the 'zabbix_vitrage.py' script into the Zabbix servers' 'AlertScriptsPath' +directory which is by default '/etc/zabbix/alertscripts' and make it executable: + + $ wget https://github.com/openstack/vitrage/tree/master/vitrage/datasources/zabbix/auxiliary/zabbix_vitrage.py + $ cp zabbix_vitrage.py /etc/zabbix/alertscripts/ + $ chmod 755 /etc/zabbix/alertscripts/zabbix_vitrage.py + +Configuration +------------- + +To forward zabbix events to Vitrage a new media script needs to be created and +associated with a user. Follow the steps below as a Zabbix Admin user: + +1. Create a new media type [Admininstration > Media Types > Create Media Type] + + + Name: Vitrage Notifications + Type: Script + Script name: zabbix_vitrage.py + Script parameters: + 1st: {ALERT.SENDTO} + 2nd: {ALERT.SUBJECT} + 3rd: {ALERT.MESSAGE} + + +2. Modify the Media for the Admin user [Administration > Users] + + Type: Vitrage Notifications + Send to: rabbit://rabbit_user:rabbit_pass@127.0.0.1:5672/ <--- Vitrage message bus url + When active: 1-7,00:00-24:00 + Use if severity: (all) + Status: Enabled + +3. Configure Action [Configuration > Actions > Create Action > Action] + + Name: Forward to Vitrage + Default Subject: {TRIGGER.STATUS} + + Default Message: + + host={HOST.NAME1} + hostid={HOST.ID1} + hostip={HOST.IP1} + id={TRIGGER.ID} + description={TRIGGER.NAME} + rawtext={TRIGGER.NAME.ORIG} + expression={TRIGGER.EXPRESSION} + value={TRIGGER.VALUE} + priority={TRIGGER.NSEVERITY} + lastchange={EVENT.DATE} {EVENT.TIME} + +For a full list of trigger macros see +https://www.zabbix.com/documentation/3.0/manual/appendix/macros/supported_by_location + +To send events add under the Conditions tab: + +(A) Maintenance status not in `maintenance` + +Finally, add an operation: + +Send to Users: Admin +Send only to: Vitrage Notifications + +DONE + diff --git a/vitrage/datasources/zabbix/auxiliary/zabbix_vitrage.py b/vitrage/datasources/zabbix/auxiliary/zabbix_vitrage.py new file mode 100644 index 000000000..b8ccc2e7c --- /dev/null +++ b/vitrage/datasources/zabbix/auxiliary/zabbix_vitrage.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +# coding: utf-8 + +# Copyright 2016 - Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import argparse +from datetime import datetime +import logging +from oslo_config import cfg +import oslo_messaging as messaging +import six +import socket +import sys +import uuid + +''' +Expected input: +Send To: +Vitrage Message Bus address e.g. +rabbit://userrabbit:passrabbit@127.0.0.1:5672/ +Subject: {TRIGGER.STATUS} +Message: + host={HOST.NAME1} + hostid={HOST.ID1} + hostip={HOST.IP1} + id={TRIGGER.ID} + description={TRIGGER.NAME} + rawtext={TRIGGER.NAME.ORIG} + expression={TRIGGER.EXPRESSION} + value={TRIGGER.VALUE} + priority={TRIGGER.NSEVERITY} + lastchange={EVENT.DATE} {EVENT.TIME} +''' + + +LOG_FILE = '/var/log/zabbix/zabbix_vitrage.log' +LOG_FORMAT = '%(asctime)s.%(msecs).03d %(name)s[%(process)d] %(threadName)s %' \ + '(levelname)s - %(message)s' +LOG_DATE_FMT = '%Y.%m.%d %H:%M:%S' +ZABBIX_EVENT_TYPE = 'zabbix.alarm' + +debug = False + + +def main(): + + parser = argparse.ArgumentParser() + parser.add_argument('sendto', help='Vitrage message bus path') + parser.add_argument('topic', help='zabbix topic') + parser.add_argument('body', help='zabbix body') + args = parser.parse_args() + + logging.debug('[vitrage] sendto=%s, topic=%s, body=%s', + args.sendto, args.topic, args.body) + + transport_url = args.sendto + transport = messaging.get_transport(cfg.CONF, transport_url) + driver = 'messaging' + notifier = messaging.Notifier(transport, + driver=driver, + publisher_id='zabbix', + topic='vitrage_notifications') + + alarm_status = args.topic.lower() + event_type = '%s.%s' % (ZABBIX_EVENT_TYPE, alarm_status) + + publisher = 'zabbix_%s' % socket.gethostname() + + payload = {key.lower().strip(): prop.strip() for key, prop in + (line.split('=') for line in args.body.splitlines())} + + logging.debug('[vitrage] publisher: %s, event: %s, payload %s', + publisher, event_type, payload) + + notifier.info(ctxt={'message_id': six.text_type(uuid.uuid4()), + 'publisher_id': publisher, + 'timestamp': datetime.utcnow()}, + event_type=event_type, + payload=payload) + +if __name__ == '__main__': + + if debug: + logging.basicConfig(stream=sys.stderr, format=LOG_FORMAT, + datefmt=LOG_DATE_FMT, level=logging.DEBUG) + else: + logging.basicConfig(filename=LOG_FILE, format=LOG_FORMAT, + datefmt=LOG_DATE_FMT, level=logging.DEBUG) + + main() diff --git a/vitrage/datasources/zabbix/driver.py b/vitrage/datasources/zabbix/driver.py index 9063b2fbd..7cf74ace5 100644 --- a/vitrage/datasources/zabbix/driver.py +++ b/vitrage/datasources/zabbix/driver.py @@ -17,11 +17,16 @@ from collections import namedtuple from oslo_log import log from pyzabbix import ZabbixAPI +from vitrage.common.constants import DatasourceProperties as DSProps +from vitrage.common.constants import SyncMode from vitrage.common import file_utils from vitrage.datasources.alarm_driver_base import AlarmDriverBase from vitrage.datasources.zabbix.properties import ZabbixProperties \ as ZabbixProps -from vitrage.datasources.zabbix.properties import ZabbixTriggerStatus +from vitrage.datasources.zabbix.properties import ZabbixTriggerStatus \ + as TriggerStatus +from vitrage.datasources.zabbix.properties import ZabbixTriggerValue \ + as TriggerValue from vitrage.datasources.zabbix import ZABBIX_DATASOURCE LOG = log.getLogger(__name__) @@ -29,12 +34,14 @@ LOG = log.getLogger(__name__) class ZabbixDriver(AlarmDriverBase): ServiceKey = namedtuple('ServiceKey', ['host_name', 'service']) + conf_map = None def __init__(self, conf): super(ZabbixDriver, self).__init__() self.conf = conf - self.configuration_mapping = self._configuration_mapping(conf) - self.status_mapping = self._status_mapping() + if ZabbixDriver.conf_map is None: + ZabbixDriver.conf_map =\ + ZabbixDriver._configuration_mapping(conf) self.client = None def _sync_type(self): @@ -66,56 +73,53 @@ class ZabbixDriver(AlarmDriverBase): self.client.login(zabbix_user, zabbix_password) alarms = [] - hosts = self.client.host.get() - for host in hosts: - if host[ZabbixProps.HOST] in self.configuration_mapping: - self._get_triggers_per_host(host, alarms) + valid_hosts = (host for host in + self.client.host.get(output=[ZabbixProps.HOST]) + if host[ZabbixProps.HOST] in ZabbixDriver.conf_map) + for host in valid_hosts: + self._get_triggers_per_host(host, alarms) return alarms + def _get_triggers_per_host(self, host, alarms): + host_id = host[ZabbixProps.HOST_ID] + triggers = self.client.trigger.get(hostids=host_id) + + for trigger in triggers: + trigger[ZabbixProps.RESOURCE_NAME] = host[ZabbixProps.HOST] + alarms.append(trigger) + def _enrich_alarms(self, alarms): for alarm in alarms: # based on zabbix configuration file, convert zabbix host name # to vitrage resource type and name zabbix_host = alarm[ZabbixProps.RESOURCE_NAME] - vitrage_resource = self.configuration_mapping[zabbix_host] + vitrage_resource = ZabbixDriver.conf_map[zabbix_host] - alarm[ZabbixProps.STATUS] = \ - self._get_status(alarm) + alarm[ZabbixProps.VALUE] = self._get_value(alarm) alarm[ZabbixProps.RESOURCE_TYPE] = \ vitrage_resource[ZabbixProps.RESOURCE_TYPE] alarm[ZabbixProps.RESOURCE_NAME] = \ vitrage_resource[ZabbixProps.RESOURCE_NAME] def _is_erroneous(self, alarm): - return alarm and alarm[ZabbixProps.STATUS] != ZabbixTriggerStatus.OK + return alarm and \ + alarm[ZabbixProps.VALUE] == TriggerValue.PROBLEM def _status_changed(self, alarm1, alarm2): - return alarm1 and alarm2 and \ - not alarm1[ZabbixProps.STATUS] == alarm2[ZabbixProps.STATUS] + return (alarm1 and alarm2) and \ + (alarm1[ZabbixProps.VALUE] != alarm2[ZabbixProps.VALUE] or + alarm1[ZabbixProps.PRIORITY] != alarm2[ZabbixProps.PRIORITY]) def _is_valid(self, alarm): return alarm[ZabbixProps.RESOURCE_TYPE] is not None and \ alarm[ZabbixProps.RESOURCE_NAME] is not None - def _get_status(self, alarm): - if alarm[ZabbixProps.IS_ALARM_DISABLED] == '1' or \ - alarm[ZabbixProps.IS_ALARM_ON] == '0': - return ZabbixTriggerStatus.OK - - return self.status_mapping[alarm[ZabbixProps.SEVERITY]] - @staticmethod - def _status_mapping(): - return { - '-1': ZabbixTriggerStatus.OK, - '0': ZabbixTriggerStatus.NOT_CLASSIFIED, - '1': ZabbixTriggerStatus.INFORMATION, - '2': ZabbixTriggerStatus.WARNING, - '3': ZabbixTriggerStatus.AVERAGE, - '4': ZabbixTriggerStatus.HIGH, - '5': ZabbixTriggerStatus.DISASTER - } + def _get_value(alarm): + if alarm[ZabbixProps.STATUS] == TriggerStatus.DISABLED: + return TriggerValue.OK + return alarm[ZabbixProps.VALUE] @staticmethod def _configuration_mapping(conf): @@ -136,9 +140,24 @@ class ZabbixDriver(AlarmDriverBase): LOG.exception('failed in init %s ', e) return {} - def _get_triggers_per_host(self, host, alarms): - host_ids = host[ZabbixProps.HOST_ID] - triggers = self.client.trigger.get(hostids=host_ids) - for trigger in triggers: - trigger[ZabbixProps.RESOURCE_NAME] = host[ZabbixProps.HOST] - alarms.append(trigger) + @staticmethod + def enrich_event(event, event_type): + event[DSProps.EVENT_TYPE] = event_type + if ZabbixDriver.conf_map: + zabbix_host = event[ZabbixProps.HOST] + vitrage_resource = ZabbixDriver.conf_map[zabbix_host] + event[ZabbixProps.RESOURCE_NAME] = \ + vitrage_resource[ZabbixProps.RESOURCE_NAME] + event[ZabbixProps.RESOURCE_TYPE] = \ + vitrage_resource[ZabbixProps.RESOURCE_TYPE] + return ZabbixDriver.make_pickleable([event], ZABBIX_DATASOURCE, + SyncMode.UPDATE)[0] + + @staticmethod + def get_event_types(conf): + return ['zabbix.alarm.ok', + 'zabbix.alarm.problem'] + + @staticmethod + def get_topic(conf): + return conf[ZABBIX_DATASOURCE].notification_topic diff --git a/vitrage/datasources/zabbix/properties.py b/vitrage/datasources/zabbix/properties.py index 1d32e44ff..ed7c1a16a 100644 --- a/vitrage/datasources/zabbix/properties.py +++ b/vitrage/datasources/zabbix/properties.py @@ -18,19 +18,43 @@ class ZabbixProperties(object): RESOURCE_NAME = 'resource_name' DESCRIPTION = 'description' STATUS = 'status' + VALUE = 'value' HOST = 'host' HOST_ID = 'hostid' - IS_ALARM_DISABLED = 'status' - IS_ALARM_ON = 'value' - SEVERITY = 'priority' + PRIORITY = 'priority' LAST_CHANGE = 'lastchange' + TIMESTAMP = 'timestamp' + ZABBIX_TIMESTAMP_FORMAT = '%Y.%m.%d %H:%M:%S' + + +class ZabbixTriggerValue(object): + OK = '0' + PROBLEM = '1' class ZabbixTriggerStatus(object): - OK = 'OK' + ENABLED = '0' + DISABLED = '1' + + +class ZabbixTriggerSeverity(object): + INFORMATION = 'INFORMATION' WARNING = 'WARNING' AVERAGE = 'AVERAGE' HIGH = 'HIGH' DISASTER = 'DISASTER' NOT_CLASSIFIED = 'NOT CLASSIFIED' + + _SEVERITY_MAPPING = { + '0': NOT_CLASSIFIED, + '1': INFORMATION, + '2': WARNING, + '3': AVERAGE, + '4': HIGH, + '5': DISASTER + } + + @staticmethod + def str(num): + return ZabbixTriggerSeverity._SEVERITY_MAPPING[num] diff --git a/vitrage/datasources/zabbix/transformer.py b/vitrage/datasources/zabbix/transformer.py index b89d42968..08ca74cdf 100644 --- a/vitrage/datasources/zabbix/transformer.py +++ b/vitrage/datasources/zabbix/transformer.py @@ -18,14 +18,22 @@ 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 VertexProperties as VProps +from vitrage.common.datetime_utils import change_time_str_format +from vitrage.common.datetime_utils import format_unix_timestamp from vitrage.datasources.alarm_properties import AlarmProperties as AlarmProps from vitrage.datasources.alarm_transformer_base import AlarmTransformerBase from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources.static_physical import SWITCH from vitrage.datasources import transformer_base as tbase from vitrage.datasources.transformer_base import Neighbor -from vitrage.datasources.zabbix.properties import ZabbixProperties -from vitrage.datasources.zabbix.properties import ZabbixTriggerStatus +from vitrage.datasources.zabbix.properties import ZabbixProperties \ + as ZabbixProps +from vitrage.datasources.zabbix.properties import ZabbixTriggerSeverity \ + as TriggerSeverity +from vitrage.datasources.zabbix.properties import ZabbixTriggerValue\ + as TriggerValue + + import vitrage.graph.utils as graph_utils LOG = logging.getLogger(__name__) @@ -43,25 +51,23 @@ class ZabbixTransformer(AlarmTransformerBase): return self._create_vertex(entity_event) def _create_vertex(self, entity_event): - # TODO(Alexey): need to check the correct format for the date - # update_timestamp = datetime_utils.change_time_str_format( - # entity_event[ZabbixProperties.LAST_CHANGE], - # '%Y-%m-%d %H:%M:%S', - # tbase.TIMESTAMP_FORMAT) - update_timestamp = entity_event[ZabbixProperties.LAST_CHANGE] + self._unify_time_format(entity_event) + + update_timestamp = entity_event[ZabbixProps.TIMESTAMP] sample_timestamp = entity_event[DSProps.SAMPLE_DATE] update_timestamp = self._format_update_timestamp(update_timestamp, sample_timestamp) - severity = entity_event[ZabbixProperties.STATUS] + value = entity_event[ZabbixProps.VALUE] entity_state = AlarmProps.INACTIVE_STATE if \ - severity == ZabbixTriggerStatus.OK else AlarmProps.ACTIVE_STATE + value == TriggerValue.OK else AlarmProps.ACTIVE_STATE metadata = { - VProps.NAME: entity_event[ZabbixProperties.DESCRIPTION], - VProps.SEVERITY: severity + VProps.NAME: entity_event[ZabbixProps.DESCRIPTION], + VProps.SEVERITY: TriggerSeverity.str( + entity_event[ZabbixProps.PRIORITY]) } return graph_utils.create_vertex( @@ -80,21 +86,18 @@ class ZabbixTransformer(AlarmTransformerBase): return self._create_zabbix_neighbors(entity_event) def _create_zabbix_neighbors(self, entity_event): - vitrage_id = self._create_entity_key(entity_event) - # TODO(Alexey): need to check the correct format for the date - # timestamp = datetime_utils.change_time_str_format( - # entity_event[ZabbixProperties.LAST_CHANGE], - # '%Y-%m-%d %H:%M:%S', - # tbase.TIMESTAMP_FORMAT) - timestamp = entity_event[DSProps.SAMPLE_DATE] + self._unify_time_format(entity_event) - resource_type = entity_event[ZabbixProperties.RESOURCE_TYPE] + vitrage_id = self._create_entity_key(entity_event) + timestamp = entity_event[ZabbixProps.TIMESTAMP] + + resource_type = entity_event[ZabbixProps.RESOURCE_TYPE] if resource_type == NOVA_HOST_DATASOURCE or resource_type == SWITCH: return [self._create_neighbor( vitrage_id, timestamp, resource_type, - entity_event[ZabbixProperties.RESOURCE_NAME])] + entity_event[ZabbixProps.RESOURCE_NAME])] return [] @@ -125,13 +128,24 @@ class ZabbixTransformer(AlarmTransformerBase): return None def _ok_status(self, entity_event): - return entity_event[ZabbixProperties.STATUS] == ZabbixTriggerStatus.OK + return entity_event[ZabbixProps.VALUE] == TriggerValue.OK def _create_entity_key(self, entity_event): sync_type = entity_event[DSProps.SYNC_TYPE] - alarm_name = entity_event[ZabbixProperties.DESCRIPTION] - resource_name = entity_event[ZabbixProperties.RESOURCE_NAME] + alarm_name = entity_event[ZabbixProps.DESCRIPTION] + resource_name = entity_event[ZabbixProps.RESOURCE_NAME] return tbase.build_key(self._key_values(sync_type, resource_name, alarm_name)) + + @staticmethod + def _unify_time_format(entity_event): + try: + entity_event[ZabbixProps.TIMESTAMP] = format_unix_timestamp( + entity_event[ZabbixProps.LAST_CHANGE], tbase.TIMESTAMP_FORMAT) + except ValueError: + entity_event[ZabbixProps.TIMESTAMP] = change_time_str_format( + entity_event[ZabbixProps.LAST_CHANGE], + ZabbixProps.ZABBIX_TIMESTAMP_FORMAT, + tbase.TIMESTAMP_FORMAT) diff --git a/vitrage/tests/resources/mock_configurations/driver/driver_zabbix_snapshot_dynamic.json b/vitrage/tests/resources/mock_configurations/driver/driver_zabbix_snapshot_dynamic.json index 1766c8396..4133d7076 100644 --- a/vitrage/tests/resources/mock_configurations/driver/driver_zabbix_snapshot_dynamic.json +++ b/vitrage/tests/resources/mock_configurations/driver/driver_zabbix_snapshot_dynamic.json @@ -3,8 +3,10 @@ "resource_type": "nova\\.host", "resource_name": "compute-[1-9]", "description": "CPU utilization|Check_MK|Uptime", + "name": "CPU utilization|Check_MK|Uptime", + "lastchange": "1469450551", + "timestamp": "2015.12.01 12:46:41", "status": "0", - "lastchange": "2016-02-07 15:26:04", "sample_date": "2015-12-01T12:46:41Z", "value": "1", "priority": "1|2|3|4|5", diff --git a/vitrage/tests/unit/datasources/zabbix/test_zabbix_configuration.py b/vitrage/tests/unit/datasources/zabbix/test_zabbix_configuration.py index 11196f200..e819e7e89 100644 --- a/vitrage/tests/unit/datasources/zabbix/test_zabbix_configuration.py +++ b/vitrage/tests/unit/datasources/zabbix/test_zabbix_configuration.py @@ -87,13 +87,6 @@ class TestZabbixConfig(base.BaseTest): for expected_mapping in self.NON_EXISTING_MAPPINGS.items(): self.assertFalse(self._check_contains(expected_mapping, mappings)) - def test_zabbix_status_mapping(self): - # Action - mappings = ZabbixDriver._status_mapping() - - # Test assertions - self.assertEqual(7, len(mappings)) - @staticmethod def _check_contains(expected_mapping, mappings): for mapping in mappings.items(): diff --git a/vitrage/tests/unit/datasources/zabbix/test_zabbix_driver.py b/vitrage/tests/unit/datasources/zabbix/test_zabbix_driver.py index 0285b6922..c1779afbc 100644 --- a/vitrage/tests/unit/datasources/zabbix/test_zabbix_driver.py +++ b/vitrage/tests/unit/datasources/zabbix/test_zabbix_driver.py @@ -49,24 +49,24 @@ class ZabbixDriverTest(ZabbixBaseTest): alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization 1', - ZabbixProps.IS_ALARM_DISABLED: '1', - ZabbixProps.IS_ALARM_ON: '0', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.STATUS: '1', + ZabbixProps.VALUE: '0', + ZabbixProps.PRIORITY: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization 2', - ZabbixProps.IS_ALARM_DISABLED: '1', - ZabbixProps.IS_ALARM_ON: '1', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.STATUS: '1', + ZabbixProps.VALUE: '1', + ZabbixProps.PRIORITY: '1'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization 3', - ZabbixProps.IS_ALARM_DISABLED: '0', - ZabbixProps.IS_ALARM_ON: '1', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.STATUS: '0', + ZabbixProps.VALUE: '1', + ZabbixProps.PRIORITY: '1'} alarm_data4 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization 4', - ZabbixProps.IS_ALARM_DISABLED: '0', - ZabbixProps.IS_ALARM_ON: '0', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.STATUS: '0', + ZabbixProps.VALUE: '0', + ZabbixProps.PRIORITY: '1'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -75,7 +75,7 @@ class ZabbixDriverTest(ZabbixBaseTest): expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization 3', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1'} # Action alarms = zabbix_driver._get_all_alarms() @@ -100,13 +100,13 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -122,13 +122,14 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.VALUE: '1', + ZabbixProps.PRIORITY: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -144,54 +145,58 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.VALUE: '1', + ZabbixProps.PRIORITY: '4'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.VALUE: '1', + ZabbixProps.PRIORITY: '1'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, alarm_data3]) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} - excpected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.VALUE: '1', + ZabbixProps.PRIORITY: '4'} + expected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.VALUE: '1', + ZabbixProps.PRIORITY: '1'} alarms = zabbix_driver._get_all_alarms() # Test assertions self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(2, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, alarm_data3]) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} - excpected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.VALUE: '0'} + expected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.VALUE: '0'} alarms = zabbix_driver._get_all_alarms() @@ -200,8 +205,8 @@ class ZabbixDriverTest(ZabbixBaseTest): # status is OK, because they were not OK earlier self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(2, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) # Action alarms = zabbix_driver._get_all_alarms() @@ -225,13 +230,16 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '2', + ZabbixProps.VALUE: '0'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '2', + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -247,13 +255,16 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '2', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '2', + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -269,88 +280,102 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, alarm_data3]) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} - excpected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} + expected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarms = zabbix_driver._get_changed_alarms() # Test assertions self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(2, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, alarm_data3]) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarms = zabbix_driver._get_changed_alarms() # Test assertions self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(1, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) + self._assert_contains(expected_alarm1, alarms) # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '0'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, alarm_data3]) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} - excpected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '0'} + expected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '0'} alarms = zabbix_driver._get_changed_alarms() # Test assertions self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(2, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) # Action alarms = zabbix_driver._get_changed_alarms() @@ -368,13 +393,16 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '2', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '2', + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -415,32 +443,37 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, alarm_data3]) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} - excpected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} + expected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarms = zabbix_driver._get_all_alarms() # Test assertions self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(2, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) # Action alarms = zabbix_driver._get_changed_alarms() @@ -457,49 +490,57 @@ class ZabbixDriverTest(ZabbixBaseTest): # Calling get_all for the second time should return the same results self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(2, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, alarm_data3]) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} - excpected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '4'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} + expected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'Uptime', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarms = zabbix_driver._get_changed_alarms() # Test assertions self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(2, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -507,7 +548,8 @@ class ZabbixDriverTest(ZabbixBaseTest): expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarms = zabbix_driver._get_changed_alarms() @@ -516,15 +558,18 @@ class ZabbixDriverTest(ZabbixBaseTest): self.assertEqual(1, len(alarms)) self._assert_contains(expected_alarm1, alarms) - excpected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} - excpected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', - ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '4'} + expected_alarm1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} + expected_alarm2 = {ZabbixProps.RESOURCE_NAME: 'host2', + ZabbixProps.DESCRIPTION: 'CPU utilization', + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} excpected_alarm3 = {ZabbixProps.RESOURCE_NAME: 'host2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '4'} + ZabbixProps.PRIORITY: '4', + ZabbixProps.VALUE: '1'} # Action alarms = zabbix_driver._get_changed_alarms() @@ -540,8 +585,8 @@ class ZabbixDriverTest(ZabbixBaseTest): # Calling get_all for the second time should return the same results self.assertIsNotNone(alarms, 'No alarms returned') self.assertEqual(3, len(alarms)) - self._assert_contains(excpected_alarm1, alarms) - self._assert_contains(excpected_alarm2, alarms) + self._assert_contains(expected_alarm1, alarms) + self._assert_contains(expected_alarm2, alarms) self._assert_contains(excpected_alarm3, alarms) def test_delete_alarm(self): @@ -553,13 +598,14 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} alarm_data3 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'Uptime', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2, @@ -575,10 +621,12 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action - delete a alarm that was OK alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2]) @@ -592,7 +640,8 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action - delete a alarm that was not OK alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data2]) @@ -615,10 +664,12 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action - "undelete" the alarm that was OK alarm_data1 = {ZabbixProps.RESOURCE_NAME: 'compute-1', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '1'} alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data1, alarm_data2]) @@ -633,7 +684,8 @@ class ZabbixDriverTest(ZabbixBaseTest): # Action - delete a alarm that was not OK and call get_changes alarm_data2 = {ZabbixProps.RESOURCE_NAME: 'compute-2', ZabbixProps.DESCRIPTION: 'CPU utilization', - ZabbixProps.SEVERITY: '-1'} + ZabbixProps.PRIORITY: '1', + ZabbixProps.VALUE: '0'} zabbix_driver.set_alarm_datas([alarm_data2]) diff --git a/vitrage/tests/unit/datasources/zabbix/test_zabbix_transformer.py b/vitrage/tests/unit/datasources/zabbix/test_zabbix_transformer.py index 19bc7c3e3..aee703b96 100644 --- a/vitrage/tests/unit/datasources/zabbix/test_zabbix_transformer.py +++ b/vitrage/tests/unit/datasources/zabbix/test_zabbix_transformer.py @@ -20,13 +20,16 @@ from vitrage.common.constants import EntityCategory from vitrage.common.constants import EventAction from vitrage.common.constants import SyncMode from vitrage.common.constants import VertexProperties as VProps +from vitrage.common.datetime_utils import format_unix_timestamp from vitrage.datasources.alarm_properties import AlarmProperties as AlarmProps from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources.nova.host.transformer import HostTransformer +from vitrage.datasources import transformer_base as tbase from vitrage.datasources.transformer_base import TransformerBase -from vitrage.datasources.zabbix.driver import ZabbixDriver -from vitrage.datasources.zabbix.properties import ZabbixProperties -from vitrage.datasources.zabbix.properties import ZabbixTriggerStatus +from vitrage.datasources.zabbix.properties import ZabbixProperties\ + as ZabbixProps +from vitrage.datasources.zabbix.properties import ZabbixTriggerSeverity +from vitrage.datasources.zabbix.properties import ZabbixTriggerValue from vitrage.datasources.zabbix.transformer import ZabbixTransformer from vitrage.tests import base from vitrage.tests.mocks import mock_driver as mock_sync @@ -54,6 +57,7 @@ class ZabbixTransformerTest(base.BaseTest): zabbix_alarms = mock_sync.generate_sequential_events_list(spec_list) transformer = ZabbixTransformer(self.transformers) event = zabbix_alarms[0] + self.enrich_event(event) # Test action observed_key = transformer._create_entity_key(event) @@ -64,9 +68,9 @@ class ZabbixTransformerTest(base.BaseTest): self.assertEqual(EntityCategory.ALARM, observed_key_fields[0]) self.assertEqual(event[DSProps.SYNC_TYPE], observed_key_fields[1]) - self.assertEqual(event[ZabbixProperties.RESOURCE_NAME], + self.assertEqual(event[ZabbixProps.RESOURCE_NAME], observed_key_fields[2]) - self.assertEqual(event[ZabbixProperties.DESCRIPTION], + self.assertEqual(event[ZabbixProps.DESCRIPTION], observed_key_fields[3]) def test_zabbix_alarm_transform(self): @@ -77,13 +81,9 @@ class ZabbixTransformerTest(base.BaseTest): events_num=10) zabbix_alarms = mock_sync.generate_sequential_events_list(spec_list) - # convert to correct status - for alar in zabbix_alarms: - alar[ZabbixProperties.STATUS] = \ - ZabbixDriver._status_mapping()[alar[ZabbixProperties.SEVERITY]] - for alarm in zabbix_alarms: # Test action + self.enrich_event(alarm, format_timestamp=False) wrapper = ZabbixTransformer(self.transformers).transform(alarm) self._validate_vertex(wrapper.vertex, alarm) @@ -100,7 +100,7 @@ class ZabbixTransformerTest(base.BaseTest): def _validate_action(self, alarm, wrapper): sync_mode = alarm[DSProps.SYNC_MODE] if sync_mode in (SyncMode.SNAPSHOT, SyncMode.UPDATE): - if alarm[ZabbixProperties.STATUS] == 'OK': + if alarm[ZabbixProps.VALUE] == ZabbixTriggerValue.OK: self.assertEqual(EventAction.DELETE_ENTITY, wrapper.action) else: self.assertEqual(EventAction.UPDATE_ENTITY, wrapper.action) @@ -111,19 +111,21 @@ class ZabbixTransformerTest(base.BaseTest): self.assertEqual(EntityCategory.ALARM, vertex[VProps.CATEGORY]) self.assertEqual(event[DSProps.SYNC_TYPE], vertex[VProps.TYPE]) - self.assertEqual(event[ZabbixProperties.DESCRIPTION], + self.assertEqual(event[ZabbixProps.DESCRIPTION], vertex[VProps.NAME]) - event_status = event[ZabbixProperties.STATUS] + event_status = event[ZabbixProps.VALUE] - if event_status == ZabbixTriggerStatus.OK: + if event_status == ZabbixTriggerValue.OK: self.assertEqual(AlarmProps.INACTIVE_STATE, vertex[VProps.STATE]) else: self.assertEqual(AlarmProps.ACTIVE_STATE, vertex[VProps.STATE]) - self.assertEqual(event_status, vertex[VProps.SEVERITY]) + event_severity = ZabbixTriggerSeverity.str( + event[ZabbixProps.PRIORITY]) + self.assertEqual(event_severity, vertex[VProps.SEVERITY]) self.assertFalse(vertex[VProps.IS_DELETED]) self.assertFalse(vertex[VProps.IS_PLACEHOLDER]) @@ -136,13 +138,13 @@ class ZabbixTransformerTest(base.BaseTest): self.assertEqual(EntityCategory.RESOURCE, key_fields[0]) self.assertEqual(NOVA_HOST_DATASOURCE, key_fields[1]) - self.assertEqual(event[ZabbixProperties.RESOURCE_NAME], key_fields[2]) + self.assertEqual(event[ZabbixProps.RESOURCE_NAME], key_fields[2]) self.assertFalse(host_vertex[VProps.IS_DELETED]) self.assertTrue(host_vertex[VProps.IS_PLACEHOLDER]) self.assertEqual(EntityCategory.RESOURCE, host_vertex[VProps.CATEGORY]) - self.assertEqual(event[ZabbixProperties.RESOURCE_NAME], + self.assertEqual(event[ZabbixProps.RESOURCE_NAME], host_vertex[VProps.ID]) self.assertEqual(NOVA_HOST_DATASOURCE, host_vertex[VProps.TYPE]) @@ -153,3 +155,9 @@ class ZabbixTransformerTest(base.BaseTest): ZabbixTransformer(self.transformers)._create_entity_key(event) self.assertEqual(alarm_key, edge.source_id) self.assertEqual(host_vertex.vertex_id, edge.target_id) + + @staticmethod + def enrich_event(event, format_timestamp=True): + if format_timestamp: + event[ZabbixProps.TIMESTAMP] = format_unix_timestamp( + event[ZabbixProps.LAST_CHANGE], tbase.TIMESTAMP_FORMAT)