Merge "Datasource configurable update Method"
This commit is contained in:
commit
f870976e48
@ -7,11 +7,11 @@ Consolidate Zabbix alerts from across multiple sites into a single "at-a-glance"
|
||||
Installation
|
||||
------------
|
||||
|
||||
Copy the `zabbix_vitrage.py` script into the Zabbix servers' `AlertScriptsPath` directory which is by default `/etc/zabbix/alertscripts` and make it executable:
|
||||
Copy the `zabbix_vitrage.py` script into the Zabbix servers' `AlertScriptsPath` directory which is by default `/usr/lib/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
|
||||
| $ cp zabbix_vitrage.py /usr/lib/zabbix/alertscripts/
|
||||
| $ chmod 755 /usr/lib/zabbix/alertscripts/zabbix_vitrage.py
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
@ -71,6 +71,12 @@ class SyncMode(object):
|
||||
UPDATE = 'update'
|
||||
|
||||
|
||||
class UpdateMethod(object):
|
||||
NONE = 'none'
|
||||
PULL = 'pull'
|
||||
PUSH = 'push'
|
||||
|
||||
|
||||
class EntityCategory(object):
|
||||
RESOURCE = 'RESOURCE'
|
||||
ALARM = 'ALARM'
|
||||
|
@ -27,7 +27,6 @@ OPENSTACK_CLUSTER = 'openstack.cluster'
|
||||
|
||||
# Register options for the service
|
||||
OPTS = [
|
||||
|
||||
cfg.ListOpt('types',
|
||||
default=[NOVA_HOST_DATASOURCE,
|
||||
NOVA_INSTANCE_DATASOURCE,
|
||||
@ -44,5 +43,8 @@ OPTS = [
|
||||
cfg.IntOpt('snapshots_interval',
|
||||
default=600,
|
||||
min=10,
|
||||
help='interval between full snapshots')
|
||||
help='interval between full snapshots'),
|
||||
cfg.StrOpt('notification_topic',
|
||||
default='vitrage_notifications',
|
||||
help='Vitrage configured notifications topic')
|
||||
]
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
AODH_DATASOURCE = 'aodh'
|
||||
|
||||
@ -26,9 +27,15 @@ OPTS = [
|
||||
default='vitrage.datasources.aodh.driver.AodhDriver',
|
||||
help='Aodh driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PULL,
|
||||
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('changes_interval',
|
||||
default=20,
|
||||
min=20,
|
||||
help='interval between checking changes in aodh data source',
|
||||
required=True),
|
||||
help='interval between checking changes in aodh data source'),
|
||||
]
|
||||
|
@ -113,6 +113,10 @@ class AodhDriver(AlarmDriverBase):
|
||||
else:
|
||||
LOG.warning('Unsupported Aodh alarm of type %s' % alarm_type)
|
||||
|
||||
@staticmethod
|
||||
def get_update_method(conf):
|
||||
return conf[AODH_DATASOURCE].update_method
|
||||
|
||||
|
||||
def _parse_query(data, key):
|
||||
query_fields = data.get(AodhProps.QUERY, {})
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
CINDER_VOLUME_DATASOURCE = 'cinder.volume'
|
||||
|
||||
@ -27,7 +28,11 @@ OPTS = [
|
||||
'CinderVolumeDriver',
|
||||
help='Nova host driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('notification_topic',
|
||||
default='vitrage_notifications',
|
||||
help='Cinder configured notifications topic for Vitrage'),
|
||||
cfg.StrOpt('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),
|
||||
]
|
||||
|
@ -68,5 +68,5 @@ class CinderVolumeDriver(DriverBase):
|
||||
'volume.delete.end']
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return conf[CINDER_VOLUME_DATASOURCE].notification_topic
|
||||
def get_update_method(conf):
|
||||
return conf[CINDER_VOLUME_DATASOURCE].update_method
|
||||
|
@ -116,21 +116,16 @@ class DriverBase(object):
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def get_topic(conf):
|
||||
"""Return the topic of events processed by this driver
|
||||
def get_update_method(conf):
|
||||
"""Return the update method for this driver
|
||||
|
||||
Example:
|
||||
to listen to nova topic, add another topic to nova.conf so nova will
|
||||
notify the notifications to another queue.
|
||||
|
||||
example of nova.conf:
|
||||
notification_topics = notifications,new_topic
|
||||
|
||||
example of get_topic():
|
||||
return 'new_topic'
|
||||
update methods available are:
|
||||
None: updates only via overall snapshots
|
||||
Pull: updates every [changes_interval] seconds
|
||||
Push: updates by getting notifications from the datasource itself
|
||||
|
||||
:param conf: the datasource's configuration
|
||||
:return: the topic of the datasource
|
||||
:return: the update method of the datasource
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
|
@ -17,11 +17,12 @@ import itertools
|
||||
|
||||
from oslo_service import service as os_service
|
||||
from oslo_utils import importutils as utils
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
from vitrage.common.utils import opt_exists
|
||||
from vitrage.datasources.listener_service import ListenerService
|
||||
|
||||
from services import ChangesService
|
||||
from services import SnapshotsService
|
||||
from vitrage.common.utils import opt_exists
|
||||
from vitrage.datasources.services import ChangesService
|
||||
from vitrage.datasources.services import SnapshotsService
|
||||
|
||||
CHANGES_INTERVAL = 'changes_interval'
|
||||
|
||||
@ -37,7 +38,7 @@ class Launcher(object):
|
||||
def __init__(self, conf, callback):
|
||||
self.conf = conf
|
||||
self.callback = callback
|
||||
self.snapshot_datasources = self._register_snapshot_datasources()
|
||||
self.snapshot_datasources = self._register_snapshot_datasources(conf)
|
||||
self.services = self._register_services()
|
||||
|
||||
def launch(self):
|
||||
@ -45,25 +46,34 @@ class Launcher(object):
|
||||
for service in self.services:
|
||||
launcher.launch_service(service, 1)
|
||||
|
||||
def _register_snapshot_datasources(self):
|
||||
return {plugin: utils.import_object(self.conf[plugin].driver,
|
||||
self.conf)
|
||||
for plugin in self.conf.datasources.types}
|
||||
@staticmethod
|
||||
def _register_snapshot_datasources(conf):
|
||||
return {datasource: utils.import_object(conf[datasource].driver, conf)
|
||||
for datasource in conf.datasources.types}
|
||||
|
||||
def _register_services(self):
|
||||
return itertools.chain(
|
||||
pull_datasources = self._get_pull_datasources(self.conf)
|
||||
changes_services = \
|
||||
(ChangesService(self.conf,
|
||||
[self.snapshot_datasources[plugin]],
|
||||
self.conf[plugin].changes_interval,
|
||||
[self.snapshot_datasources[datasource]],
|
||||
self.conf[datasource].changes_interval,
|
||||
self.callback)
|
||||
for datasource in pull_datasources)
|
||||
|
||||
for plugin in self.conf.datasources.types
|
||||
if opt_exists(self.conf[plugin], CHANGES_INTERVAL)),
|
||||
snapshot_service = (SnapshotsService(self.conf,
|
||||
self.snapshot_datasources,
|
||||
self.callback),)
|
||||
|
||||
(SnapshotsService(self.conf,
|
||||
self.snapshot_datasources,
|
||||
self.callback),),
|
||||
listener_service = (ListenerService(self.conf,
|
||||
self.snapshot_datasources,
|
||||
self.callback),)
|
||||
|
||||
(ListenerService(self.conf,
|
||||
self.snapshot_datasources,
|
||||
self.callback),),)
|
||||
return itertools.chain(changes_services,
|
||||
snapshot_service,
|
||||
listener_service)
|
||||
|
||||
@staticmethod
|
||||
def _get_pull_datasources(conf):
|
||||
return (datasource for datasource in conf.datasources.types
|
||||
if conf[datasource].update_method.lower() == UpdateMethod.PULL
|
||||
and opt_exists(conf[datasource], CHANGES_INTERVAL))
|
||||
|
@ -18,6 +18,7 @@ from oslo_log import log
|
||||
import oslo_messaging
|
||||
from oslo_service import service as os_service
|
||||
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
from vitrage import messaging
|
||||
|
||||
|
||||
@ -29,12 +30,11 @@ class ListenerService(os_service.Service):
|
||||
def __init__(self, conf, drivers, callback):
|
||||
super(ListenerService, self).__init__()
|
||||
|
||||
# Get the topics of the drivers and callbacks
|
||||
topics = self._get_topics_set(drivers, conf)
|
||||
self.enrich_callbacks_by_events = \
|
||||
self._create_callbacks_by_events_dict(drivers, conf)
|
||||
|
||||
self.listener = self._get_topics_listener(conf, topics, callback)
|
||||
topic = conf.datasources.notification_topic
|
||||
self.listener = self._get_topic_listener(conf, topic, callback)
|
||||
|
||||
def start(self):
|
||||
LOG.info("Vitrage data source Listener Service - Starting...")
|
||||
@ -51,36 +51,31 @@ class ListenerService(os_service.Service):
|
||||
|
||||
LOG.info("Vitrage data source Listener Service - Stopped!")
|
||||
|
||||
@staticmethod
|
||||
def _get_topics_set(drivers, conf):
|
||||
topics = {driver.get_topic(conf) for driver in drivers.values()}
|
||||
|
||||
if None in topics:
|
||||
topics.remove(None)
|
||||
|
||||
return topics
|
||||
|
||||
@staticmethod
|
||||
def _create_callbacks_by_events_dict(drivers, conf):
|
||||
@classmethod
|
||||
def _create_callbacks_by_events_dict(cls, drivers, conf):
|
||||
ret = defaultdict(list)
|
||||
push_drivers = cls._get_push_drivers(drivers, conf)
|
||||
|
||||
for driver in drivers.values():
|
||||
for driver in push_drivers:
|
||||
for event in driver.get_event_types(conf):
|
||||
ret[event].append(driver.enrich_event)
|
||||
|
||||
return ret
|
||||
|
||||
def _get_topics_listener(self, conf, topics, callback):
|
||||
@staticmethod
|
||||
def _get_push_drivers(drivers, conf):
|
||||
return (driver for driver in drivers.values()
|
||||
if driver.get_update_method(conf).lower() == UpdateMethod.PUSH)
|
||||
|
||||
def _get_topic_listener(self, conf, topic, callback):
|
||||
# Create a listener for each topic
|
||||
transport = messaging.get_transport(conf)
|
||||
targets = [oslo_messaging.Target(topic=topic, exchange='nova')
|
||||
for topic in topics]
|
||||
targets = [oslo_messaging.Target(topic=topic, exchange='nova')]
|
||||
|
||||
return messaging.get_notification_listener(
|
||||
transport,
|
||||
targets,
|
||||
[NotificationsEndpoint(self.enrich_callbacks_by_events,
|
||||
callback)])
|
||||
[NotificationsEndpoint(self.enrich_callbacks_by_events, callback)])
|
||||
|
||||
|
||||
class NotificationsEndpoint(object):
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
NAGIOS_DATASOURCE = 'nagios'
|
||||
|
||||
@ -26,11 +27,17 @@ OPTS = [
|
||||
default='vitrage.datasources.nagios.driver.NagiosDriver',
|
||||
help='Nagios driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PULL,
|
||||
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('changes_interval',
|
||||
default=30,
|
||||
min=30,
|
||||
help='interval between checking changes in nagios data source',
|
||||
required=True),
|
||||
help='interval between checking changes in nagios data source'),
|
||||
cfg.StrOpt('user', default='nagiosadmin',
|
||||
help='Nagios user name'),
|
||||
cfg.StrOpt('password', default='nagiosadmin',
|
||||
|
@ -103,3 +103,7 @@ class NagiosDriver(AlarmDriverBase):
|
||||
def _is_valid(self, alarm):
|
||||
return alarm[NagiosProps.RESOURCE_TYPE] is not None and \
|
||||
alarm[NagiosProps.RESOURCE_NAME] is not None
|
||||
|
||||
@staticmethod
|
||||
def get_update_method(conf):
|
||||
return conf[NAGIOS_DATASOURCE].update_method
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
NEUTRON_NETWORK_DATASOURCE = 'neutron.network'
|
||||
|
||||
@ -27,8 +28,11 @@ OPTS = [
|
||||
'NetworkDriver',
|
||||
help='Neutron network driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('notification_topic',
|
||||
default='vitrage_notifications',
|
||||
help='Neutron network configured notifications topic for '
|
||||
'Vitrage'),
|
||||
cfg.StrOpt('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),
|
||||
]
|
||||
|
@ -22,8 +22,8 @@ from vitrage.datasources.neutron.network import NEUTRON_NETWORK_DATASOURCE
|
||||
class NetworkDriver(NeutronBase):
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return conf[NEUTRON_NETWORK_DATASOURCE].notification_topic
|
||||
def get_update_method(conf):
|
||||
return conf[NEUTRON_NETWORK_DATASOURCE].update_method
|
||||
|
||||
@staticmethod
|
||||
def get_event_types(conf):
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
NEUTRON_PORT_DATASOURCE = 'neutron.port'
|
||||
|
||||
@ -26,7 +27,11 @@ OPTS = [
|
||||
default='vitrage.datasources.neutron.port.driver.PortDriver',
|
||||
help='Neutron port driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('notification_topic',
|
||||
default='vitrage_notifications',
|
||||
help='Neutron port configured notifications topic for Vitrage'),
|
||||
cfg.StrOpt('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),
|
||||
]
|
||||
|
@ -22,8 +22,8 @@ from vitrage.datasources.neutron.port import NEUTRON_PORT_DATASOURCE
|
||||
class PortDriver(NeutronBase):
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return conf[NEUTRON_PORT_DATASOURCE].notification_topic
|
||||
def get_update_method(conf):
|
||||
return conf[NEUTRON_PORT_DATASOURCE].update_method
|
||||
|
||||
@staticmethod
|
||||
def get_event_types(conf):
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
NOVA_HOST_DATASOURCE = 'nova.host'
|
||||
|
||||
@ -26,4 +27,11 @@ OPTS = [
|
||||
default='vitrage.datasources.nova.host.driver.HostDriver',
|
||||
help='Nova host driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.NONE,
|
||||
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),
|
||||
]
|
||||
|
@ -27,6 +27,10 @@ class HostDriver(NovaDriverBase):
|
||||
compute_hosts.append(host_dict)
|
||||
return compute_hosts
|
||||
|
||||
@staticmethod
|
||||
def get_update_method(conf):
|
||||
return conf[NOVA_HOST_DATASOURCE].update_method
|
||||
|
||||
def get_all(self, sync_mode):
|
||||
return self.make_pickleable(
|
||||
self.filter_none_compute_hosts(self.client.hosts.list()),
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
NOVA_INSTANCE_DATASOURCE = 'nova.instance'
|
||||
|
||||
@ -27,7 +28,11 @@ OPTS = [
|
||||
'InstanceDriver',
|
||||
help='Nova instance driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('notification_topic',
|
||||
default='vitrage_notifications',
|
||||
help='Nova configured notifications topic for Vitrage'),
|
||||
cfg.StrOpt('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),
|
||||
]
|
||||
|
@ -69,5 +69,5 @@ class InstanceDriver(NovaDriverBase):
|
||||
'compute.instance.unpause.end']
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return conf[NOVA_INSTANCE_DATASOURCE].notification_topic
|
||||
def get_update_method(conf):
|
||||
return conf[NOVA_INSTANCE_DATASOURCE].update_method
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
NOVA_ZONE_DATASOURCE = 'nova.zone'
|
||||
|
||||
@ -27,4 +28,11 @@ OPTS = [
|
||||
'.ZoneDriver',
|
||||
help='Nova zone datasource class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.NONE,
|
||||
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),
|
||||
]
|
||||
|
@ -27,6 +27,10 @@ class ZoneDriver(NovaDriverBase):
|
||||
zones_res.append(zone_dict)
|
||||
return zones_res
|
||||
|
||||
@staticmethod
|
||||
def get_update_method(conf):
|
||||
return conf[NOVA_ZONE_DATASOURCE].update_method
|
||||
|
||||
def get_all(self, sync_mode):
|
||||
return self.make_pickleable(self.filter_internal_zone(
|
||||
self.client.availability_zones.list()),
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
STATIC_PHYSICAL_DATASOURCE = 'static_physical'
|
||||
SWITCH = 'switch'
|
||||
@ -28,12 +29,18 @@ OPTS = [
|
||||
'StaticPhysicalDriver',
|
||||
help='Static physical driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PULL,
|
||||
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('changes_interval',
|
||||
default=20,
|
||||
min=5,
|
||||
help='interval between checking changes in the configuration '
|
||||
'files of the physical topology data sources',
|
||||
required=True),
|
||||
'files of the physical topology data sources'),
|
||||
cfg.StrOpt('directory', default='/etc/vitrage/static_datasources',
|
||||
help='Static physical data sources directory'),
|
||||
cfg.ListOpt('entities',
|
||||
|
@ -33,8 +33,8 @@ class StaticPhysicalDriver(DriverBase):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return None
|
||||
def get_update_method(conf):
|
||||
return conf[STATIC_PHYSICAL_DATASOURCE].update_method
|
||||
|
||||
ENTITIES_SECTION = 'entities'
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
|
||||
ZABBIX_DATASOURCE = 'zabbix'
|
||||
|
||||
@ -26,11 +27,17 @@ OPTS = [
|
||||
default='vitrage.datasources.zabbix.driver.ZabbixDriver',
|
||||
help='Zabbix driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('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('changes_interval',
|
||||
default=30,
|
||||
min=30,
|
||||
help='interval between checking changes in zabbix data source',
|
||||
required=True),
|
||||
min=10,
|
||||
help='interval between checking changes in zabbix data source'),
|
||||
cfg.StrOpt('user', default='admin',
|
||||
help='Zabbix user name'),
|
||||
cfg.StrOpt('password', default='zabbix',
|
||||
@ -39,7 +46,4 @@ 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'),
|
||||
]
|
||||
|
@ -10,11 +10,11 @@ Installation
|
||||
------------
|
||||
|
||||
Copy the 'zabbix_vitrage.py' script into the Zabbix servers' 'AlertScriptsPath'
|
||||
directory which is by default '/etc/zabbix/alertscripts' and make it executable:
|
||||
directory which is by default '/usr/lib/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
|
||||
$ cp zabbix_vitrage.py /usr/lib/zabbix/alertscripts/
|
||||
$ chmod 755 /usr/lib/zabbix/alertscripts/zabbix_vitrage.py
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
@ -19,6 +19,7 @@
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
import logging
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from oslo_config import cfg
|
||||
import oslo_messaging as messaging
|
||||
import six
|
||||
@ -47,6 +48,7 @@ Message:
|
||||
|
||||
|
||||
LOG_FILE = '/var/log/zabbix/zabbix_vitrage.log'
|
||||
LOG_MAX_SIZE = 10240
|
||||
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'
|
||||
@ -68,17 +70,16 @@ def main():
|
||||
|
||||
transport_url = args.sendto
|
||||
transport = messaging.get_transport(cfg.CONF, transport_url)
|
||||
driver = 'messaging'
|
||||
driver = 'messagingv2'
|
||||
publisher = 'zabbix_%s' % socket.gethostname()
|
||||
notifier = messaging.Notifier(transport,
|
||||
driver=driver,
|
||||
publisher_id='zabbix',
|
||||
publisher_id=publisher,
|
||||
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())}
|
||||
|
||||
@ -99,5 +100,9 @@ if __name__ == '__main__':
|
||||
else:
|
||||
logging.basicConfig(filename=LOG_FILE, format=LOG_FORMAT,
|
||||
datefmt=LOG_DATE_FMT, level=logging.DEBUG)
|
||||
|
||||
log = logging.getLogger()
|
||||
handler = RotatingFileHandler(filename=LOG_FILE,
|
||||
maxBytes=LOG_MAX_SIZE,
|
||||
backupCount=1)
|
||||
log.addHandler(handler)
|
||||
main()
|
||||
|
@ -187,5 +187,5 @@ class ZabbixDriver(AlarmDriverBase):
|
||||
return ['zabbix.alarm.ok', 'zabbix.alarm.problem']
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return conf[ZABBIX_DATASOURCE].notification_topic
|
||||
def get_update_method(conf):
|
||||
return conf[ZABBIX_DATASOURCE].update_method
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from vitrage.datasources.nagios.driver import NagiosDriver
|
||||
from vitrage.datasources.nagios import NAGIOS_DATASOURCE
|
||||
from vitrage.tests.mocks import mock_driver
|
||||
|
||||
|
||||
@ -32,8 +33,8 @@ class MockNagiosDriver(NagiosDriver):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return None
|
||||
def get_update_method(conf):
|
||||
return conf[NAGIOS_DATASOURCE].update_method
|
||||
|
||||
def __init__(self, conf):
|
||||
super(MockNagiosDriver, self).__init__(conf)
|
||||
|
197
vitrage/tests/unit/datasources/test_datasource_update_method.py
Normal file
197
vitrage/tests/unit/datasources/test_datasource_update_method.py
Normal file
@ -0,0 +1,197 @@
|
||||
# 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 oslo_log import log as logging
|
||||
from oslo_utils import importutils as utils
|
||||
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
from vitrage.datasources.launcher import Launcher
|
||||
from vitrage.datasources.listener_service import ListenerService
|
||||
from vitrage.datasources.nagios import NAGIOS_DATASOURCE
|
||||
from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
|
||||
from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
|
||||
from vitrage.datasources.zabbix import ZABBIX_DATASOURCE
|
||||
from vitrage.tests import base
|
||||
|
||||
|
||||
CHANGES_INTERVAL = 'changes_interval'
|
||||
LOG = logging.getLogger(__name__)
|
||||
ZABBIX_DATASOURCE_NONE = '_'.join((ZABBIX_DATASOURCE, UpdateMethod.NONE))
|
||||
ZABBIX_DATASOURCE_PULL = '_'.join((ZABBIX_DATASOURCE, UpdateMethod.PULL))
|
||||
ZABBIX_DATASOURCE_PUSH = ZABBIX_DATASOURCE
|
||||
ZABBIX_DATASOURCE_PULL_NO_INTERVAL = \
|
||||
'_'.join((ZABBIX_DATASOURCE, UpdateMethod.PULL, 'no_interval'))
|
||||
|
||||
|
||||
class DatasourceUpdateMethod(base.BaseTest):
|
||||
|
||||
DATASOURCES_OPTS = [
|
||||
cfg.ListOpt('types',
|
||||
default=[NOVA_HOST_DATASOURCE,
|
||||
NOVA_INSTANCE_DATASOURCE,
|
||||
NAGIOS_DATASOURCE,
|
||||
ZABBIX_DATASOURCE_NONE,
|
||||
ZABBIX_DATASOURCE_PULL,
|
||||
ZABBIX_DATASOURCE_PUSH,
|
||||
ZABBIX_DATASOURCE_PULL_NO_INTERVAL],
|
||||
help='Names of supported data sources'),
|
||||
cfg.StrOpt('notification_topic',
|
||||
default='vitrage_notifications',
|
||||
help='Vitrage configured notifications topic')
|
||||
]
|
||||
|
||||
NOVA_HOST_OPTS = [
|
||||
cfg.StrOpt('driver',
|
||||
default='vitrage.datasources.nova.host.driver.HostDriver',
|
||||
help='Nova host driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.NONE,
|
||||
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),
|
||||
]
|
||||
|
||||
NOVA_INSTANCE_OPTS = [
|
||||
cfg.StrOpt('driver',
|
||||
default='vitrage.datasources.nova.instance.driver.'
|
||||
'InstanceDriver',
|
||||
help='Nova instance driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PUSH,
|
||||
required=True),
|
||||
]
|
||||
|
||||
NAGIOS_OPTS = [
|
||||
cfg.StrOpt('driver',
|
||||
default='vitrage.datasources.nagios.driver.NagiosDriver',
|
||||
help='Nagios driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PULL,
|
||||
required=True),
|
||||
cfg.IntOpt('changes_interval',
|
||||
default=30,
|
||||
min=30,
|
||||
help='interval between checking changes in nagios'
|
||||
' data source'),
|
||||
]
|
||||
|
||||
ZABBIX_OPTS_PUSH = [
|
||||
cfg.StrOpt('driver',
|
||||
default='vitrage.datasources.zabbix.driver.ZabbixDriver',
|
||||
help='Zabbix driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PUSH,
|
||||
required=True),
|
||||
cfg.IntOpt('changes_interval',
|
||||
default=30,
|
||||
min=30,
|
||||
help='interval between checking changes in zabbix'
|
||||
' data source'),
|
||||
]
|
||||
|
||||
ZABBIX_OPTS_PULL = [
|
||||
cfg.StrOpt('driver',
|
||||
default='vitrage.datasources.zabbix.driver.ZabbixDriver',
|
||||
help='Zabbix driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PULL,
|
||||
required=True),
|
||||
cfg.IntOpt('changes_interval',
|
||||
default=30,
|
||||
min=30,
|
||||
help='interval between checking changes in zabbix'
|
||||
' data source'),
|
||||
]
|
||||
|
||||
ZABBIX_OPTS_PULL_NO_INTERVAL = [
|
||||
cfg.StrOpt('driver',
|
||||
default='vitrage.datasources.zabbix.driver.ZabbixDriver',
|
||||
help='Zabbix driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.PULL,
|
||||
required=True),
|
||||
]
|
||||
|
||||
ZABBIX_OPTS_NONE = [
|
||||
cfg.StrOpt('driver',
|
||||
default='vitrage.datasources.zabbix.driver.ZabbixDriver',
|
||||
help='Zabbix driver class path',
|
||||
required=True),
|
||||
cfg.StrOpt('update_method',
|
||||
default=UpdateMethod.NONE,
|
||||
required=True),
|
||||
cfg.IntOpt('changes_interval',
|
||||
default=30,
|
||||
min=30,
|
||||
help='interval between checking changes in zabbix'
|
||||
' data source'),
|
||||
]
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.conf = cfg.ConfigOpts()
|
||||
cls.conf.register_opts(cls.DATASOURCES_OPTS, group='datasources')
|
||||
cls.conf.register_opts(cls.NOVA_HOST_OPTS, group=NOVA_HOST_DATASOURCE)
|
||||
cls.conf.register_opts(cls.NOVA_INSTANCE_OPTS,
|
||||
group=NOVA_INSTANCE_DATASOURCE)
|
||||
cls.conf.register_opts(cls.NAGIOS_OPTS, group=NAGIOS_DATASOURCE)
|
||||
cls.conf.register_opts(cls.ZABBIX_OPTS_NONE,
|
||||
group=ZABBIX_DATASOURCE_NONE)
|
||||
cls.conf.register_opts(cls.ZABBIX_OPTS_PULL,
|
||||
group=ZABBIX_DATASOURCE_PULL)
|
||||
cls.conf.register_opts(cls.ZABBIX_OPTS_PUSH,
|
||||
group=ZABBIX_DATASOURCE_PUSH)
|
||||
cls.conf.register_opts(cls.ZABBIX_OPTS_PULL_NO_INTERVAL,
|
||||
group=ZABBIX_DATASOURCE_PULL_NO_INTERVAL)
|
||||
|
||||
def test_datasource_update_method_none(self):
|
||||
none_drivers = tuple(driver for driver in self.conf.datasources.types
|
||||
if self.conf[driver].update_method
|
||||
== UpdateMethod.NONE)
|
||||
self.assertSequenceEqual(none_drivers,
|
||||
(NOVA_HOST_DATASOURCE,
|
||||
ZABBIX_DATASOURCE_NONE))
|
||||
|
||||
def test_datasource_update_method_push(self):
|
||||
drivers = {driver: utils.import_class(self.conf[driver].driver)
|
||||
for driver in self.conf.datasources.types}
|
||||
push_drivers = ListenerService._get_push_drivers(
|
||||
drivers=drivers, conf=self.conf)
|
||||
self.assertSequenceEqual(set(push_drivers), {utils.import_class(
|
||||
self.conf[NOVA_INSTANCE_DATASOURCE].driver), utils.import_class(
|
||||
self.conf[ZABBIX_DATASOURCE_PUSH].driver)})
|
||||
|
||||
def test_datasource_update_method_pull(self):
|
||||
pull_drivers = tuple(Launcher._get_pull_datasources(self.conf))
|
||||
self.assertSequenceEqual(pull_drivers,
|
||||
(NAGIOS_DATASOURCE,
|
||||
ZABBIX_DATASOURCE_PULL))
|
||||
|
||||
def test_datasource_update_method_pull_with_no_changes_interval(self):
|
||||
pull_drivers = tuple(Launcher._get_pull_datasources(self.conf))
|
||||
self.assertNotIn(ZABBIX_DATASOURCE_PULL_NO_INTERVAL, pull_drivers)
|
||||
|
||||
def test_datasources_notification_topic(self):
|
||||
self.assertEqual(self.conf.datasources.notification_topic,
|
||||
'vitrage_notifications')
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from vitrage.datasources.zabbix.driver import ZabbixDriver
|
||||
from vitrage.datasources.zabbix import ZABBIX_DATASOURCE
|
||||
from vitrage.tests.mocks import mock_driver
|
||||
|
||||
|
||||
@ -32,8 +33,8 @@ class MockZabbixDriver(ZabbixDriver):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_topic(conf):
|
||||
return None
|
||||
def get_update_method(conf):
|
||||
return conf[ZABBIX_DATASOURCE].update_method
|
||||
|
||||
def __init__(self, conf):
|
||||
super(MockZabbixDriver, self).__init__(conf)
|
||||
|
Loading…
x
Reference in New Issue
Block a user