[Nagiosplug-devel] Re: check_* -w and -c switches
Paul L. Allen
pla at softflare.com
Mon Mar 8 10:03:14 CET 2004
Elsewhere, Karl DeBisschop writes:
> On Fri, 05 Mar 2004 13:05:56 +0000
> "Paul L. Allen" <pla at softflare.com> wrote:
>> I have a perl subroutine that does the same thing which you can have
>> if you want it (let me know where to send it if you do).
>
> Post to the list or drop into patches against utils.pm on sourceforge
> (preferred)
I couldn't see any obvious place to drop into the patches which didn't
require me to get a sourceforge login, so it's attached below. Also
attached is the same subroutine plus a test harness that calls it to
check it copes with all the syntax permutations correctly (80 tests).
Note that I arbitrarily decided that it would treat ~:~ as an invalid
range specifier even though theoretically it is valid (but not useful)
in order not to complicate the code any further. I didn't see any point
in special-casing an instance that is of no practical use to anyone.
--
Paul Allen
Softflare Support
-------------- next part --------------
sub check_range ($$@)
{
# Takes three parameters. The first is a metric. The second is
# a range using Nagios plugin range syntax. The third is an optional
# name for the range (such as 'warning' or 'critical') which is used
# if a usage error is generated because of an invalid range. No
# explicit checking is done that the metric or the range consists
# of non-numeric values - they will be treated as zero.
# Accepts ranges of the following form:
#
# min:max (between min and max inclusive)
# min: (equivalent to min:infinity)
# :max (equivalent to 0:max)
# max (equivalent :max which is equivalent to 0:max)
# 0 (equivalent to 0:infinity)
#
# The symbol ~ may be specified as the minimum portion of a range
# to represent -infinity. The range may be prefixed by @ to negate
# the result (so the metric is critical if within the range).
# Note that ~:~ is treated as an invalid range
my($metric) = shift(@_);
my($range) = shift(@_);
# Take third and any subsequent parameters and concatenate with spaces
# to form the name of the range for use in error messages.
my($range_name) = join(' ', @_);
$range_name = " for $range_name." if ($range_name);
# Use strict doesn't let us do string/numeric conversions, so turn
# off warnings to get around that problem and the problem of undefined
# variables from the regex below.
local($^W) = 0;
my($range_ok) = 0;
# Split the range into the optional 'invert range' prefix (@), minimum
# bound and upper bound, allowing all the variations.
my($invert_range, $lower, $upper) = $range =~ /^(\@)?(?:([^:])*:)?(.*)?$/;
# The above regex has problems with 0 (which means 0:infinity), so
# we have to correct for that (but not for :0, which means 0:0 and is
# handled correctly by the regex).
($lower, $upper) = ($upper, $lower) if
(($upper eq '0' and not $lower) and $range !~ /:/);
# Check that upper >= lower, including the case when lower or upper is
# ~ (negative infinity). Set $! and die rather than just exit so we
# can trap this in a test harness.
if ($upper eq '~' or ($lower ne '~' and $upper ne '' and $lower > $upper ))
{
print "Error: range is $lower:$upper$range_name\n";
print_usage();
$! = $ERRORS{UNKNOWN};
die "\n";
}
# If the lower bound is not ~ (negative infinity) then check that the
# metric is greater than or equal to the lower bound. If the lower bound
# is ~ then the metric has to be OK because any metric has to be higher
# than negative infinity.
if ($lower ne '~')
{
$range_ok++ if ($metric >= $lower + 0);
}
else
{
$range_ok++;
}
$range_ok = 0 if ($upper ne '' and $metric > $upper + 0);
$range_ok ^= 1 if ($invert_range);
return($range_ok);
}
-------------- next part --------------
#! /usr/bin/perl -wT
use strict;
use lib "/usr/local/nagios/libexec" ;
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use vars qw(@tests $test $result $num_tests $num_successes);
@tests =
(
# Format: [metric, range, name, expected result]
#
# 'Expected result' is the result expected from check_range: 0 if
# check_range should return 0 (metric is outside of range), 1 if
# check_range should return 1 (metric is inside range). The expected
# result can also be -1, indicating that check_range should exit with
# plugin error code of 'UNKNOWN' after a usage error (caused by an
# invalid range).
# Check min:max ranges
[-1, '2:4', 'Test 1', 0],
[0, '2:4', 'Test 2', 0],
[1, '2:4', 'Test 3', 0],
[2, '2:4', 'Test 4', 1],
[3, '2:4', 'Test 5', 1],
[4, '2:4', 'Test 6', 1],
[5, '2:4', 'Test 7', 0],
# Check max ranges
[-1, 2, 'Test 8', 0],
[0, 2, 'Test 9', 1],
[1, 2, 'Test 10', 1],
[2, 2, 'Test 11', 1],
[3, 2, 'Test 12', 0],
# Check :max ranges
[-1, ':2', 'Test 13', 0],
[0, ':2', 'Test 14', 1],
[1, ':2', 'Test 15', 1],
[2, ':2', 'Test 16', 1],
[3, ':2', 'Test 17', 0],
[-1, '1:', 'Test 18', 0],
# Check min: ranges
[0, '1:', 'Test 19', 0],
[1, '1:', 'Test 20', 1],
[2, '1:', 'Test 21', 1],
# Check 0
[-1, 0, 'Test 22', 0],
[0, 0, 'Test 23', 1],
[1, 0, 'Test 24', 1],
# Check ~:max ranges
[-1, '~:1', 'Test 25', 1],
[0, '~:1', 'Test 26', 1],
[1, '~:1', 'Test 27', 1],
[2, '~:1', 'Test 28', 0],
# Check min:max ranges where min and max are the same, including :0
# which should be equivalent to 0:0.
[-1, '1:1', 'Test 29', 0],
[0, '1:1', 'Test 30', 0],
[1, '1:1', 'Test 31', 1],
[2, '1:1', 'Test 32', 0],
[-1, '0:0', 'Test 33', 0],
[0, '0:0', 'Test 34', 1],
[1, '0:0', 'Test 35', 0],
[-1, ':0', 'Test 36', 0],
[0, ':0', 'Test 37', 1],
[1, ':0', 'Test 38', 0],
# Check min:max ranges which are invalid
[1, '4:2', 'Test 39', -1],
[1, '~:~', 'Test 40', -1],
# Check @min:max ranges
[-1, '@2:4', 'Test 1', 1],
[0, '@2:4', 'Test 2', 1],
[1, '@2:4', 'Test 3', 1],
[2, '@2:4', 'Test 4', 0],
[3, '@2:4', 'Test 5', 0],
[4, '@2:4', 'Test 6', 0],
[5, '@2:4', 'Test 7', 1],
# Check @max ranges
[-1, '@2', 'Test 8', 1],
[0, '@2', 'Test 9', 0],
[1, '@2', 'Test 10', 0],
[2, '@2', 'Test 11', 0],
[3, '@2', 'Test 12', 1],
# Check @:max ranges
[-1, '@:2', 'Test 13', 1],
[0, '@:2', 'Test 14', 0],
[1, '@:2', 'Test 15', 0],
[2, '@:2', 'Test 16', 0],
[3, '@:2', 'Test 17', 1],
[-1, '@1:', 'Test 18', 1],
# Check @min: ranges
[0, '@1:', 'Test 19', 1],
[1, '@1:', 'Test 20', 0],
[2, '@1:', 'Test 21', 0],
# Check @0
[-1, '@0', 'Test 22', 1],
[0, '@0', 'Test 23', 0],
[1, '@0', 'Test 24', 0],
# Check @~:max ranges
[-1, '@~:1', 'Test 25', 0],
[0, '@~:1', 'Test 26', 0],
[1, '@~:1', 'Test 27', 0],
[2, '@~:1', 'Test 28', 1],
# Check @min:max ranges where min and max are the same, including @:0
# which should be equivalent to @0:0.
[-1, '@1:1', 'Test 29', 1],
[0, '@1:1', 'Test 30', 1],
[1, '@1:1', 'Test 31', 0],
[2, '@1:1', 'Test 32', 1],
[-1, '@0:0', 'Test 33', 1],
[0, '@0:0', 'Test 34', 0],
[1, '@0:0', 'Test 35', 1],
[-1, '@:0', 'Test 36', 1],
[0, '@:0', 'Test 37', 0],
[1, '@:0', 'Test 38', 1],
# Check @min:max ranges which are invalid
[1, '@4:2', 'Test 39', -1],
[1, '@~:~', 'Test 40', -1],
);
foreach $test (@tests)
{
$num_tests++;
eval
{
$result = &check_range($test->[0], $test->[1], $test->[2]);
};
$result = -1 if ($@);
print "$test->[2]: metric is $test->[0], range is $test->[1], ";
if ($result == 1)
{
print "result is 'pass', ";
}
elsif ($result == -1)
{
print "result is 'unknown', ";
}
else
{
print "result is 'fail', ";
}
if ($result == $test->[3])
{
$num_successes++;
print "OK\n";
}
else
{
print "Fail\n";
}
}
print "$num_successes/$num_tests tests successful\n";
exit;
sub check_range ($$@)
{
# Takes three parameters. The first is a metric. The second is
# a range using Nagios plugin range syntax. The third is an optional
# name for the range (such as 'warning' or 'critical') which is used
# if a usage error is generated because of an invalid range. No
# explicit checking is done that the metric or the range consists
# of non-numeric values - they will be treated as zero.
# Accepts ranges of the following form:
#
# min:max (between min and max inclusive)
# min: (equivalent to min:infinity)
# :max (equivalent to 0:max)
# max (equivalent :max which is equivalent to 0:max)
# 0 (equivalent to 0:infinity)
#
# The symbol ~ may be specified as the minimum portion of a range
# to represent -infinity. The range may be prefixed by @ to negate
# the result (so the metric is critical if within the range).
# Note that ~:~ is treated as an invalid range
my($metric) = shift(@_);
my($range) = shift(@_);
# Take third and any subsequent parameters and concatenate with spaces
# to form the name of the range for use in error messages.
my($range_name) = join(' ', @_);
$range_name = " for $range_name." if ($range_name);
# Use strict doesn't let us do string/numeric conversions, so turn
# off warnings to get around that problem and the problem of undefined
# variables from the regex below.
local($^W) = 0;
my($range_ok) = 0;
# Split the range into the optional 'invert range' prefix (@), minimum
# bound and upper bound, allowing all the variations.
my($invert_range, $lower, $upper) = $range =~ /^(\@)?(?:([^:])*:)?(.*)?$/;
# The above regex has problems with 0 (which means 0:infinity), so
# we have to correct for that (but not for :0, which means 0:0 and is
# handled correctly by the regex).
($lower, $upper) = ($upper, $lower) if
(($upper eq '0' and not $lower) and $range !~ /:/);
# Check that upper >= lower, including the case when lower or upper is
# ~ (negative infinity). Set $! and die rather than just exit so we
# can trap this in a test harness.
if ($upper eq '~' or ($lower ne '~' and $upper ne '' and $lower > $upper ))
{
print "Error: range is $lower:$upper$range_name\n";
print_usage();
$! = $ERRORS{UNKNOWN};
die "\n";
}
# If the lower bound is not ~ (negative infinity) then check that the
# metric is greater than or equal to the lower bound. If the lower bound
# is ~ then the metric has to be OK because any metric has to be higher
# than negative infinity.
if ($lower ne '~')
{
$range_ok++ if ($metric >= $lower + 0);
}
else
{
$range_ok++;
}
$range_ok = 0 if ($upper ne '' and $metric > $upper + 0);
$range_ok ^= 1 if ($invert_range);
return($range_ok);
}
sub print_usage
{
# Dummy print_usage subroutine to so the test harness doesn't complain
# when we specify a range with an lower bound greater than the upper bound.
}
More information about the Devel
mailing list