=================================================================== RCS file: /cvs/nagios/check_openbgpd/check_openbgpd,v retrieving revision 1.1 retrieving revision 1.10 diff -u -r1.1 -r1.10 --- nagios/check_openbgpd/check_openbgpd 2009/11/13 02:05:20 1.1 +++ nagios/check_openbgpd/check_openbgpd 2015/03/26 04:44:15 1.10 @@ -1,5 +1,5 @@ #!/usr/bin/perl -T -# $RedRiver$ +# $AFresh1: check_openbgpd,v 1.9 2015/03/26 03:42:23 andrew Exp $ ######################################################################## # check_openbgpd *** A nagios check for OpenBSD bgpd # @@ -9,13 +9,14 @@ use warnings; use 5.010; +use if $] >= 5.016, experimental => 'switch'; local %ENV = (); -my $NAGIOS_OUTPUT = 0; +my $NAGIOS_OUTPUT = 1; my $LICENSE = <<'EOL'; -Copyright (c) 2009 Andrew Fresh +Copyright (c) 2009-2015 Andrew Fresh Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. @@ -56,11 +57,11 @@ exit $ERRORS{'OK'}; } -my @STATUS = read_status(); +my @STATUS = read_status( $CHECKS{_SOCKET} ); my %STATES = check_status( \@STATUS, \%CHECKS ); my $have_results = 0; -my $state = 'OK'; +my $state = 'OK'; foreach my $error ( reverse sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS ) { @@ -89,12 +90,17 @@ exit $ERRORS{$state}; sub read_status { - my ($status) = @_; + my ($socket) = @_; my @S; + my @cmd = ($BGPCTL); + if ($socket) { + push @cmd, '-s', $socket; + } + push @cmd, 'show', 'summary'; + #open my $fh, '<', 'output' # XXX - open my $fh , '-|', $BGPCTL, 'show', 'summary' - or die "Couldn't open bgpctl: $!\n"; + open my $fh, '-|', @cmd or die "Couldn't open bgpctl: $!\n"; while (<$fh>) { chomp; push @S, parse_line($_); @@ -143,7 +149,7 @@ foreach my $d ( 'low', 'high' ) { if ( defined $c{$d} ) { - $c{$d} =~ s/[^-\d\.]//gxms; + $c{$d} =~ s/[^-\d\.\%]//gxms; if ( !length $c{$d} ) { delete $c{$d}; } @@ -157,14 +163,14 @@ my ( $S, $C ) = @_; my %states; - my %neighbors; + my %neighbors = map { $_ => $C->{$_} } qw( _SOCKET _UNKNOWN ); STATE: foreach my $s ( @{$S} ) { my $n = $s->{neighbor}; $neighbors{$n} = $s; my $result; - if ( my $c = $C->{$n} ) { + if ( my $c = $C->{$n} || $C->{_UNKNOWN} ) { CODE: foreach my $code ( 'CRITICAL', 'WARNING' ) { next CODE if ( ref $c->{$code} ne 'HASH' ); my $data = $s->{state}; @@ -208,19 +214,42 @@ if ( $c->{low} || $c->{high} ) { $result = undef; - my $num = $d; + my ( $num, $max ) = split m{/}xms, $d; $num =~ s/[^-\d\.]//gxms; if ( !length $num ) { return 'State (' . $d . ') is not numeric'; } - if ( $c->{low} && $num < $c->{low} ) { - return 'is below threshold (' . $d . ' < ' . $c->{low} . ')'; - } + DIRECTION: foreach my $dir (qw( low high )) { + if ( !$c->{$dir} ) { next DIRECTION; } - if ( $c->{high} && $num > $c->{high} ) { - return 'is above threshold (' . $d . ' > ' . $c->{high} . ')'; + my $check = $c->{$dir}; + my $cnum = $num; + + if ( $check =~ s/\%$//xms ) { + if ( !defined $max ) { + return 'max-prefix not specified and % check requested'; + } + + # convert to percent + $cnum = 100 * $cnum / $max; + } + + my @nums = ( $cnum, $check ); + my $abovebelow = 'below'; + my $symbol = '<'; + if ( $dir eq 'high' ) { + @nums = ( $check, $cnum ); + $abovebelow = 'above'; + $symbol = '>'; + } + + if ( $nums[0] < $nums[1] ) { + return join q{ }, 'is', $abovebelow, + 'threshold (' . $d, + $symbol, $c->{$dir} . ')'; + } } } @@ -235,20 +264,27 @@ state( $w, $c ); my $opt = shift @argv; - given ($opt) { + for ($opt) { when ( '-V' || '--version' ) { - print_revision( $PROGNAME, '$Revision: 1.1 $ ' ); + print_revision( $PROGNAME, '$Revision: 1.10 $ ' ); exit $ERRORS{'OK'} } - when ( /^-?-h(?:elp)?/xms ) { print_help(); exit $ERRORS{'OK'} } - when ( /^-?-w(?:arning)?/xms ) { $w = parse_check( shift @argv ) } - when ( /^-?-c(?:ritical)?/xms ) { $c = parse_check( shift @argv ) } - when ( /^-?-n(?:eighbor)?/xms ) { + when (/^-?-h(?:elp)?/xms) { print_help(); exit $ERRORS{'OK'} } + when (/^-?-s(?:ocket)?/xms) { $checks{_SOCKET} = shift @argv } + when (/^-?-w(?:arning)?/xms) { $w = parse_check( shift @argv ) } + when (/^-?-c(?:ritical)?/xms) { $c = parse_check( shift @argv ) } + when (/^-?-u(?:nknown)?/xms) { + $checks{_UNKNOWN} = { + WARNING => $w, + CRITICAL => $c, + }; + } + when (/^-?-n(?:eighbor)?/xms) { while ( @argv && $argv[0] !~ /^-/xms ) { $checks{ shift @argv } = { - WARNING => $w, - CRITICAL => $c - } + WARNING => $w, + CRITICAL => $c, + }; } } default { print_help(); exit $ERRORS{'UNKNOWN'} } @@ -259,43 +295,82 @@ sub print_help { print <<"EOL"; -$PROGNAME - monitors sysctl hw.bgpstatus on OpenBSD - $PROGNAME [ -w ENTRY ][ -c ENTRY ][ -n NEIGHBOR [ NEIGHBOR2 ] ] +$PROGNAME - checks status of OpenBGPd peers + $PROGNAME [ -s SOCKET ][ -w ENTRY ][ -c ENTRY ]( -u | -n NEIGHBOR ) Usage: + -s, --socket SOCKET + Path to bgpd socket to use. See -r in bgpd(8). -w, --warning RANGE or single ENTRY Exit with WARNING status if outside of RANGE or if != ENTRY + May be entered multiple times. -c, --critical RANGE or single ENTRY Exit with CRITICAL status if outside of RANGE or if != ENTRY + May be entered multiple times. -n, --neighbor NEIGHBOR - The name of the Neighbor + The name of the Neighbor, can be a space separated list of neighbors. + May be entered multiple times. + -u, --unknown + As if you specified -n for all unknown neighbors ENTRY is a comma separated list of items to match against. Each item can be a RANGE or it will just be matched against the status. RANGE is specified as two optional numbers separated with a colon (:). The check is that the value is between the two numbers. If either number is left -off, that check is ignored +off, that check is ignored. +If either number in a RANGE is specified as a percent, check is that +max-prefix is specified and that the number is within the specified percent. + NEIGHBOR is the name that shows when running "bgpctl show summary" Examples: +(where many of the numbers would probably have to be multiplied by 1000) -$PROGNAME -w 10000:300000 -c 1000:500000 -n eBGP1 eBGP2 -n eBGP3 +Any time a NEIGHBOR is specified on the command line but does NOT show up in +the output causes a CRITICAL result. -Checks that peers eBGP1, eBGP2 and eBGP2 are within the ranges specified +Any time a NEIGHBOR that is NOT specified on the command line shows up in the +output causes a CRITICAL result. If -u is specified, it treats NEIGHBOR as if +it were specified at that position. -$PROGNAME -c 1:1 -n eBGP1 -w 200000:300000 -c 100: -n iBGP1 -Checks that 1 and only 1 prefix is received from from eBGP1, warns if less -than 200000 or more than 300000 prefixes are recieved from peer iBGP1 and is -critical if less than 100 prefixes are recieved from peer iBGP1 +$PROGNAME -c Idle -n P1 -c 1:1 -n P2 -w 200:300 -c Active,10: -n P3 -$PROGNAME -c Idle -n iBGP1 -w +CRITICAL + If P1 is any value but Idle. + If P2 is any value but 1. + If P3 is below 10 or any non-numeric value other than "Active". +WARNING + If P3 is above 10 and below 200 or above 300. + + +$PROGNAME -u -w 50%:70% -c 10%:90% -n P2 P3 + +No checks of unknown neighbors. + +CRITICAL + If P2 or P3 do not have max-prefix set or if they do but learned prefixes + are below 10% or above 90% of max-prefix or any non-numeric value. + +WARNING + If P2 or P3 have learned prefixes below 50% or above 70% of max-prefix. + + +$PROGNAME -w 50%:70% -c 10%:90% -u + +CRITICAL + If any neighbor does not have max-prefix set or if they do but learned + prefixes are below 10% or above 90% of max-prefix or any non-numeric value. + +WARNING + If any neighbor have learned prefixes below 50% or above 70% of max-prefix. + EOL - print_revision( $PROGNAME, '$Revision: 1.1 $' ); + print_revision( $PROGNAME, '$Revision: 1.10 $' ); print $LICENSE;