File check_nsca of Package monitoring-plugins-nsca

#!/usr/bin/perl -w
#
# Copyright (c) 2015, SUSE Linux GmbH
#
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# 1) Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 
# 2) Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#     and/or other materials provided with the distribution.
# 
# 3) Neither the name of the ORGANIZATION nor the names of its contributors may
#    be used to endorse or promote products derived from this software without
#    specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
use strict;
use warnings;
use Carp;
use Pod::Usage;
use Time::HiRes qw( gettimeofday );
use Getopt::Long;
Getopt::Long::Configure('bundling');

our $conf = {
    'VERSION'           => '1.0',
    'PROGNAME'          => 'check_nsca',
    'send_nsca'         => '/usr/bin/send_nsca',
    'send_nsca_cfg'     => '/etc/send_nsca.cfg',   #'/etc/nagios/send_nsca.cfg',
    'nsca_send_host'    => 'watson',
    'nsca_receive_host' => 'watson',
    'nsca_check_description' => 'NSCA dummy test',
    'nsca_check_result'      => 'Last test run:',
    'debug'             => 0,
    'timeout'           => 60,
    'sleeptime'         => 5,
    'livestatus_socket' => '/var/spool/check_mk/livestatus.cmd',
};
our $print_version = 0;
our $print_help    = 0;
our %ERRORS          = (
    'OK'        => 0,
    'WARNING'   => 1,
    'CRITICAL'  => 2,
    'UNKNOWN'   => 3,
    'DEPENDENT' => 4,
);

#######################################################################
# Functions
#######################################################################

sub print_myrevision ($$) {
    my ($commandName,$pluginRevision) = @_;
    print "$commandName v$pluginRevision\n";
}

sub send_nsca_message($$){
	my ($conf,$timestamp) = @_;
	# sending STDOUT to /dev/null as send_nsca is producing "debug" output otherwise
	open(SEND,"| $conf->{'send_nsca'} -H $conf->{'nsca_receive_host'} -c $conf->{'send_nsca_cfg'} 1>/dev/null") or warn ("Could not open pipe to $conf->{'send_nsca'}\n");
	if ( $conf->{'debug'} ){
		print STDERR "SENDING: $conf->{'nsca_send_host'}\\t$conf->{'nsca_check_description'}\\t0\\t$conf->{'nsca_check_result'} ${timestamp}\n";
	}
	print SEND "$conf->{'nsca_send_host'}\t$conf->{'nsca_check_description'}\t0\t$conf->{'nsca_check_result'} ${timestamp}";
	close(SEND);
}

sub get_livestatus_result($){
 	my ($conf) = @_;
	use Monitoring::Livestatus;
	my $ml = Monitoring::Livestatus->new(
		socket => $conf->{'livestatus_socket'},
	);
	my $ml_result = $ml->selectall_arrayref("GET services\nColumns: plugin_output\nFilter: host_name = $conf->{'nsca_send_host'}\nFilter: description = $conf->{'nsca_check_description'}\nLimit: 1");
	if($Monitoring::Livestatus::ErrorCode) {
		croak($Monitoring::Livestatus::ErrorMessage);
	} 
 	if ( $conf->{'debug'} ){
		use Data::Dumper; 
		print "selectall_arrayref result (from Livestatus):\n".Dumper($ml_result)."\n";
	}
	$ml_result->[0]->[0] =~ s/\s*$conf->{'nsca_check_result'}\s*//;
	return($ml_result->[0]->[0])
}

#######################################################################
# Main
#######################################################################

GetOptions(
    "V"                          => \$print_version,
    "Version"                    => \$print_version,
    "h"                          => \$print_help,
    "help"                       => \$print_help,
    "debug"                      => \$conf->{'debug'},
    "send_nsca=s"                => \$conf->{'send_nsca'},
    "send_nsca_cfg=s"            => \$conf->{'send_nsca_cfg'},
    "nsca_send_host=s"           => \$conf->{'nsca_send_host'},
    "nsca_receive_host=s"        => \$conf->{'nsca_receive_host'},
    "nsca_check_description=s"   => \$conf->{'nsca_check_description'},
    "nsca_check_result=s"        => \$conf->{'nsca_check_result'},
    "sleeptime=i"                => \$conf->{'sleeptime'},
    "livestatus_socket=s"        => \$conf->{'livestatus_socket'},
    "timeout"                    => \$conf->{'timeout'},
) or print_help(2);

pod2usage(
    -exitstatus => 0,
    -verbose    => 1,    # 2 to print full pod
) if $print_help;

if ($print_version) {
    print_myrevision( $conf->{'PROGNAME'}, $conf->{'VERSION'} );
    exit 0;
}

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
    print "UNKNOWN - Plugin timed out\n";
    exit $ERRORS{'UNKNOWN'};
};
alarm($conf->{'timeout'});

if (! -x "$conf->{'send_nsca'}" ){
	print "UNKNOWN: could not execute $conf->{'send_nsca'}\n";
	exit $ERRORS{'UNKNOWN'};
}

if (! -r "$conf->{'send_nsca_cfg'}" ){
	print "UNKNOWN: could not read $conf->{'send_nsca_cfg'}\n";
	exit $ERRORS{'UNKNOWN'};
}
if (! -S "$conf->{'livestatus_socket'}" ){
	print "CRICITAL: no socket found at $conf->{'livestatus_socket'}\n";
	exit $ERRORS{'CRITICAL'};
}

my $timestamp=gettimeofday();
send_nsca_message($conf, $timestamp);

# now we need to sleep for a while to give NSCA and Nagios/Icinga time to submit and update the value
if ( $conf->{'debug'} ){
	print "Sleeping for $conf->{'sleeptime'} seconds\n";
}
sleep $conf->{'sleeptime'};

# get the service output from Nagios/Icinga and compare it with the timestamp submitted before
my $res_timestamp=get_livestatus_result($conf);

if ( "$res_timestamp" eq "$timestamp" ){
	print "OK: NSCA seems to work";
	exit $ERRORS{'OK'};
}
else {
	print "CRITICAL: expected timestamp $timestamp but got $res_timestamp";
	exit $ERRORS{'CRITICAL'};
}

__END__


=head1 check_nsca

Check if the Nagios Service Check Acceptor is running and can successful submit check results 
to a running Nagios or Icinga instance.

=head1 SYNOPSIS

./check_nsca [options]

 Options:

    --help
    --debug
    --version

    --send_nsca
    --send_nsca_cfg

    --nsca_send_host
    --nsca_receive_host
    --nsca_check_description
    --nsca_check_result

    --livestatus_socket
    --sleeptime
    --timeout

=head1 OPTIONS

=over 8

=item B<--help>

Produces this output.

=item B<--debug>

Print debug output on STDERR.

=item B<--version>

Print current version number of this check.

=item B<--send_nsca>

Path to the send_nsca binary (default: /usr/bin/send_nsca).

=item B<--send_nsca_cfg>

Path to the send_nsca configuration file (default: /etc/send_nsca.cfg).

=item B<--nsca_receive_host>

The hostname with the NSCA test definition (used in send_nsca).

=item B<--nsca_check_description>

The service description of the NSCA test definition (default: 'NSCA dummy test').

=item B<--nsca_check_result>

The content of the NSCA test result (will be ignored, but might be useful for humans (default: 'Last test run:').

=item B<--sleeptime>

How long in seconds to wait between the submission of the test result and the search for the correct value (NSCA <-> Nagios/Icinga <-> updated result; default: 5).

=item B<--timeout>

Timeout in seconds for the whole script, to not hang Nagios (default: 60).

=item B<--livestatus_socket>

The path to the livestatus socket (default: /var/spool/check_mk/livestatus.cmd)

=back

=head1 DESCRIPTION

Sometimes you wonder if your NSCA is still up and running (especially if you forget to define freshness values for your passive checks ;-).
This script might help you here as it:

=over 8

=item * sends a test message to your NSCA instance

=item * waits a few seconds (to give NSCA and Nagios/Icinga time to process the results)

=item * checks if the message was delivered to Nagios/Icinga successfully by checking the result of the check

=back

=head1 CONFIGURATION

Write the following in your /etc/icinga or /etc/nagios configuration files:
 define command{
        command_name check_nsca
        command_line $USER1$/check_nsca
 }

 define service {
        use                     nsca-service-template
        hostgroup_name          nsca_dummy_check
        check_freshness         1
        freshness_threshold     93600   ; 26 hour threshold
        service_description     NSCA dummy test
        check_period            none
 }

 define service {
        use                     service-template
        hostgroup_name          check_nsca
        service_description     NSCA
        check_command           check_nrpe!check_nsca
 }

and in /etc/nrpe.cfg (or in /etc/nrpe.d/nsca.cfg):
 command[check_nsca]=/usr/lib/nagios/plugins/check_nsca

=head1 AUTHORS

Written by Lars Vogdt <lrupp@suse.com>

=head1 SUPPORT

Please use https://bugzilla.suse.com to submit patches or suggest improvements.

Include version information with all correspondence (when possible use output from 
the --version option of the plugin itself).

=cut

openSUSE Build Service is sponsored by