From 72e92ffa0192697b730d96ce9981cda082a2b3e7 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 3 May 2022 08:20:47 +0200 Subject: [PATCH 01/13] add support for zabbix as alternative to nagios --- lib/vsc/utils/script_tools.py | 10 ++++---- lib/vsc/utils/zabbix.py | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 lib/vsc/utils/zabbix.py diff --git a/lib/vsc/utils/script_tools.py b/lib/vsc/utils/script_tools.py index ee99d20..cc3a146 100644 --- a/lib/vsc/utils/script_tools.py +++ b/lib/vsc/utils/script_tools.py @@ -42,7 +42,7 @@ from vsc.utils.generaloption import SimpleOption from vsc.utils.lock import lock_or_bork, release_or_bork, LOCKFILE_DIR, LOCKFILE_FILENAME_TEMPLATE from vsc.utils.nagios import ( - SimpleNagios, NAGIOS_CACHE_DIR, NAGIOS_CACHE_FILENAME_TEMPLATE, exit_from_errorcode, + SimpleZabbix, SimpleNagios, NAGIOS_CACHE_DIR, NAGIOS_CACHE_FILENAME_TEMPLATE, exit_from_errorcode, NAGIOS_EXIT_OK, NAGIOS_EXIT_WARNING, NAGIOS_EXIT_CRITICAL, NAGIOS_EXIT_UNKNOWN, ) from vsc.utils.timestamp import ( @@ -140,18 +140,18 @@ def __init__(self, options, run_prologue=True, excepthook=None, **kwargs): self.log = fancylogger.getLogger() - def prologue(self): + def prologue(self, MonitorClass=SimpleNagios): """Checks the options given for settings and takes appropriate action. See _merge_options for the format. - - - if nagios_report is set, creates a SimpleNagios instance and prints the report. + - MonitorClass: the class to use for interaction with the monitoring software + - if nagios_report is set, creates a MonitorClass instance and prints the report. - if ha is set, checks if running on the correct host, set the appropriate nagios message and bail if not. - if locking_filename is set, take a lock. If the lock fails, bork and set the nagios exit accordingly. """ # bail if nagios report is requested - self.nagios_reporter = SimpleNagios(_cache=self.options.nagios_check_filename, + self.nagios_reporter = MonitorClass(_cache=self.options.nagios_check_filename, _report_and_exit=self.options.nagios_report, _threshold=self.options.nagios_check_interval_threshold, _cache_user=self.options.nagios_user, diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py new file mode 100644 index 0000000..cd6e9cb --- /dev/null +++ b/lib/vsc/utils/zabbix.py @@ -0,0 +1,44 @@ + +# -*- encoding: utf-8 -*- +# +# Copyright 2012-2021 Ghent University +# +# This file is part of vsc-utils, +# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), +# with support of Ghent University (http://ugent.be/hpc), +# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be), +# the Flemish Research Foundation (FWO) (http://www.fwo.be/en) +# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en). +# +# https://github.com/hpcugent/vsc-utils +# +# vsc-utils is free software: you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation, either version 2 of +# the License, or (at your option) any later version. +# +# vsc-utils is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with vsc-utils. If not, see . +# +""" +This module adapts the nagios module so its output can be interpreted by Zabbix. + +@author: Samuel Moors (Vrije Universiteit Brussel) +""" + +import json + +from vsc.utils.nagios import SimpleNagios + + +class SimpleZabbix(SimpleNagios): + def __str__(self): + """__str__ determines how the data is written to the cache""" + processed_dict = {key: value for (key, value) in self.__dict__.items() if not key.startswith('_')} + return json.dumps(processed_dict) + From 3f0e291587fb40b17edb9a946df04053a418d697 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 3 May 2022 09:36:33 +0200 Subject: [PATCH 02/13] remove wrong import --- lib/vsc/utils/script_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vsc/utils/script_tools.py b/lib/vsc/utils/script_tools.py index cc3a146..61e018a 100644 --- a/lib/vsc/utils/script_tools.py +++ b/lib/vsc/utils/script_tools.py @@ -42,7 +42,7 @@ from vsc.utils.generaloption import SimpleOption from vsc.utils.lock import lock_or_bork, release_or_bork, LOCKFILE_DIR, LOCKFILE_FILENAME_TEMPLATE from vsc.utils.nagios import ( - SimpleZabbix, SimpleNagios, NAGIOS_CACHE_DIR, NAGIOS_CACHE_FILENAME_TEMPLATE, exit_from_errorcode, + SimpleNagios, NAGIOS_CACHE_DIR, NAGIOS_CACHE_FILENAME_TEMPLATE, exit_from_errorcode, NAGIOS_EXIT_OK, NAGIOS_EXIT_WARNING, NAGIOS_EXIT_CRITICAL, NAGIOS_EXIT_UNKNOWN, ) from vsc.utils.timestamp import ( From 7b639b93225d76392005b780300ec6c2f4be2cbe Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 3 May 2022 15:25:40 +0200 Subject: [PATCH 03/13] update copyright date --- lib/vsc/__init__.py | 2 +- lib/vsc/utils/__init__.py | 2 +- lib/vsc/utils/availability.py | 2 +- lib/vsc/utils/cache.py | 2 +- lib/vsc/utils/fs_store.py | 2 +- lib/vsc/utils/lock.py | 2 +- lib/vsc/utils/nagios.py | 2 +- lib/vsc/utils/pickle_files.py | 2 +- lib/vsc/utils/rest_oauth.py | 2 +- lib/vsc/utils/script_tools.py | 2 +- lib/vsc/utils/timestamp.py | 2 +- lib/vsc/utils/timestamp_pid_lockfile.py | 2 +- lib/vsc/utils/zabbix.py | 2 +- test/00-import.py | 2 +- test/__init__.py | 2 +- test/cache.py | 2 +- test/nagios.py | 2 +- test/nagios_results.py | 2 +- test/nagios_simple.py | 2 +- test/script_tools.py | 2 +- test/timestamp.py | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/vsc/__init__.py b/lib/vsc/__init__.py index f1c17a1..409eb68 100644 --- a/lib/vsc/__init__.py +++ b/lib/vsc/__init__.py @@ -1,5 +1,5 @@ # -# Copyright 2015-2021 Ghent University +# Copyright 2015-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/__init__.py b/lib/vsc/utils/__init__.py index f1c17a1..409eb68 100644 --- a/lib/vsc/utils/__init__.py +++ b/lib/vsc/utils/__init__.py @@ -1,5 +1,5 @@ # -# Copyright 2015-2021 Ghent University +# Copyright 2015-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/availability.py b/lib/vsc/utils/availability.py index ab16205..80fa3cd 100644 --- a/lib/vsc/utils/availability.py +++ b/lib/vsc/utils/availability.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/cache.py b/lib/vsc/utils/cache.py index 782fbd4..df278bb 100644 --- a/lib/vsc/utils/cache.py +++ b/lib/vsc/utils/cache.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/fs_store.py b/lib/vsc/utils/fs_store.py index 209e793..552250b 100644 --- a/lib/vsc/utils/fs_store.py +++ b/lib/vsc/utils/fs_store.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/lock.py b/lib/vsc/utils/lock.py index a8a289f..d827f3f 100644 --- a/lib/vsc/utils/lock.py +++ b/lib/vsc/utils/lock.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/nagios.py b/lib/vsc/utils/nagios.py index 77bed77..e4702df 100644 --- a/lib/vsc/utils/nagios.py +++ b/lib/vsc/utils/nagios.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/pickle_files.py b/lib/vsc/utils/pickle_files.py index 10d6411..b500e4b 100644 --- a/lib/vsc/utils/pickle_files.py +++ b/lib/vsc/utils/pickle_files.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/rest_oauth.py b/lib/vsc/utils/rest_oauth.py index 209311a..65742d5 100644 --- a/lib/vsc/utils/rest_oauth.py +++ b/lib/vsc/utils/rest_oauth.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/script_tools.py b/lib/vsc/utils/script_tools.py index 61e018a..91d4e92 100644 --- a/lib/vsc/utils/script_tools.py +++ b/lib/vsc/utils/script_tools.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/timestamp.py b/lib/vsc/utils/timestamp.py index 25965e1..830293c 100644 --- a/lib/vsc/utils/timestamp.py +++ b/lib/vsc/utils/timestamp.py @@ -1,6 +1,6 @@ # -*- coding: latin-1 -*- # -# Copyright 2009-2021 Ghent University +# Copyright 2009-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/timestamp_pid_lockfile.py b/lib/vsc/utils/timestamp_pid_lockfile.py index 53116ce..9c27a16 100644 --- a/lib/vsc/utils/timestamp_pid_lockfile.py +++ b/lib/vsc/utils/timestamp_pid_lockfile.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py index cd6e9cb..acf5c49 100644 --- a/lib/vsc/utils/zabbix.py +++ b/lib/vsc/utils/zabbix.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/00-import.py b/test/00-import.py index 5433120..753c284 100644 --- a/test/00-import.py +++ b/test/00-import.py @@ -1,5 +1,5 @@ # -# Copyright 2016-2021 Ghent University +# Copyright 2016-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/__init__.py b/test/__init__.py index 2c87f0f..fe69a6e 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,5 +1,5 @@ # -# Copyright 2016-2021 Ghent University +# Copyright 2016-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/cache.py b/test/cache.py index ea315d4..25b24db 100644 --- a/test/cache.py +++ b/test/cache.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/nagios.py b/test/nagios.py index f04eb48..52bf590 100644 --- a/test/nagios.py +++ b/test/nagios.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/nagios_results.py b/test/nagios_results.py index ae416dc..30c4354 100644 --- a/test/nagios_results.py +++ b/test/nagios_results.py @@ -1,6 +1,6 @@ # encoding: utf-8 # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/nagios_simple.py b/test/nagios_simple.py index f033c21..9f306dc 100644 --- a/test/nagios_simple.py +++ b/test/nagios_simple.py @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 Ghent University +# Copyright 2012-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/script_tools.py b/test/script_tools.py index 8bac724..f74b555 100644 --- a/test/script_tools.py +++ b/test/script_tools.py @@ -1,5 +1,5 @@ # -# Copyright 2016-2021 Ghent University +# Copyright 2016-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/timestamp.py b/test/timestamp.py index e105130..4dfa7a8 100644 --- a/test/timestamp.py +++ b/test/timestamp.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2021 Ghent University +# Copyright 2018-2022 Ghent University # # This file is part of vsc-utils, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), From 70d2fa9e3b92708287a2bb9cae05d82451b8f75e Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 3 May 2022 19:20:47 +0200 Subject: [PATCH 04/13] add monitorclass arg to __init__ instead of prologue --- lib/vsc/utils/script_tools.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/vsc/utils/script_tools.py b/lib/vsc/utils/script_tools.py index 91d4e92..f89be4d 100644 --- a/lib/vsc/utils/script_tools.py +++ b/lib/vsc/utils/script_tools.py @@ -115,11 +115,13 @@ class ExtendedSimpleOption(SimpleOption): The prologue should be called at the start of the script; the epilogue at the end. """ - def __init__(self, options, run_prologue=True, excepthook=None, **kwargs): + def __init__(self, options, run_prologue=True, excepthook=None, monitorclass=SimpleNagios, **kwargs): """Initialise. If run_prologue is True (default), we immediately execute the prologue. + - monitorclass: the class to use for interaction with the monitoring software + Note that if taking a lock is requested (default), and the lock cannot be acquire for some reason, the program will exit, """ @@ -129,6 +131,7 @@ def __init__(self, options, run_prologue=True, excepthook=None, **kwargs): self.nagios_reporter = None self.lockfile = None + self.MonitorClass = monitorclass if run_prologue: self.prologue() @@ -140,23 +143,23 @@ def __init__(self, options, run_prologue=True, excepthook=None, **kwargs): self.log = fancylogger.getLogger() - def prologue(self, MonitorClass=SimpleNagios): + def prologue(self): """Checks the options given for settings and takes appropriate action. See _merge_options for the format. - - MonitorClass: the class to use for interaction with the monitoring software + - if nagios_report is set, creates a MonitorClass instance and prints the report. - if ha is set, checks if running on the correct host, set the appropriate nagios message and bail if not. - if locking_filename is set, take a lock. If the lock fails, bork and set the nagios exit accordingly. """ # bail if nagios report is requested - self.nagios_reporter = MonitorClass(_cache=self.options.nagios_check_filename, - _report_and_exit=self.options.nagios_report, - _threshold=self.options.nagios_check_interval_threshold, - _cache_user=self.options.nagios_user, - _world_readable=self.options.nagios_world_readable_check, - ) + self.nagios_reporter = self.MonitorClass(_cache=self.options.nagios_check_filename, + _report_and_exit=self.options.nagios_report, + _threshold=self.options.nagios_check_interval_threshold, + _cache_user=self.options.nagios_user, + _world_readable=self.options.nagios_world_readable_check, + ) # check for HA host if self.options.ha and not proceed_on_ha_service(self.options.ha): From c7595ad59e6e1dfd9b2d76f97f7807f1d4e36847 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 3 May 2022 19:26:50 +0200 Subject: [PATCH 05/13] use lowercase monitorclass everywhere --- lib/vsc/utils/script_tools.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/vsc/utils/script_tools.py b/lib/vsc/utils/script_tools.py index f89be4d..2b1acdc 100644 --- a/lib/vsc/utils/script_tools.py +++ b/lib/vsc/utils/script_tools.py @@ -131,7 +131,7 @@ def __init__(self, options, run_prologue=True, excepthook=None, monitorclass=Sim self.nagios_reporter = None self.lockfile = None - self.MonitorClass = monitorclass + self.monitorclass = monitorclass if run_prologue: self.prologue() @@ -148,13 +148,13 @@ def prologue(self): See _merge_options for the format. - - if nagios_report is set, creates a MonitorClass instance and prints the report. + - if nagios_report is set, creates a monitorclass instance and prints the report. - if ha is set, checks if running on the correct host, set the appropriate nagios message and bail if not. - if locking_filename is set, take a lock. If the lock fails, bork and set the nagios exit accordingly. """ # bail if nagios report is requested - self.nagios_reporter = self.MonitorClass(_cache=self.options.nagios_check_filename, + self.nagios_reporter = self.monitorclass(_cache=self.options.nagios_check_filename, _report_and_exit=self.options.nagios_report, _threshold=self.options.nagios_check_interval_threshold, _cache_user=self.options.nagios_user, From 75732bfc1f5b9e30f51ea750f506b5a58b3e93ac Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 8 May 2022 22:27:15 +0200 Subject: [PATCH 06/13] dont print nagios exit string for zabbix --- lib/vsc/utils/nagios.py | 15 ++++++++++++--- lib/vsc/utils/zabbix.py | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/vsc/utils/nagios.py b/lib/vsc/utils/nagios.py index e4702df..98a6cdd 100644 --- a/lib/vsc/utils/nagios.py +++ b/lib/vsc/utils/nagios.py @@ -280,11 +280,15 @@ def report_and_exit(self): if self.threshold <= 0 or time.time() - timestamp < self.threshold: self.log.info("Nagios check cache file %s contents delivered: %s", self.filename, nagios_message) - print("%s %s" % (nagios_exit_string, nagios_message)) + self.print_report(nagios_exit_string, nagios_message) sys.exit(nagios_exit_code) else: unknown_exit("%s gzipped JSON file too old (timestamp = %s)" % (self.header, time.ctime(timestamp))) + def print_report(self, nagios_exit_string, nagios_message): + """Print the nagios report""" + print("%s %s" % (nagios_exit_string, nagios_message)) + def cache(self, nagios_exit, nagios_message): """Store the result in the cache file with a timestamp. @@ -434,6 +438,11 @@ class SimpleNagios(NagiosResult): def __init__(self, **kwargs): """Initialise message and perfdata""" + self._init(**kwargs) + + def _init(self, reporterclass=NagiosReporter, **kwargs): + """The real init method""" + self.__dict__ = {} self.message = None # the message @@ -453,10 +462,10 @@ def __init__(self, **kwargs): if self._cache: # make a NagiosReporter instance that can be used for caching if self._cache_user: - cache = NagiosReporter('no header', self._cache, self._threshold, nagios_username=self._cache_user, + cache = reporterclass('no header', self._cache, self._threshold, nagios_username=self._cache_user, world_readable=self._world_readable) else: - cache = NagiosReporter('no header', self._cache, self._threshold, world_readable=self._world_readable) + cache = reporterclass('no header', self._cache, self._threshold, world_readable=self._world_readable) if self._report_and_exit: cache.report_and_exit() else: diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py index acf5c49..fe1598f 100644 --- a/lib/vsc/utils/zabbix.py +++ b/lib/vsc/utils/zabbix.py @@ -30,15 +30,29 @@ @author: Samuel Moors (Vrije Universiteit Brussel) """ +from __future__ import print_function import json -from vsc.utils.nagios import SimpleNagios + +from vsc.utils.nagios import SimpleNagios, NagiosReporter class SimpleZabbix(SimpleNagios): + def __init__(self, **kwargs): + """Initialise message and perfdata""" + super(SimpleZabbix, self)._init(reporterclass=ZabbixReporter, **kwargs) + def __str__(self): """__str__ determines how the data is written to the cache""" processed_dict = {key: value for (key, value) in self.__dict__.items() if not key.startswith('_')} return json.dumps(processed_dict) + +class ZabbixReporter(NagiosReporter): + """Reporting class for Zabbix reports""" + + def print_report(self, nagios_exit_string, nagios_message): + """Print the nagios report""" + print(nagios_message) + From 86afb52ed81a6088231b6c68774cdefa24ca73ad Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 11 May 2022 09:28:32 +0200 Subject: [PATCH 07/13] include timestamp into json output for zabbix; add test for zabbix --- lib/vsc/utils/nagios.py | 10 ++--- lib/vsc/utils/zabbix.py | 12 ++++-- test/zabbix.py | 93 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 test/zabbix.py diff --git a/lib/vsc/utils/nagios.py b/lib/vsc/utils/nagios.py index 98a6cdd..e3f7fbe 100644 --- a/lib/vsc/utils/nagios.py +++ b/lib/vsc/utils/nagios.py @@ -277,18 +277,18 @@ def report_and_exit(self): unknown_exit("%s nagios gzipped JSON file unavailable (%s)" % (self.header, self.filename)) (timestamp, ((nagios_exit_code, nagios_exit_string), nagios_message)) = nagios_cache.load('nagios') + self.print_report_and_exit(timestamp, nagios_exit_code, nagios_exit_string, nagios_message) + + def print_report_and_exit(self, timestamp, nagios_exit_code, nagios_exit_string, nagios_message): + """Print the nagios report (if the data is not too old) and exit""" if self.threshold <= 0 or time.time() - timestamp < self.threshold: self.log.info("Nagios check cache file %s contents delivered: %s", self.filename, nagios_message) - self.print_report(nagios_exit_string, nagios_message) + print("%s %s" % (nagios_exit_string, nagios_message)) sys.exit(nagios_exit_code) else: unknown_exit("%s gzipped JSON file too old (timestamp = %s)" % (self.header, time.ctime(timestamp))) - def print_report(self, nagios_exit_string, nagios_message): - """Print the nagios report""" - print("%s %s" % (nagios_exit_string, nagios_message)) - def cache(self, nagios_exit, nagios_message): """Store the result in the cache file with a timestamp. diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py index fe1598f..654f6e4 100644 --- a/lib/vsc/utils/zabbix.py +++ b/lib/vsc/utils/zabbix.py @@ -33,12 +33,14 @@ from __future__ import print_function import json - +import sys from vsc.utils.nagios import SimpleNagios, NagiosReporter class SimpleZabbix(SimpleNagios): + """Class to allow easy interaction with Zabbix related code""" + def __init__(self, **kwargs): """Initialise message and perfdata""" super(SimpleZabbix, self)._init(reporterclass=ZabbixReporter, **kwargs) @@ -52,7 +54,9 @@ def __str__(self): class ZabbixReporter(NagiosReporter): """Reporting class for Zabbix reports""" - def print_report(self, nagios_exit_string, nagios_message): - """Print the nagios report""" - print(nagios_message) + def print_report_and_exit(self, timestamp, nagios_exit_code, nagios_exit_string, nagios_message): + """Print the zabbix report and exit""" + json.dump([timestamp, nagios_exit_string, json.loads(nagios_message)], sys.stdout) + self.log.info("Zabbix check cache file %s contents delivered: %s", self.filename, nagios_message) + sys.exit(nagios_exit_code) diff --git a/test/zabbix.py b/test/zabbix.py new file mode 100644 index 0000000..23c9718 --- /dev/null +++ b/test/zabbix.py @@ -0,0 +1,93 @@ +# +# Copyright 2012-2022 Ghent University +# +# This file is part of vsc-utils, +# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), +# with support of Ghent University (http://ugent.be/hpc), +# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be), +# the Flemish Research Foundation (FWO) (http://www.fwo.be/en) +# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en). +# +# https://github.com/hpcugent/vsc-utils +# +# vsc-utils is free software: you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation, either version 2 of +# the License, or (at your option) any later version. +# +# vsc-utils is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with vsc-utils. If not, see . +# +""" +Tests for the vsc.utils.zabbix module. + +@author: Andy Georges (Ghent University) +@author: Samuel Moors (Vrije Universiteit Brussel) +""" +import json +import os +import tempfile +import time +import sys +import random +import string +from pwd import getpwuid + +from vsc.install.testing import TestCase + +from vsc.utils.zabbix import ZabbixReporter, SimpleZabbix +from vsc.utils.nagios import NAGIOS_EXIT_OK, NAGIOS_EXIT_WARNING, NAGIOS_EXIT_CRITICAL, NAGIOS_EXIT_UNKNOWN +from vsc.utils.py2vs3 import StringIO + + +class TestZabbix(TestCase): + """Test for the zabbix reporter class.""" + + def setUp(self): + user = getpwuid(os.getuid()) + self.nagios_user = user.pw_name + super(TestZabbix, self).setUp() + + def test_cache(self): + """Test the caching mechanism in the reporter.""" + length = random.randint(1, 30) + exit_code = random.randint(0, 3) + threshold = random.randint(0, 10) + + message = ''.join(random.choice(string.printable) for x in range(length)) + message = message.rstrip() + message = json.dumps([message]) + + (handle, filename) = tempfile.mkstemp() + os.unlink(filename) + os.close(handle) + reporter = ZabbixReporter('test_cache', filename, threshold, self.nagios_user) + + nagios_exit = [NAGIOS_EXIT_OK, NAGIOS_EXIT_WARNING, NAGIOS_EXIT_CRITICAL, NAGIOS_EXIT_UNKNOWN][exit_code] + + reporter.cache(nagios_exit, message) + + (handle, output_filename) = tempfile.mkstemp() + os.close(handle) + + try: + old_stdout = sys.stdout + buffer = StringIO() + sys.stdout = buffer + reporter_test = ZabbixReporter('test_cache', filename, threshold, self.nagios_user) + reporter_test.report_and_exit() + except SystemExit as err: + line = buffer.getvalue().rstrip() + sys.stdout = old_stdout + buffer.close() + self.assertTrue(err.code == nagios_exit[0]) + line = json.loads(line) + self.assertTrue(line[1] == nagios_exit[1]) + self.assertTrue(line[2][0] == json.loads(message)[0]) + + os.unlink(filename) From df0cee385e84db0994951f2395df229ac687003d Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 11 May 2022 12:50:27 +0200 Subject: [PATCH 08/13] simplify report printing for zabbix --- lib/vsc/utils/zabbix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py index 654f6e4..1f117b2 100644 --- a/lib/vsc/utils/zabbix.py +++ b/lib/vsc/utils/zabbix.py @@ -56,7 +56,7 @@ class ZabbixReporter(NagiosReporter): def print_report_and_exit(self, timestamp, nagios_exit_code, nagios_exit_string, nagios_message): """Print the zabbix report and exit""" - json.dump([timestamp, nagios_exit_string, json.loads(nagios_message)], sys.stdout) + print('[%f, "%s", %s]' % (timestamp, nagios_exit_string, nagios_message)) self.log.info("Zabbix check cache file %s contents delivered: %s", self.filename, nagios_message) sys.exit(nagios_exit_code) From 507804c29499c399c97d2809de214eb64f778473 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 13 May 2022 10:49:49 +0200 Subject: [PATCH 09/13] use class constants for monitorclass and reporterclass --- lib/vsc/utils/nagios.py | 11 +++-------- lib/vsc/utils/script_tools.py | 10 ++++------ lib/vsc/utils/zabbix.py | 27 ++++++++++++++------------- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/lib/vsc/utils/nagios.py b/lib/vsc/utils/nagios.py index e3f7fbe..f2428fc 100644 --- a/lib/vsc/utils/nagios.py +++ b/lib/vsc/utils/nagios.py @@ -279,7 +279,6 @@ def report_and_exit(self): (timestamp, ((nagios_exit_code, nagios_exit_string), nagios_message)) = nagios_cache.load('nagios') self.print_report_and_exit(timestamp, nagios_exit_code, nagios_exit_string, nagios_message) - def print_report_and_exit(self, timestamp, nagios_exit_code, nagios_exit_string, nagios_message): """Print the nagios report (if the data is not too old) and exit""" if self.threshold <= 0 or time.time() - timestamp < self.threshold: @@ -435,14 +434,10 @@ class SimpleNagios(NagiosResult): USE_HEADER = True RESERVED_WORDS = set(['message', 'ok', 'warning', 'critical', 'unknown', '_exit', '_cache', '_cache_user', '_final', '_final_state', '_report', '_threshold']) + REPORTERCLASS = NagiosReporter def __init__(self, **kwargs): """Initialise message and perfdata""" - self._init(**kwargs) - - def _init(self, reporterclass=NagiosReporter, **kwargs): - """The real init method""" - self.__dict__ = {} self.message = None # the message @@ -462,10 +457,10 @@ def _init(self, reporterclass=NagiosReporter, **kwargs): if self._cache: # make a NagiosReporter instance that can be used for caching if self._cache_user: - cache = reporterclass('no header', self._cache, self._threshold, nagios_username=self._cache_user, + cache = self.REPORTERCLASS('no header', self._cache, self._threshold, nagios_username=self._cache_user, world_readable=self._world_readable) else: - cache = reporterclass('no header', self._cache, self._threshold, world_readable=self._world_readable) + cache = self.REPORTERCLASS('no header', self._cache, self._threshold, world_readable=self._world_readable) if self._report_and_exit: cache.report_and_exit() else: diff --git a/lib/vsc/utils/script_tools.py b/lib/vsc/utils/script_tools.py index 2b1acdc..d49f36f 100644 --- a/lib/vsc/utils/script_tools.py +++ b/lib/vsc/utils/script_tools.py @@ -114,14 +114,13 @@ class ExtendedSimpleOption(SimpleOption): The prologue should be called at the start of the script; the epilogue at the end. """ + MONITORCLASS = SimpleNagios - def __init__(self, options, run_prologue=True, excepthook=None, monitorclass=SimpleNagios, **kwargs): + def __init__(self, options, run_prologue=True, excepthook=None, **kwargs): """Initialise. If run_prologue is True (default), we immediately execute the prologue. - - monitorclass: the class to use for interaction with the monitoring software - Note that if taking a lock is requested (default), and the lock cannot be acquire for some reason, the program will exit, """ @@ -131,7 +130,6 @@ def __init__(self, options, run_prologue=True, excepthook=None, monitorclass=Sim self.nagios_reporter = None self.lockfile = None - self.monitorclass = monitorclass if run_prologue: self.prologue() @@ -148,13 +146,13 @@ def prologue(self): See _merge_options for the format. - - if nagios_report is set, creates a monitorclass instance and prints the report. + - if nagios_report is set, creates a SimpleNagios instance and prints the report. - if ha is set, checks if running on the correct host, set the appropriate nagios message and bail if not. - if locking_filename is set, take a lock. If the lock fails, bork and set the nagios exit accordingly. """ # bail if nagios report is requested - self.nagios_reporter = self.monitorclass(_cache=self.options.nagios_check_filename, + self.nagios_reporter = self.MONITORCLASS(_cache=self.options.nagios_check_filename, _report_and_exit=self.options.nagios_report, _threshold=self.options.nagios_check_interval_threshold, _cache_user=self.options.nagios_user, diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py index 1f117b2..50d47fc 100644 --- a/lib/vsc/utils/zabbix.py +++ b/lib/vsc/utils/zabbix.py @@ -36,19 +36,7 @@ import sys from vsc.utils.nagios import SimpleNagios, NagiosReporter - - -class SimpleZabbix(SimpleNagios): - """Class to allow easy interaction with Zabbix related code""" - - def __init__(self, **kwargs): - """Initialise message and perfdata""" - super(SimpleZabbix, self)._init(reporterclass=ZabbixReporter, **kwargs) - - def __str__(self): - """__str__ determines how the data is written to the cache""" - processed_dict = {key: value for (key, value) in self.__dict__.items() if not key.startswith('_')} - return json.dumps(processed_dict) +from vsc.utils.script_tools import ExtendedSimpleOption class ZabbixReporter(NagiosReporter): @@ -60,3 +48,16 @@ def print_report_and_exit(self, timestamp, nagios_exit_code, nagios_exit_string, self.log.info("Zabbix check cache file %s contents delivered: %s", self.filename, nagios_message) sys.exit(nagios_exit_code) + +class SimpleZabbix(SimpleNagios): + """Class to allow easy interaction with Zabbix related code""" + REPORTERCLASS = ZabbixReporter + + def __str__(self): + """__str__ determines how the data is written to the cache""" + processed_dict = {key: value for (key, value) in self.__dict__.items() if not key.startswith('_')} + return json.dumps(processed_dict) + + +class ExtendedSimpleOptionZabbix(ExtendedSimpleOption): + MONITORCLASS = SimpleZabbix From 2fa7a98db927b72bff6ad43a389a63c002ab974f Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 13 May 2022 10:55:47 +0200 Subject: [PATCH 10/13] fix line too long --- lib/vsc/utils/nagios.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/vsc/utils/nagios.py b/lib/vsc/utils/nagios.py index f2428fc..02114c8 100644 --- a/lib/vsc/utils/nagios.py +++ b/lib/vsc/utils/nagios.py @@ -460,7 +460,8 @@ def __init__(self, **kwargs): cache = self.REPORTERCLASS('no header', self._cache, self._threshold, nagios_username=self._cache_user, world_readable=self._world_readable) else: - cache = self.REPORTERCLASS('no header', self._cache, self._threshold, world_readable=self._world_readable) + cache = self.REPORTERCLASS( + 'no header', self._cache, self._threshold, world_readable=self._world_readable) if self._report_and_exit: cache.report_and_exit() else: From dacb163d5b34baf6dd51b37f59c33bbe74ac7708 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 20 Jun 2022 16:33:51 +0200 Subject: [PATCH 11/13] use 'zabbix' as default cache user for zabbix --- lib/vsc/utils/nagios.py | 1 + lib/vsc/utils/script_tools.py | 5 ++++- lib/vsc/utils/zabbix.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/vsc/utils/nagios.py b/lib/vsc/utils/nagios.py index 02114c8..56417c8 100644 --- a/lib/vsc/utils/nagios.py +++ b/lib/vsc/utils/nagios.py @@ -435,6 +435,7 @@ class SimpleNagios(NagiosResult): RESERVED_WORDS = set(['message', 'ok', 'warning', 'critical', 'unknown', '_exit', '_cache', '_cache_user', '_final', '_final_state', '_report', '_threshold']) REPORTERCLASS = NagiosReporter + DEFAULT_CACHE_USER = 'nrpe' def __init__(self, **kwargs): """Initialise message and perfdata""" diff --git a/lib/vsc/utils/script_tools.py b/lib/vsc/utils/script_tools.py index d49f36f..277604b 100644 --- a/lib/vsc/utils/script_tools.py +++ b/lib/vsc/utils/script_tools.py @@ -80,7 +80,7 @@ def _script_name(full_name): os.path.join(NAGIOS_CACHE_DIR, NAGIOS_CACHE_FILENAME_TEMPLATE % (_script_name(sys.argv[0]),))), 'nagios-check-interval-threshold': ('threshold of nagios checks timing out', 'int', 'store', 0), - 'nagios-user': ('user nagios runs as', 'string', 'store', 'nrpe'), + 'nagios-user': ('user nagios runs as', 'string', 'store', None), 'nagios-world-readable-check': ('make the nagios check data file world readable', None, 'store_true', False), } @@ -128,6 +128,9 @@ def __init__(self, options, run_prologue=True, excepthook=None, **kwargs): options_ = _merge_options(options) super(ExtendedSimpleOption, self).__init__(options_, **kwargs) + if not self.options.nagios_user: + self.options.nagios_user = self.MONITORCLASS.DEFAULT_CACHE_USER + self.nagios_reporter = None self.lockfile = None diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py index 50d47fc..67faf36 100644 --- a/lib/vsc/utils/zabbix.py +++ b/lib/vsc/utils/zabbix.py @@ -52,6 +52,7 @@ def print_report_and_exit(self, timestamp, nagios_exit_code, nagios_exit_string, class SimpleZabbix(SimpleNagios): """Class to allow easy interaction with Zabbix related code""" REPORTERCLASS = ZabbixReporter + DEFAULT_CACHE_USER = 'zabbix' def __str__(self): """__str__ determines how the data is written to the cache""" From 4869a7c6ee69dc5dcf8c93efdf793d1074b5c84d Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 20 Jun 2022 16:52:31 +0200 Subject: [PATCH 12/13] version bump --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index eb08065..db13081 100755 --- a/setup.py +++ b/setup.py @@ -54,7 +54,7 @@ PACKAGE = { - 'version': '2.1.10', + 'version': '2.1.11', 'author': [ag, sdw], 'maintainer': [ag, sdw], 'excluded_pkgs_rpm': ['vsc', 'vsc.utils'], # vsc is default, vsc.utils is provided by vsc-base From a316993f7fe9e281f3185e09ae338a33a6a05983 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 20 Jun 2022 18:10:27 +0200 Subject: [PATCH 13/13] use dictionary rather than list for json --- lib/vsc/utils/zabbix.py | 2 +- test/zabbix.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/vsc/utils/zabbix.py b/lib/vsc/utils/zabbix.py index 67faf36..53a698b 100644 --- a/lib/vsc/utils/zabbix.py +++ b/lib/vsc/utils/zabbix.py @@ -44,7 +44,7 @@ class ZabbixReporter(NagiosReporter): def print_report_and_exit(self, timestamp, nagios_exit_code, nagios_exit_string, nagios_message): """Print the zabbix report and exit""" - print('[%f, "%s", %s]' % (timestamp, nagios_exit_string, nagios_message)) + print('{"timestamp": %f, "exit_string": "%s", "message": %s}' % (timestamp, nagios_exit_string, nagios_message)) self.log.info("Zabbix check cache file %s contents delivered: %s", self.filename, nagios_message) sys.exit(nagios_exit_code) diff --git a/test/zabbix.py b/test/zabbix.py index 23c9718..6752dbb 100644 --- a/test/zabbix.py +++ b/test/zabbix.py @@ -87,7 +87,7 @@ def test_cache(self): buffer.close() self.assertTrue(err.code == nagios_exit[0]) line = json.loads(line) - self.assertTrue(line[1] == nagios_exit[1]) - self.assertTrue(line[2][0] == json.loads(message)[0]) + self.assertTrue(line["exit_string"] == nagios_exit[1]) + self.assertTrue(line["message"][0] == json.loads(message)[0]) os.unlink(filename)