Skip to content

WIP: Cleaning up the CLI mess stack #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions lib/vsc/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,31 @@
"""
import pkg_resources
pkg_resources.declare_namespace(__name__)

import os
import warnings
from functools import wraps
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this do?


def _script_name(full_name):
"""Return the script name without .py extension if any. This assumes that the script name does not contain a
dot in case of lacking an extension.
"""
(name, _) = os.path.splitext(full_name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use pathlib

return os.path.basename(name)


def deprecated_class(message=None):
def decorator(cls):
class Wrapped(cls):
def __init__(self, *args, **kwargs):
warnings.warn(
f"{cls.__name__} is deprecated. {message or ''}",
category=DeprecationWarning,
stacklevel=2,
)
super().__init__(*args, **kwargs)
Wrapped.__name__ = cls.__name__
Wrapped.__doc__ = cls.__doc__
Wrapped.__module__ = cls.__module__
return Wrapped
return decorator
74 changes: 71 additions & 3 deletions lib/vsc/utils/nagios.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
@author: Luis Fernando Muñoz Mejías (Ghent University)
"""

import logging
import operator
import os
import pwd
Expand All @@ -47,12 +48,16 @@
import sys
import time

from pathlib import Path

from vsc.utils import _script_name
from vsc.utils.cache import FileCache
from vsc.utils.fancylogger import getLogger

log = getLogger(__name__)
#log = getLogger(__name__)

NAGIOS_CACHE_DIR = '/var/cache'
NAGIOS_CACHE_FILENAME = 'cache.nagios.json.gz'
NAGIOS_CACHE_FILENAME_TEMPLATE = '%s.nagios.json.gz'

NAGIOS_OK = 'OK'
Expand Down Expand Up @@ -85,7 +90,7 @@ def _real_exit(message, code, metrics=''):
metrics = f'|{message[1]}'
if len(msg) > NAGIOS_MAX_MESSAGE_LENGTH:
# log long message but print truncated message
log.info("Nagios report %s: %s%s", exit_text, msg, metrics)
logging.info("Nagios report %s: %s%s", exit_text, msg, metrics)
msg = msg[:NAGIOS_MAX_MESSAGE_LENGTH-3] + '...'

print(f"{exit_text} {msg}{metrics}")
Expand Down Expand Up @@ -203,7 +208,7 @@ def parse(self, nrange):
self.log.debug("parse: start %s end %s neg %s", start, end, neg)
else:
msg = f"parse: invalid nrange {nrange}."
self.log.Error(msg)
self.log.error(msg)
raise ValueError(nrange)

def range_fn(test):
Expand Down Expand Up @@ -241,6 +246,69 @@ def alert(self, test):
"""
return not self.range_fn(test)

class NagiosStatusMixin:
"""
A mixin class providing methods for Nagios status codes.

Note that these methods do not return, they exit the script.

Options come from NAGIOS_MIXIN_OPTIONS.
"""

NAGIOS_MIXIN_OPTIONS = {
'nagios-report': ('print out nagios information', None, 'store_true', False, 'n'),
'nagios-check-filename':
('filename of where the nagios check data is stored', 'str', 'store',
Path(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),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't know what this does, thresholds are configured in icinga, not in checks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? This has been in NagiosRepoerter for 12 years.

class NagiosReporter:
    """Reporting class for Nagios/Icinga reports.

    Can cache the result in a gzipped JSON file and print the result out at some later point.
    """

    def __init__(self, header, filename, threshold, nagios_username="nagios", world_readable=False):
        """Initialisation.

        @type header: string
        @type filename: string
        @type threshold: positive integer

        @param header: application specific part of the message, used to denote what program/script is using the
                       reporter.
        @param filename: the filename of the gzipped JSON cache file
        @param threshold: Seconds to determines how old the gzipped JSON data may be
                         before reporting an unknown result. This can be used to check if the script that uses the
                         reporter has run the last time and succeeded in writing the cache data. If the threshold <= 0,
                         this feature is not used.

See @param threshold.

'nagios-user': ('user nagios runs as', 'str', 'store', 'nrpe'),
'nagios-world-readable-check': ('make the nagios check data file world readable', None, 'store_true', False),
}

def nagios_prologue(self):
"""
This will set up the reporter, but exit immediately of the report is requested
"""
# bail if nagios report is requested
self.nagios = SimpleNagios(
_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,
)

def nagios_epilogue(self, nagios_exit, nagios_message):
"""
This will write the result to the cache file
"""
self.nagios._exit(nagios_exit, nagios_message)

def ok(self, msg):
"""
Convenience method that exits with Nagios OK exit code.
"""
exit_from_errorcode(0, msg)

def warning(self, msg):
"""
Convenience method that exits with Nagios WARNING exit code.
"""
exit_from_errorcode(1, msg)

def critical(self, msg):
"""
Convenience method that exits with Nagios CRITICAL exit code.
"""
exit_from_errorcode(2, msg)

def unknown(self, msg):
"""
Convenience method that exits with Nagios UNKNOWN exit code.
"""
exit_from_errorcode(3, msg)


class NagiosReporter:
"""Reporting class for Nagios/Icinga reports.
Expand Down
Loading
Loading