#!/usr/bin/perl -w 
# Author  : Tony Wasson (ajwasson@gmail.com) based on a heavily hacked copy of check_snmp_load by Patrick Proy ( patrick at proy.org)

#use strict;
use Net::SNMP;
use Getopt::Long;

# Customize for your nagios install
use lib "/usr/local/nagios/libexec";
use utils qw(%ERRORS $TIMEOUT);

#Put Your default SNMP info here
my $o_community = "public"; 	# community
my $o_port = 	161; 		# port

#If you don't setup exec like I did change this
my $EXEC_STATUS_MIB = ".1.3.6.1.4.1.2021.8.2.100";
my $EXEC_STATUS_OID = "$EXEC_STATUS_MIB.100.1";
my $EXEC_STATUSMSG_OID = "$EXEC_STATUS_MIB.101.1";

# Here is a bad condition
#UCD-SNMP-MIB::extTable.2.100.102.1 = INTEGER: 0
#$ snmpwalk -v1 -c your-community-name 192.168.1.1 .1.3.6.1.4.1.2021.8.2
#UCD-SNMP-MIB::extTable.2.100.1.1 = INTEGER: 1
#UCD-SNMP-MIB::extTable.2.100.2.1 = STRING: "waiting-query-check"
#UCD-SNMP-MIB::extTable.2.100.3.1 = STRING: "/usr/local/bin/waiting-query-check "
#UCD-SNMP-MIB::extTable.2.100.100.1 = INTEGER: 2
#UCD-SNMP-MIB::extTable.2.100.101.1 = STRING: "postgres     9798  0.2  0.2 77424 2712 ?        S    09:43   0:00 postgres: postgres stuff [local] INSERT waiting         

#UCD-SNMP-MIB::extTable.2.100.102.1 = INTEGER: 0

# Here is a normal condition
#$ snmpwalk -v1 -c your-community-name 192.168.1.1 .1.3.6.1.4.1.2021.8.2
#UCD-SNMP-MIB::extTable.2.100.1.1 = INTEGER: 1
#UCD-SNMP-MIB::extTable.2.100.2.1 = STRING: "waiting-query-check"
#UCD-SNMP-MIB::extTable.2.100.3.1 = STRING: "/usr/local/bin/waiting-query-check "
#UCD-SNMP-MIB::extTable.2.100.100.1 = INTEGER: 0
#UCD-SNMP-MIB::extTable.2.100.101.1 = STRING: "No queries waiting"
#UCD-SNMP-MIB::extTable.2.100.102.1 = INTEGER: 0

#We care about these 2 lines:
#UCD-SNMP-MIB::extTable.2.100.100.1 = INTEGER: 0
#UCD-SNMP-MIB::extTable.2.100.101.1 = STRING: "No queries waiting"


# Globals

my $o_host; 		# hostname
my $o_help=	undef; 		# wan't some help ?
my $o_verb=	undef;		# verbose mode
my $o_timeout=  5;             	# Default 5s Timeout
my $o_perf=     undef;          # Output performance data

# functions

sub print_usage {
	print "Usage: $0 [-v] -H <host> -C <snmp_community> [-p <port>] [-V]\n";
}

sub isnnum { # Return true if arg is not a number
	my $num = shift;
	if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;}
	return 1;
}

sub help {
	print "\nPostgresql Waiting Query Check\n";
	print_usage();
}

# For verbose output
sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; }

sub check_options {
	Getopt::Long::Configure ("bundling");
	GetOptions(
			'v'	=> \$o_verb,		'verbose'	=> \$o_verb,
			'h'     => \$o_help,    	'help'        	=> \$o_help,
			'H:s'   => \$o_host,		'hostname:s'	=> \$o_host,
			'p:i'   => \$o_port,   		'port:i'	=> \$o_port,
			'C:s'   => \$o_community,	'community:s'	=> \$o_community,
			't:i'   => \$o_timeout,       	'timeout:i'     => \$o_timeout,
			'V'	=> \$o_version,		'version'	=> \$o_version,
			'c:s'   => \$o_crit,            'critical:s'    => \$o_crit,
			'w:s'   => \$o_warn,            'warn:s'        => \$o_warn,
			'f'     => \$o_perf,            'perfparse'     => \$o_perf
		  );
	if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}};
	if ( ! defined($o_host) ) # check host and filter 
	{ print_usage(); exit $ERRORS{"UNKNOWN"}}
# check snmp information
	if ( !defined($o_community) )
	{ print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}}
}

########## MAIN #######

check_options();

# Check global timeout if snmp screws up
if (defined($TIMEOUT)) {
	verb("Alarm at $TIMEOUT + 5");
	alarm($TIMEOUT+5);
} else {
	verb("no timeout defined : $o_timeout + 10");
	alarm ($o_timeout+10);
}

# Connect to host
my ($session, $error) = Net::SNMP->session(
					-hostname  => $o_host,
					-community => $o_community,
					-port      => $o_port,
					-timeout   => $o_timeout
				       );
if (!defined($session)) {
	printf("ERROR opening session: %s.\n", $error);
	exit $ERRORS{"UNKNOWN"};
}

my $exit_val=$ERRORS{"UNKNOWN"};

#Get status
my $result_status = $session->get_table(
		Baseoid => $EXEC_STATUS_MIB
		); 
if (!defined($result_status)) {
	printf("ERROR: Description table : %s.\n", $session->error);
	exit $ERRORS{"UNKNOWN"};
}

#check status
foreach my $key ( keys %$result_status) {
	verb("OID : $key, Desc : $$result_status{$key}");
	#print "Checking: $key, $$result_status{$key}\n";
	if ($key =~ /$EXEC_STATUS_OID/)
	{
		if ($$result_status{$key} > 0)
		{
			$exit_val=$ERRORS{"CRITICAL"};
		}
        else
        {
            #It must be ok
          	$exit_val=$ERRORS{"OK"};
        }
	}
	elsif ($key =~ /$EXEC_STATUSMSG_OID/)
	{
		#pgsql    12719  0.0  0.2 77424 2720 ?        S    10:49   0:00 postgres: pgsql start [local] INSERT waiting
		$output=$$result_status{$key};
	}
	else {
		#It is all good
	}
}
$session->close;

#New error handler -- testing
if ($exit_val eq $ERRORS{"CRITICAL"})
{
	print " CRITICAL $output"; 
	exit $ERRORS{"CRITICAL"};
}
elsif ($exit_val eq $ERRORS{"WARNING"})
{
	print " WARNING $output";
	exit $ERRORS{"WARNING"};
}
elsif ($exit_val eq $ERRORS{"OK"}) 
{
	print " OK $output";
	exit $ERRORS{"OK"};

}
else 
{
	print " UNKNOWN";
	exit $ERRORS{"UNKNOWN"};
}

