Search code examples
pythonpython-3.xnagios

Returning information in addition to metric in nagiosplugin


I have a nagiosplugin check that get the version of a package using salt (because of the network architecture) and then compare it with a version given in argument, using the salt.pkg_version_cmp method.

I'm able to return the result of this check (-1|0|1) in a metric and display the statusline.

But I want to add the actual version of the package in the status line, and I don't know how to return it with nagiosplugin class|function, and not by using a global var.

Here is my nagiosplugin.Resource class:

class CheckSaltPkgVersion(nagiosplugin.Resource):
def __init__(self, args):
    self.package = args.package
    self.rule = args.rule
    self.target = args.vm

def salt_pkg_version(self):
    sa = getSaltAdapter()
    version = sa.exec_function([{
        'client': 'local',
        'tgt': self.target,
        'fun': 'pkg.version',
        'arg': [self.package]
    }])
    compare = sa.exec_function([{
        'client': 'local',
        'tgt': self.target,
        'fun': 'pkg.version_cmp',
        'arg': [version['return'][0][self.target], self.rule]
    }])
    # depending of compare and version, mist return smth between 0 and 4
    return compare['return'][0][self.target]

def probe(self):
    """Runs"""
    yield nagiosplugin.Metric(self.package, 
                              self.salt_pkg_version(),
                              context='salt_pkg_version_compare')

Here is my nagiosplugin.Summary (basic)

class VersionSummary(nagiosplugin.Summary):
def ok(self, results):
    return ("ok")

def problem(self, results):
    return("warning")

I would like to have a Summary like this (ignoring the conditional check about Unknown/warning/critical):

class VersionSummary(nagiosplugin.Summary):
def ok(self, results):
    return 'the package %s is in version %s' % (results.first_significant.metric.name, version)

def problem(self, results):
    return 'the package %s is in version %s which is less that %s' % (results.first_significant.metric.name, version, rule)

I searched, but the only thing I found was this: nagiosplugin: how to show different fmt_metric based on the value? and he's doing 2 check (the first in main, then the second in the summary to get the information)

It doesn't seem like the Metric class (https://pythonhosted.org/nagiosplugin/api/intermediate.html#module-nagiosplugin.metric) could carry other thing than the value.


Solution

  • I don't find another solution than to write a new Context :

    class CheckContext(nagiosplugin.Context):
    
        def __init__(self, name, rule, critical, fmt_metric=None, result_cls=nagiosplugin.Result):
            super(CheckContext, self).__init__(name, fmt_metric, result_cls)
            self.rule = rule
            self.critical = critical
    
        def performance(self, metric, ressource):
            return None
    
        def evaluate(self, metric, resource):
            need_update = self.compare(metric.value)
            if (need_update):
                if (self.critical == 0):
                    return self.result_cls(nagiosplugin.Warn, None, metric)
                else:
                    return self.result_cls(nagiosplugin.Critical, None, metric)
            else:
                return self.result_cls(nagiosplugin.Ok, None, metric)
    
        def compare(self,metric):
            metric = re.sub("[^0-9]", '.', metric).split('.')
            rule = re.sub("[^0-9]", '.', self.rule).split('.')
            i = 0
            while (i < len(rule) and int(rule[i]) <= int(metric[i])):
                i+=1
                if (len(metric) <= i):
                    metric.append(0)
            return (i < len(rule))
    

    It take the version that return the first salt function. The comparison between the two strings is now do in the Compare.

    here are the Summary and the main

    class VersionSummary(nagiosplugin.Summary):
    
    
        def __init__(self, rule):
                self.rule = rule;
    
        def ok(self, results):
            return ("Package = %s, version = %s, rule = %s" % (results.__getitem__(0).metric.name, results.__getitem__(0).metric.value, self.rule))
    
        def problem(self, results):
            return("Package %s must be in version %s but is in version %s" % (results.__getitem__(0).metric.name, self.rule, results.__getitem__(0).metric.value))
    
    
    
    
    
    @nagiosplugin.guarded
    def main():
        args = parse_args()
        check = nagiosplugin.Check(CheckSaltPkgVersion(args.package, args.vm), 
                                    CheckContext('salt_pkg_version_compare',
                                                args.rule, 
                                                args.critical),
                                    VersionSummary(args.rule))
        check.main()
    

    The rule is send to the summary from the main, and the version in the result. The context evaluate if it's critical/warning/ok and send the result to the summary.