From af6c343efedb26feba521f3583d1dde1798037c9 Mon Sep 17 00:00:00 2001 From: slivik Date: Wed, 27 Feb 2019 17:58:03 +0100 Subject: [PATCH] Added validation of zabbix_host to support hostnames, IPv4 and IPv6. Changed exception logging. Doc typo fixed. Signed-off-by: slivik (cherry picked from commit c5e74c9f296f51554713ccc605c52f6e32445bc5) --- doc/mgr/zabbix.rst | 2 +- src/pybind/mgr/zabbix/module.py | 38 ++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/doc/mgr/zabbix.rst b/doc/mgr/zabbix.rst index 7d574c167cbfb..1aa3ebfcf7e57 100644 --- a/doc/mgr/zabbix.rst +++ b/doc/mgr/zabbix.rst @@ -113,7 +113,7 @@ For example: :: -ceph zabbix config-set zabbix_host "zabbix1,zabbix2:2222,zabbix3:3333" + ceph zabbix config-set zabbix_host "zabbix1,zabbix2:2222,zabbix3:3333" Manually sending data diff --git a/src/pybind/mgr/zabbix/module.py b/src/pybind/mgr/zabbix/module.py index 7a2beff7098e9..de4a2e196223b 100644 --- a/src/pybind/mgr/zabbix/module.py +++ b/src/pybind/mgr/zabbix/module.py @@ -6,6 +6,7 @@ server using the zabbix_sender executable. """ import json import errno +import re from subprocess import Popen, PIPE from threading import Event from mgr_module import MgrModule @@ -51,6 +52,7 @@ class Module(MgrModule): run = False config = dict() ceph_health_mapping = {'HEALTH_OK': 0, 'HEALTH_WARN': 1, 'HEALTH_ERR': 2} + _zabbix_hosts = list() @property def config_keys(self): @@ -112,6 +114,9 @@ class Module(MgrModule): for key, default in self.config_keys.items(): self.set_config_option(key, self.get_module_option(key, default)) + if self.config['zabbix_host']: + self._parse_zabbix_hosts() + def set_config_option(self, option, value): if option not in self.config_keys.keys(): raise RuntimeError('{0} is a unknown configuration ' @@ -132,6 +137,20 @@ class Module(MgrModule): self.config[option] = value return True + def _parse_zabbix_hosts(self): + self._zabbix_hosts = list() + servers = self.config['zabbix_host'].split(",") + for server in servers: + uri = re.match("(?:(?:\[?)([a-z0-9-\.]+|[a-f0-9:\.]+)(?:\]?))(?:((?::))([0-9]{1,5}))?$", server) + if uri: + zabbix_host, sep, zabbix_port = uri.groups() + zabbix_port = zabbix_port if sep == ':' else self.config['zabbix_port'] + self._zabbix_hosts.append({'zabbix_host': zabbix_host, 'zabbix_port': zabbix_port}) + else: + self.log.error('Zabbix host "%s" is not valid', server) + + self.log.error('Parsed Zabbix hosts: %s', self._zabbix_hosts) + def get_pg_stats(self): stats = dict() @@ -257,7 +276,7 @@ class Module(MgrModule): if identifier is None or len(identifier) == 0: identifier = 'ceph-{0}'.format(self.fsid) - if not self.config['zabbix_host']: + if not self.config['zabbix_host'] or not self._zabbix_hosts: self.log.error('Zabbix server not set, please configure using: ' 'ceph zabbix config-set zabbix_host ') self.set_health_checks({ @@ -269,25 +288,21 @@ class Module(MgrModule): }) return - servers = self.config['zabbix_host'].split(",") result = True - for server in servers: - zabbix_host, sep, zabbix_port = server.partition(':') - zabbix_port = zabbix_port if sep == ':' else self.config['zabbix_port'] - + for server in self._zabbix_hosts: self.log.info( 'Sending data to Zabbix server %s, port %s as host/identifier %s', - zabbix_host, zabbix_port, identifier) + server['zabbix_host'], server['zabbix_port'], identifier) self.log.debug(data) try: zabbix = ZabbixSender(self.config['zabbix_sender'], - zabbix_host, - zabbix_port, self.log) + server['zabbix_host'], + server['zabbix_port'], self.log) zabbix.send(identifier, data) except Exception as exc: - self.log.error('Exception when sending: %s', exc) + self.log.exception('Failed to send.') self.set_health_checks({ 'MGR_ZABBIX_SEND_FAILED': { 'severity': 'warning', @@ -295,6 +310,7 @@ class Module(MgrModule): 'detail': [str(exc)] } }) + result = False self.set_health_checks(dict()) return result @@ -311,6 +327,8 @@ class Module(MgrModule): self.log.debug('Setting configuration option %s to %s', key, value) if self.set_config_option(key, value): self.set_module_option(key, value) + if key == 'zabbix_host' or key == 'zabbix_port': + self._parse_zabbix_hosts() return 0, 'Configuration option {0} updated'.format(key), '' return 1,\ -- 2.39.5