diff options
| author | EUcancER <root@euer.krebsco.de> | 2012-10-05 10:46:47 +0200 |
|---|---|---|
| committer | EUcancER <root@euer.krebsco.de> | 2012-10-05 10:46:47 +0200 |
| commit | c5fcba52713424c1653b802b4090bb182782362d (patch) | |
| tree | 1cce378e27e4a5672672185f5c93ee2a25a1c224 /Monitoring/nagios/plugins | |
| parent | 07939d80687399a8ad2fff0242b708013018cc14 (diff) | |
| parent | 6c89839b7fc344608e61c8916ac9d9925fa98d14 (diff) | |
Merge branch 'master' of github.com:krebscode/painload
Diffstat (limited to 'Monitoring/nagios/plugins')
92 files changed, 6257 insertions, 0 deletions
diff --git a/Monitoring/nagios/plugins/check.bat b/Monitoring/nagios/plugins/check.bat new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/Monitoring/nagios/plugins/check.bat diff --git a/Monitoring/nagios/plugins/check.sh b/Monitoring/nagios/plugins/check.sh new file mode 100755 index 00000000..9e62fbee --- /dev/null +++ b/Monitoring/nagios/plugins/check.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "When in doubt... blow it up. | cpu=100%" +#sleep 1.5 +exit 0 diff --git a/Monitoring/nagios/plugins/check_apt b/Monitoring/nagios/plugins/check_apt Binary files differnew file mode 100755 index 00000000..2371c32d --- /dev/null +++ b/Monitoring/nagios/plugins/check_apt diff --git a/Monitoring/nagios/plugins/check_bgpstate b/Monitoring/nagios/plugins/check_bgpstate new file mode 100755 index 00000000..645d7505 --- /dev/null +++ b/Monitoring/nagios/plugins/check_bgpstate @@ -0,0 +1,215 @@ +#!/usr/bin/perl -w +# +# check_bgpstate.pl - nagios plugin +# +# Copyright (C) 2000 Christoph Kron +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# Report bugs to: ck@zet.net +# +# 11.01.2000 Version 1.0 + + + +use strict; + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + + +# whois programm for RIPE database queries +my $whois = '/usr/bin/whois'; +my $status; +my $TIMEOUT = 30; + +# critical bgp sessions +my %uplinks = ( 1273, 'Uplink ECRC', + 1755, 'Uplink EBONE', + 3300, 'Uplink AUCS' + ); + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + + +my %bgpPeerState = ( + '1',"idle", + '2',"connect", + '3',"active", + '4',"opensent", + '5',"openconfirm", + '6',"established" + ); +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey; +my $snmpoid; +my $key; +my $community = "public"; +my $port = 161; +my @snmpoids; +my $snmpbgpPeerState = '1.3.6.1.2.1.15.3.1.2'; +my $snmpbgpPeerLocalAddr = '1.3.6.1.2.1.15.3.1.5'; +my $snmpbgpPeerRemoteAddr = '1.3.6.1.2.1.15.3.1.7'; +my $snmpbgpPeerRemoteAs = '1.3.6.1.2.1.15.3.1.9'; +my $hostname; +my $session; +my $error; +my $response; +my %bgpStatus; +my $bgpestablished =0 ; +my $bgpcritical =0; +my $bgpdown =0; +my $bgpidle =0; +my $bgpmessage; +my $asname; +my $remoteas; +my @output; + +sub usage { + printf "\nMissing arguments!\n"; + printf "\n"; + printf "Perl bgpstate plugin for Nagios\n"; + printf "monitors all BGP sessions\n"; + printf "usage: \n"; + printf "check_bgpstate.pl -c <READCOMMUNITY> -p <PORT> <HOSTNAME>\n"; + printf "Copyright (C) 2000 Christoph Kron\n"; + printf "check_bgpstate.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +$status = GetOptions("community=s",\$community, + "port=i",\$port); +if ($status == 0) +{ + &usage; +} + + #shift; + $hostname = shift || &usage; + + +push(@snmpoids, $snmpbgpPeerState); +push(@snmpoids, $snmpbgpPeerLocalAddr); +push(@snmpoids, $snmpbgpPeerRemoteAddr); +push(@snmpoids, $snmpbgpPeerRemoteAs); + +foreach $snmpoid (@snmpoids) { + + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -community => $community, + -port => $port + ); + + if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer"); + exit $ERRORS{$state}; + } + + if (!defined($response = $session->get_table($snmpoid))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + print ("$state: $answer,$snmpkey"); + exit $ERRORS{$state}; + } + + foreach $snmpkey (keys %{$response}) { + $snmpkey =~ m/.*\.(\d+\.\d+\.\d+\.\d+$)/; + $key = $1; +# printf "debug: $snmpkey: $key -> $response->{$snmpkey}\n"; + $bgpStatus{$key}{$snmpoid} = $response->{$snmpkey}; + } + $session->close; +} + +foreach $key (keys %bgpStatus) { + if ($bgpStatus{$key}{$snmpbgpPeerState} == 6 ) { + $bgpestablished++; + } + elsif ($bgpStatus{$key}{$snmpbgpPeerState} == 1 ) { + $bgpidle++; + } + else { + $bgpdown++ ; + if (exists($uplinks{$bgpStatus{$key}{$snmpbgpPeerRemoteAs}}) ) { + $bgpcritical++; + } + @output = `$whois -T aut-num AS$bgpStatus{$key}{$snmpbgpPeerRemoteAs}`; + + $asname = ""; + foreach (@output) { + if (m/as-name/) { + $asname = $_; + $asname =~ s/as-name://; + last; + } + if ( $asname =~ "" && m/descr/ ) { + $asname = $_; + $asname =~ s/descr://; + } + } + $asname =~ s/^\s*//; + $asname =~ s/\s*$//; + $bgpmessage .= sprintf("Peering with AS%s not established -> %s<BR>", + $bgpStatus{$key}{$snmpbgpPeerRemoteAs}, + $asname); + } +} + + + if ($bgpdown > 0) { + if ($bgpcritical > 0) { + $state = 'CRITICAL'; + } + else { + $state = 'WARNING'; + } + $answer = sprintf("host '%s', sessions up: %d, down: %d, shutdown: %d<BR>", + $hostname, + $bgpestablished, + $bgpdown, $bgpidle); + $answer = $answer . $bgpmessage . "\n"; + } + else { + $state = 'OK'; + $answer = sprintf("host '%s', sessions up: %d, down: %d, shutdown: %d\n", + $hostname, + $bgpestablished, + $bgpdown,$bgpidle); + } + +print ("$state: $answer"); +exit $ERRORS{$state}; + diff --git a/Monitoring/nagios/plugins/check_breeze b/Monitoring/nagios/plugins/check_breeze new file mode 100755 index 00000000..d0382e69 --- /dev/null +++ b/Monitoring/nagios/plugins/check_breeze @@ -0,0 +1,87 @@ +#! /usr/bin/perl -wT + + +use strict; +use Getopt::Long; +use vars qw($opt_V $opt_h $opt_w $opt_c $opt_H $opt_C $PROGNAME); +use lib "/usr/lib/nagios/plugins" ; +use utils qw(%ERRORS &print_revision &support &usage); + +$PROGNAME = "check_breeze"; + +sub print_help (); +sub print_usage (); + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +Getopt::Long::Configure('bundling'); +GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "w=s" => \$opt_w, "warning=s" => \$opt_w, + "c=s" => \$opt_c, "critical=s" => \$opt_c, + "H=s" => \$opt_H, "hostname=s" => \$opt_H, + "C=s" => \$opt_C, "community=s" => \$opt_C); + +if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); + exit $ERRORS{'OK'}; +} + +if ($opt_h) {print_help(); exit $ERRORS{'OK'};} + +($opt_H) || usage("Host name/address not specified\n"); +my $host = $1 if ($opt_H =~ /([-.A-Za-z0-9]+)/); +($host) || usage("Invalid host: $opt_H\n"); + +($opt_w) || usage("Warning threshold not specified\n"); +my $warning = $1 if ($opt_w =~ /([0-9]{1,2}|100)+/); +($warning) || usage("Invalid warning threshold: $opt_w\n"); + +($opt_c) || usage("Critical threshold not specified\n"); +my $critical = $1 if ($opt_c =~ /([0-9]{1,2}|100)/); +($critical) || usage("Invalid critical threshold: $opt_c\n"); + +($opt_C) || ($opt_C = "public") ; + +my $sig=0; +$sig = `snmpget $host $opt_C .1.3.6.1.4.1.710.3.2.3.1.3.0`; +my @test=split(/ /,$sig); +$sig=$test[2]; +$sig=int($sig); +if ($sig>100){$sig=100} + +print "Signal Strength at: $sig%\n"; + +exit $ERRORS{'CRITICAL'} if ($sig<$critical); +exit $ERRORS{'WARNING'} if ($sig<$warning); +exit $ERRORS{'OK'}; + + +sub print_usage () { + print "Usage: $PROGNAME -H <host> [-C community] -w <warn> -c <crit>\n"; +} + +sub print_help () { + print_revision($PROGNAME,'1.4.15'); + print "Copyright (c) 2000 Jeffrey Blank/Karl DeBisschop + +This plugin reports the signal strength of a Breezecom wireless equipment + +"; + print_usage(); + print " +-H, --hostname=HOST + Name or IP address of host to check +-C, --community=community + SNMPv1 community (default public) +-w, --warning=INTEGER + Percentage strength below which a WARNING status will result +-c, --critical=INTEGER + Percentage strength below which a CRITICAL status will result + +"; + support(); +} diff --git a/Monitoring/nagios/plugins/check_btcguild_miner b/Monitoring/nagios/plugins/check_btcguild_miner new file mode 100755 index 00000000..2e6a8de3 --- /dev/null +++ b/Monitoring/nagios/plugins/check_btcguild_miner @@ -0,0 +1,36 @@ +#!/usr/bin/python + +import sys +from urllib2 import urlopen +try: + import json + getattr(json,"load") +except: #deal with it + import simplejson as json + +if len(sys.argv) != 4 : + print "** Usage: %s APIKEY WORKER_NAME LOW_WORKER_SPEED" % sys.argv[0] + print "** aka YOU ARE MADE OF STUPID" + exit (3) + +API_KEY=sys.argv[1] +WORKER_NAME=sys.argv[2] +LOW_WORKER_SPEED=float(sys.argv[3]) +url="http://www.btcguild.com/api.php?api_key=%s" % API_KEY +try: + fh = urlopen(url) + result = json.load(fh) +except Exception,e: + print "?? cannot parse json or connect to server: %s"% str(e) + exit (1) + +for k,v in result["workers"].iteritems(): + if v["worker_name"] == WORKER_NAME: + curr = v["hash_rate"] + if curr < LOW_WORKER_SPEED: + print "!! %f is below expected %f" % (curr,LOW_WORKER_SPEED) + exit (2) + else: + print "++ everything fine, current speed is %f" % curr + exit(0) + diff --git a/Monitoring/nagios/plugins/check_by_ssh b/Monitoring/nagios/plugins/check_by_ssh Binary files differnew file mode 100755 index 00000000..5f969058 --- /dev/null +++ b/Monitoring/nagios/plugins/check_by_ssh diff --git a/Monitoring/nagios/plugins/check_clamd b/Monitoring/nagios/plugins/check_clamd new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_clamd @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_cluster b/Monitoring/nagios/plugins/check_cluster Binary files differnew file mode 100755 index 00000000..8d6dbb90 --- /dev/null +++ b/Monitoring/nagios/plugins/check_cluster diff --git a/Monitoring/nagios/plugins/check_cpu b/Monitoring/nagios/plugins/check_cpu new file mode 100755 index 00000000..26a93da5 --- /dev/null +++ b/Monitoring/nagios/plugins/check_cpu @@ -0,0 +1,165 @@ +#!/usr/bin/python + +import string, os, sys, re +#from optik import OptionParser +from optparse import OptionParser + + + +####################################### +### Define a set of strings to handle +### any info output requirements. + + +check_cpu_version = "check_cpu (nagios-plugins 1.5.1!?) 0.4.0a\n" + +intro = "The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\ncopies of the plugins under the terms of the GNU General Public License.\nFor more information about these matters, see the file named COPYING.\nCopyright (c) 2004 Ethan Galstad/Karl DeBisschop\n\n" + +preamble = "This plugin will check the percent of idle CPU usage on the system it is\nexecuted on and generate an alert if the percentage is below\none of the threshold values.\n\n" + +use = "Usage:\tcheck_cpu -w limit -c limit [-t timeout]\n\tcheck_cpu (-h|--help)\n\tcheck_cpu (-V|--version)\n" + +options = "\n -w, --warning=PERCENT\n\tExit with WARNING status if idle CPU percentage is less than PERCENT\n -c, --critical=PERCENT\n\tExit with CRITICAL status if idle CPU percentage is less than PERCENT\n -t, --timeout=INTEGER\n\tSeconds before check attempt times out (default: 10)\n -s, --sample=INTEGER\n\tSeconds to use as sample time. (default: 5)\n -h, --help\n\tPrint detailed help screen\n -V, --version\n\tPrint version information\n\n" + +bugs = "Bugs:\tTimeout does not do what has been documented here. Rather, it does \nnothing. The plugin seems to ignore characters that are not attached to \nparameter syntax. This has been tested on RedHat 8.0+, Fedora Core 1 & 2, \nOpenBSD 3.x and Debian. I would appreciate feedback and/or patches if it doesn't\nfunction under your chosen operating system.\n\n" + +query = "Send email to nagios-users@lists.sourceforge.net if you have questions\nregarding the use of this software. To submit patches or suggest improvements,\nsend email to nagiosplug-devel@lists.sourceforge.net.\n\nFor questions and suggestions pertaining to the check_cpu plugin,\nplease send email to nemir@hotmail.com.\n" + +fullHelp = check_cpu_version + intro + preamble + use + options + bugs + query + + + + + +def helpFunc(option, opt, value, parser): + print fullHelp + sys.exit(3) + +def verFunc(option, opt, value, parser): + print check_cpu_version + sys.exit(3) + + + + +####################################### +### Parse all the parameters. Define +### variables for later use. + + + +parser = OptionParser(add_help_option=0) + +parser.add_option("-h", "--help", action="callback", callback=helpFunc) +parser.add_option("-V", "--version", action="callback", callback=verFunc) +parser.add_option("-w", "--warning", action="store", type="int", dest="warn", default=-1) +parser.add_option("-c", "--critical", action="store", type="int", dest="crit", default=-2) +parser.add_option("-s", "--sample", action="store", type="int", dest="sample", default=5) +parser.add_option("-t", "--timeout", action="store", type="int", dest="timeout", default=10) + +(options, args) = parser.parse_args() + +critical = options.crit +warning = options.warn +sample = options.sample +timeout = options.timeout + + +if -3 > critical or 101 < critical: + print "Critical value is a percentage and must be between 0 and 100.\n" + use + sys.exit(3) + +if -2 > warning or 101 < warning: + print "Warning value is a percentage and must be between 0 and 100.\n" + use + sys.exit(3) + +if critical >= warning: + print "Critical value must be less than the warning value.\n" + use + sys.exit(3) + +if sample >= timeout -1: + print "Sample time must be 2 seconds less than timeout.\n" + use + sys.exit(3) + +strSample = str(sample) + + +####################################### +### Determine what OS we are being run +### on, to figure syntax required. + + +v = os.popen("uname", "r") +l = v.read() + +if l == "Linux\n": + vmcmd = "/usr/bin/vmstat " + strSample + " 2" +elif l == "OpenBSD\n": + vmcmd = "/usr/bin/vmstat -c 2 -w " + strSample +elif l == "FreeBSD\n": + vmcmd = "/usr/bin/vmstat -c 2 -w " + strSample +elif l == "NetBSD\n": + vmcmd = "/usr/bin/vmstat -c 2 -w " + strSample +elif l == "SunOS\n": + vmcmd = "/usr/bin/vmstat " + strSample + " 2" +else: + print "Unknown operating system, unable to continue.\n" + sys.exit(3) + + +####################################### +### Grab the CPU sample and convert the +### the relevent info to an int. + + +vmstat = os.popen( vmcmd, "r" ) +statOut = vmstat.read() + + +statLines = string.split( statOut, '\n') +lastLine = statLines[-2].strip() + +n = len(statLines) +for i in range(0, n): + idcheck = re.search("id", statLines[i]) + if idcheck: + idLine = statLines[i].strip() + + + +idStr = re.sub( "[ \t\n\r\v]+", " ", idLine ) +idList = string.split(idStr, " ") +idColumn = idList.index("id") + +valueStr = re.sub( "[ \t\n\r\v]+", " ", lastLine ) +values = string.split( valueStr, ' ') + +idleCPU = values[idColumn] +sysCPU = values[-2] +userCPU = values[-3] + +idleValue = string.atoi(idleCPU) + + +####################################### +### Finally, determine and report CPU +### state, and exit the plugin. + + +if idleValue <= critical: + status = "CPU CRITICAL" + print status + ": CPU is only " + idleCPU + "% idle" + sys.exit(2) +elif idleValue <= warning: + status = "WARNING" + print status + ": CPU is only " + idleCPU + "% idle" + sys.exit(1) +elif warning < idleValue: + status = "OK" + print status + ": CPU is " + idleCPU + "% idle" + sys.exit(0) +else: + status = "CPU STATUS UNKNOWN" + print status + ": Could not complete check." + sys.exit(3) + diff --git a/Monitoring/nagios/plugins/check_dhcp b/Monitoring/nagios/plugins/check_dhcp Binary files differnew file mode 100755 index 00000000..6b51224f --- /dev/null +++ b/Monitoring/nagios/plugins/check_dhcp diff --git a/Monitoring/nagios/plugins/check_dig b/Monitoring/nagios/plugins/check_dig Binary files differnew file mode 100755 index 00000000..650608dc --- /dev/null +++ b/Monitoring/nagios/plugins/check_dig diff --git a/Monitoring/nagios/plugins/check_disk b/Monitoring/nagios/plugins/check_disk Binary files differnew file mode 100755 index 00000000..43dc43a3 --- /dev/null +++ b/Monitoring/nagios/plugins/check_disk diff --git a/Monitoring/nagios/plugins/check_disk_smb b/Monitoring/nagios/plugins/check_disk_smb new file mode 100755 index 00000000..80fa6779 --- /dev/null +++ b/Monitoring/nagios/plugins/check_disk_smb @@ -0,0 +1,307 @@ +#! /usr/bin/perl -w +# +# +# check_disk.pl <host> <share> <user> <pass> [warn] [critical] [port] +# +# Nagios host script to get the disk usage from a SMB share +# +# Changes and Modifications +# ========================= +# 7-Aug-1999 - Michael Anthon +# Created from check_disk.pl script provided with netsaint_statd (basically +# cause I was too lazy (or is that smart?) to write it from scratch) +# 8-Aug-1999 - Michael Anthon +# Modified [warn] and [critical] parameters to accept format of nnn[M|G] to +# allow setting of limits in MBytes or GBytes. Percentage settings for large +# drives is a pain in the butt +# 2-May-2002 - SGhosh fix for embedded perl +# +# + +require 5.004; +use POSIX; +use strict; +use Getopt::Long; +use vars qw($opt_P $opt_V $opt_h $opt_H $opt_s $opt_W $opt_u $opt_p $opt_w $opt_c $opt_a $verbose); +use vars qw($PROGNAME); +use lib "/usr/lib/nagios/plugins" ; +use utils qw($TIMEOUT %ERRORS &print_revision &support &usage); + +sub print_help (); +sub print_usage (); + +$PROGNAME = "check_disk_smb"; + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +Getopt::Long::Configure('bundling'); +GetOptions + ("v" => \$verbose, "verbose" => \$verbose, + "P=s" => \$opt_P, "port=s" => \$opt_P, + "V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "w=s" => \$opt_w, "warning=s" => \$opt_w, + "c=s" => \$opt_c, "critical=s" => \$opt_c, + "p=s" => \$opt_p, "password=s" => \$opt_p, + "u=s" => \$opt_u, "username=s" => \$opt_u, + "s=s" => \$opt_s, "share=s" => \$opt_s, + "W=s" => \$opt_W, "workgroup=s" => \$opt_W, + "H=s" => \$opt_H, "hostname=s" => \$opt_H, + "a=s" => \$opt_a, "address=s" => \$opt_a); + +if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); #' + exit $ERRORS{'OK'}; +} + +if ($opt_h) {print_help(); exit $ERRORS{'OK'};} + +my $smbclient = $utils::PATH_TO_SMBCLIENT; + +# Options checking + +($opt_H) || ($opt_H = shift @ARGV) || usage("Host name not specified\n"); +my $host = $1 if ($opt_H =~ /^([-_.A-Za-z0-9 ]+\$?)$/); +($host) || usage("Invalid host: $opt_H\n"); + +($opt_s) || ($opt_s = shift @ARGV) || usage("Share volume not specified\n"); +my $share = $1 if ($opt_s =~ /^([-_.A-Za-z0-9 ]+\$?)$/); +($share) || usage("Invalid share: $opt_s\n"); + +defined($opt_u) || ($opt_u = shift @ARGV) || ($opt_u = "guest"); +my $user = $1 if ($opt_u =~ /^([-_.A-Za-z0-9\\]*)$/); +defined($user) || usage("Invalid user: $opt_u\n"); + +defined($opt_p) || ($opt_p = shift @ARGV) || ($opt_p = ""); +my $pass = $1 if ($opt_p =~ /(.*)/); + +($opt_w) || ($opt_w = shift @ARGV) || ($opt_w = 85); +my $warn = $1 if ($opt_w =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/); +($warn) || usage("Invalid warning threshold: $opt_w\n"); + +($opt_c) || ($opt_c = shift @ARGV) || ($opt_c = 95); +my $crit = $1 if ($opt_c =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/); +($crit) || usage("Invalid critical threshold: $opt_c\n"); + +# Execute the given command line and return anything it writes to STDOUT and/or +# STDERR. (This might be useful for other plugins, too, so it should possibly +# be moved to utils.pm.) +sub output_and_error_of { + local *CMD; + local $/ = undef; + my $pid = open CMD, "-|"; + if (defined($pid)) { + if ($pid) { + return <CMD>; + } else { + open STDERR, ">&STDOUT" and exec @_; + exit(1); + } + } + return undef; +} + +# split the type from the unit value +#Check $warn and $crit for type (%/M/G) and set up for tests +#P = Percent, K = KBytes +my $warn_type; +my $crit_type; + +if ($opt_w =~ /^([0-9]+)\%?$/) { + $warn = "$1"; + $warn_type = "P"; +} elsif ($opt_w =~ /^([0-9]+)k$/) { + $warn_type = "K"; + $warn = $1; +} elsif ($opt_w =~ /^([0-9]+)M$/) { + $warn_type = "K"; + $warn = $1 * 1024; +} elsif ($opt_w =~ /^([0-9]+)G$/) { + $warn_type = "K"; + $warn = $1 * 1048576; +} +if ($opt_c =~ /^([0-9]+)\%?$/) { + $crit = "$1"; + $crit_type = "P"; +} elsif ($opt_c =~ /^([0-9]+)k$/) { + $crit_type = "K"; + $crit = $1; +} elsif ($opt_c =~ /^([0-9]+)M$/) { + $crit_type = "K"; + $crit = $1 * 1024; +} elsif ($opt_c =~ /^([0-9]+)G$/) { + $crit_type = "K"; + $crit = $1 * 1048576; +} + +# check if both warning and critical are percentage or size +unless( ( $warn_type eq "P" && $crit_type eq "P" ) || ( $warn_type ne "P" && $crit_type ne "P" ) ){ + $opt_w =~ s/\%/\%\%/g; + $opt_c =~ s/\%/\%\%/g; + usage("Both warning and critical should be same type- warning: $opt_w critical: $opt_c \n"); +} + +# verify warning is less than critical +if ( $warn_type eq "K") { + unless ( $warn > $crit) { + usage("Disk size: warning ($opt_w) should be greater than critical ($opt_c) \n"); + } +}else{ + unless ( $warn < $crit) { + $opt_w =~ s/\%/\%\%/g; + $opt_c =~ s/\%/\%\%/g; + usage("Percentage: warning ($opt_w) should be less than critical ($opt_c) \n"); + } +} + +my $workgroup = $1 if (defined($opt_W) && $opt_W =~ /(.*)/); + +my $address = $1 if (defined($opt_a) && $opt_a =~ /(.*)/); + +# end of options checking + + +my $state = "OK"; +my $answer = undef; +my $res = undef; +my @lines = undef; + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print "No Answer from Client\n"; + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + +# Execute an "ls" on the share using smbclient program +# get the results into $res +my @cmd = ( + $smbclient, + "//$host/$share", + "-U", "$user%$pass", + defined($workgroup) ? ("-W", $workgroup) : (), + defined($address) ? ("-I", $address) : (), + defined($opt_P) ? ("-p", $opt_P) : (), + "-c", "ls" +); + +print join(" ", @cmd) . "\n" if ($verbose); +$res = output_and_error_of(@cmd) or exit $ERRORS{"UNKNOWN"}; + +#Turn off alarm +alarm(0); + +#Split $res into an array of lines +@lines = split /\n/, $res; + +#Get the last line into $_ +$_ = $lines[$#lines]; +#print "$_\n"; + +#Process the last line to get free space. +#If line does not match required regexp, return an UNKNOWN error +if (/\s*(\d*) blocks of size (\d*)\. (\d*) blocks available/) { + + my ($avail) = ($3*$2)/1024; + my ($avail_bytes) = $avail; + my ($capper) = int(($3/$1)*100); + my ($mountpt) = "\\\\$host\\$share"; + + + if (int($avail / 1024) > 0) { + $avail = int($avail / 1024); + if (int($avail /1024) > 0) { + $avail = (int(($avail / 1024)*100))/100; + $avail = $avail ."G"; + } else { + $avail = $avail ."M"; + } + } else { + $avail = $avail ."K"; + } + +#print ":$warn:$warn_type:\n"; +#print ":$crit:$crit_type:\n"; +#print ":$avail:$avail_bytes:$capper:$mountpt:\n"; + + if ((($warn_type eq "P") && (100 - $capper) < $warn) || (($warn_type eq "K") && ($avail_bytes > $warn))) { + $answer = "Disk ok - $avail ($capper%) free on $mountpt\n"; + } elsif ((($crit_type eq "P") && (100 - $capper) < $crit) || (($crit_type eq "K") && ($avail_bytes > $crit))) { + $state = "WARNING"; + $answer = "WARNING: Only $avail ($capper%) free on $mountpt\n"; + } else { + $state = "CRITICAL"; + $answer = "CRITICAL: Only $avail ($capper%) free on $mountpt\n"; + } +} else { + $answer = "Result from smbclient not suitable\n"; + $state = "UNKNOWN"; + foreach (@lines) { + if (/(Access denied|NT_STATUS_LOGON_FAILURE|NT_STATUS_ACCESS_DENIED)/) { + $answer = "Access Denied\n"; + $state = "CRITICAL"; + last; + } + if (/(Unknown host \w*|Connection.*failed)/) { + $answer = "$1\n"; + $state = "CRITICAL"; + last; + } + if (/(You specified an invalid share name|NT_STATUS_BAD_NETWORK_NAME)/) { + $answer = "Invalid share name \\\\$host\\$share\n"; + $state = "CRITICAL"; + last; + } + } +} + + +print $answer; +print "$state\n" if ($verbose); +exit $ERRORS{$state}; + +sub print_usage () { + print "Usage: $PROGNAME -H <host> -s <share> -u <user> -p <password> + -w <warn> -c <crit> [-W <workgroup>] [-P <port>] [-a <IP>]\n"; +} + +sub print_help () { + print_revision($PROGNAME,'1.4.15'); + print "Copyright (c) 2000 Michael Anthon/Karl DeBisschop + +Perl Check SMB Disk plugin for Nagios + +"; + print_usage(); + print " +-H, --hostname=HOST + NetBIOS name of the server +-s, --share=STRING + Share name to be tested +-W, --workgroup=STRING + Workgroup or Domain used (Defaults to \"WORKGROUP\") +-a, --address=IP + IP-address of HOST (only necessary if HOST is in another network) +-u, --user=STRING + Username to log in to server. (Defaults to \"guest\") +-p, --password=STRING + Password to log in to server. (Defaults to an empty password) +-w, --warning=INTEGER or INTEGER[kMG] + Percent of used space at which a warning will be generated (Default: 85%) + +-c, --critical=INTEGER or INTEGER[kMG] + Percent of used space at which a critical will be generated (Defaults: 95%) +-P, --port=INTEGER + Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default) + + If thresholds are followed by either a k, M, or G then check to see if that + much disk space is available (kilobytes, Megabytes, Gigabytes) + + Warning percentage should be less than critical + Warning (remaining) disk space should be greater than critical. + +"; + support(); +} diff --git a/Monitoring/nagios/plugins/check_dns b/Monitoring/nagios/plugins/check_dns Binary files differnew file mode 100755 index 00000000..8a80b991 --- /dev/null +++ b/Monitoring/nagios/plugins/check_dns diff --git a/Monitoring/nagios/plugins/check_dummy b/Monitoring/nagios/plugins/check_dummy Binary files differnew file mode 100755 index 00000000..b66006ac --- /dev/null +++ b/Monitoring/nagios/plugins/check_dummy diff --git a/Monitoring/nagios/plugins/check_dummy.sh b/Monitoring/nagios/plugins/check_dummy.sh new file mode 100755 index 00000000..fe834bd0 --- /dev/null +++ b/Monitoring/nagios/plugins/check_dummy.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "Return in Dummy" $1 + +exit $1
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_file_age b/Monitoring/nagios/plugins/check_file_age new file mode 100755 index 00000000..7f20bad7 --- /dev/null +++ b/Monitoring/nagios/plugins/check_file_age @@ -0,0 +1,112 @@ +#! /usr/bin/perl -w + +# check_file_age.pl Copyright (C) 2003 Steven Grimm <koreth-nagios@midwinter.com> +# +# Checks a file's size and modification time to make sure it's not empty +# and that it's sufficiently recent. +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# you should have received a copy of the GNU General Public License +# along with this program (or with Nagios); if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA + +use strict; +use English; +use Getopt::Long; +use File::stat; +use vars qw($PROGNAME); +use lib "/usr/lib/nagios/plugins"; +use utils qw (%ERRORS &print_revision &support); + +sub print_help (); +sub print_usage (); + +my ($opt_c, $opt_f, $opt_w, $opt_C, $opt_W, $opt_h, $opt_V); +my ($result, $message, $age, $size, $st); + +$PROGNAME="check_file_age"; + +$opt_w = 240; +$opt_c = 600; +$opt_W = 0; +$opt_C = 0; +$opt_f = ""; + +Getopt::Long::Configure('bundling'); +GetOptions( + "V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "f=s" => \$opt_f, "file" => \$opt_f, + "w=f" => \$opt_w, "warning-age=f" => \$opt_w, + "W=f" => \$opt_W, "warning-size=f" => \$opt_W, + "c=f" => \$opt_c, "critical-age=f" => \$opt_c, + "C=f" => \$opt_C, "critical-size=f" => \$opt_C); + +if ($opt_V) { + print_revision($PROGNAME, '1.4.15'); + exit $ERRORS{'OK'}; +} + +if ($opt_h) { + print_help(); + exit $ERRORS{'OK'}; +} + +$opt_f = shift unless ($opt_f); + +if (! $opt_f) { + print "FILE_AGE UNKNOWN: No file specified\n"; + exit $ERRORS{'UNKNOWN'}; +} + +# Check that file exists (can be directory or link) +unless (-e $opt_f) { + print "FILE_AGE CRITICAL: File not found - $opt_f\n"; + exit $ERRORS{'CRITICAL'}; +} + +$st = File::stat::stat($opt_f); +$age = time - $st->mtime; +$size = $st->size; + + +$result = 'OK'; + +if (($opt_c and $age > $opt_c) or ($opt_C and $size < $opt_C)) { + $result = 'CRITICAL'; +} +elsif (($opt_w and $age > $opt_w) or ($opt_W and $size < $opt_W)) { + $result = 'WARNING'; +} + +print "FILE_AGE $result: $opt_f is $age seconds old and $size bytes\n"; +exit $ERRORS{$result}; + +sub print_usage () { + print "Usage:\n"; + print " $PROGNAME [-w <secs>] [-c <secs>] [-W <size>] [-C <size>] -f <file>\n"; + print " $PROGNAME [-h | --help]\n"; + print " $PROGNAME [-V | --version]\n"; +} + +sub print_help () { + print_revision($PROGNAME, '1.4.15'); + print "Copyright (c) 2003 Steven Grimm\n\n"; + print_usage(); + print "\n"; + print " <secs> File must be no more than this many seconds old (default: warn 240 secs, crit 600)\n"; + print " <size> File must be at least this many bytes long (default: crit 0 bytes)\n"; + print "\n"; + support(); +} diff --git a/Monitoring/nagios/plugins/check_flexlm b/Monitoring/nagios/plugins/check_flexlm new file mode 100755 index 00000000..532785ef --- /dev/null +++ b/Monitoring/nagios/plugins/check_flexlm @@ -0,0 +1,244 @@ +#! /usr/bin/perl -w +# +# usage: +# check_flexlm.pl license_file +# +# Check available flexlm license managers. +# Use lmstat to check the status of the license server +# described by the license file given as argument. +# Check and interpret the output of lmstat +# and create returncodes and output. +# +# Contrary to the nagios concept, this script takes +# a file, not a hostname as an argument and returns +# the status of hosts and services described in that +# file. Use these hosts.cfg entries as an example +# +#host[anchor]=any host will do;some.address.com;;check-host-alive;3;120;24x7;1;1;1; +#service[anchor]=yodel;24x7;3;5;5;unix-admin;60;24x7;1;1;1;;check_flexlm!/opt/lic/licfiles/yodel_lic +#service[anchor]=yeehaw;24x7;3;5;5;unix-admin;60;24x7;1;1;1;;check_flexlm!/opt/lic/licfiles/yeehaw_lic +#command[check_flexlm]=/some/path/libexec/check_flexlm.pl $ARG1$ +# +# Notes: +# - you need the lmstat utility which comes with flexlm. +# - set the correct path in the variable $lmstat. +# +# initial version: 9-10-99 Ernst-Dieter Martin edmt@infineon.com +# +# License: GPL +# +# lmstat output patches from Steve Rigler/Cliff Rice 13-Apr-2002 +# srigler@marathonoil.com,cerice@marathonoil.com + + + +use strict; +use Getopt::Long; +use vars qw($opt_V $opt_h $opt_F $opt_t $verbose $PROGNAME); +use lib "/usr/lib/nagios/plugins"; +use utils qw(%ERRORS &print_revision &support &usage); + +$PROGNAME="check_flexlm"; + +sub print_help (); +sub print_usage (); + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +Getopt::Long::Configure('bundling'); +GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "v" => \$verbose, "verbose" => \$verbose, + "F=s" => \$opt_F, "filename=s" => \$opt_F, + "t=i" => \$opt_t, "timeout=i" => \$opt_t); + +if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); + exit $ERRORS{'OK'}; +} + +unless (defined $opt_t) { + $opt_t = $utils::TIMEOUT ; # default timeout +} + + +if ($opt_h) {print_help(); exit $ERRORS{'OK'};} + +unless (defined $opt_F) { + print "Missing license.dat file\n"; + print_usage(); + exit $ERRORS{'UNKNOWN'}; +} +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print "Timeout: No Answer from Client\n"; + exit $ERRORS{'UNKNOWN'}; +}; +alarm($opt_t); + +my $lmstat = $utils::PATH_TO_LMSTAT ; +unless (-x $lmstat ) { + print "Cannot find \"lmstat\"\n"; + exit $ERRORS{'UNKNOWN'}; +} + +($opt_F) || ($opt_F = shift) || usage("License file not specified\n"); +my $licfile = $1 if ($opt_F =~ /^(.*)$/); +($licfile) || usage("Invalid filename: $opt_F\n"); + +print "$licfile\n" if $verbose; + +if ( ! open(CMD,"$lmstat -c $licfile |") ) { + print "ERROR: Could not open \"$lmstat -c $licfile\" ($!)\n"; + exit exit $ERRORS{'UNKNOWN'}; +} + +my $serverup = 0; +my @upsrv; +my @downsrv; # list of servers up and down + +#my ($ls1,$ls2,$ls3,$lf1,$lf2,$lf3,$servers); + +# key off of the term "license server" and +# grab the status. Keep going until "Vendor" is found +# + +# +# Collect list of license servers by their status +# Vendor daemon status is ignored for the moment. + +while ( <CMD> ) { + next if (/^lmstat/); # ignore 1st line - copyright + next if (/^Flexible/); # ignore 2nd line - timestamp + (/^Vendor/) && last; # ignore Vendor daemon status + print $_ if $verbose; + + if ($_ =~ /license server /) { # matched 1 (of possibly 3) license server + s/^\s*//; #some servers start at col 1, other have whitespace + # strip staring whitespace if any + if ( $_ =~ /UP/) { + $_ =~ /^(.*):/ ; + push(@upsrv, $1); + print "up:$1:\n" if $verbose; + } else { + $_ =~ /^(.*):/; + push(@downsrv, $1); + print "down:$1:\n" if $verbose; + } + + } + + +# if ( /^License server status: [0-9]*@([-0-9a-zA-Z_]*),[0-9]*@([-0-9a-zA-Z_]*),[0-9]*@([-0-9a-zA-Z_]*)/ ) { +# $ls1 = $1; +# $ls2 = $2; +# $ls3 = $3; +# $lf1 = $lf2 = $lf3 = 0; +# $servers = 3; +# } elsif ( /^License server status: [0-9]*@([-0-9a-zA-Z_]*)/ ) { +# $ls1 = $1; +# $ls2 = $ls3 = ""; +# $lf1 = $lf2 = $lf3 = 0; +# $servers = 1; +# } elsif ( / *$ls1: license server UP/ ) { +# print "$ls1 UP, "; +# $lf1 = 1 +# } elsif ( / *$ls2: license server UP/ ) { +# print "$ls2 UP, "; +# $lf2 = 1 +# } elsif ( / *$ls3: license server UP/ ) { +# print "$ls3 UP, "; +# $lf3 = 1 +# } elsif ( / *([^:]*: UP .*)/ ) { +# print " license server for $1\n"; +# $serverup = 1; +# } + +} + +#if ( $serverup == 0 ) { +# print " license server not running\n"; +# exit 2; +#} + +close CMD; + +if ($verbose) { + print "License Servers running: ".scalar(@upsrv) ."\n"; + foreach my $upserver (@upsrv) { + print "$upserver\n"; + } + print "License servers not running: ".scalar(@downsrv)."\n"; + foreach my $downserver (@downsrv) { + print "$downserver\n"; + } +} + +# +# print list of servers which are up. +# +if (scalar(@upsrv) > 0) { + print "License Servers running:"; + foreach my $upserver (@upsrv) { + print "$upserver,"; + } +} +# +# Ditto for those which are down. +# +if (scalar(@downsrv) > 0) { + print "License servers NOT running:"; + foreach my $downserver (@downsrv) { + print "$downserver,"; + } +} + +# perfdata +print "\n|flexlm::up:".scalar(@upsrv).";down:".scalar(@downsrv)."\n"; + +exit $ERRORS{'OK'} if ( scalar(@downsrv) == 0 ); +exit $ERRORS{'WARNING'} if ( (scalar(@upsrv) > 0) && (scalar(@downsrv) > 0)); + +#exit $ERRORS{'OK'} if ( $servers == $lf1 + $lf2 + $lf3 ); +#exit $ERRORS{'WARNING'} if ( $servers == 3 && $lf1 + $lf2 + $lf3 == 2 ); +exit $ERRORS{'CRITICAL'}; + + +sub print_usage () { + print "Usage: + $PROGNAME -F <filename> [-v] [-t] [-V] [-h] + $PROGNAME --help + $PROGNAME --version +"; +} + +sub print_help () { + print_revision($PROGNAME,'1.4.15'); + print "Copyright (c) 2000 Ernst-Dieter Martin/Karl DeBisschop + +Check available flexlm license managers + +"; + print_usage(); + print " +-F, --filename=FILE + Name of license file (usually \"license.dat\") +-v, --verbose + Print some extra debugging information (not advised for normal operation) +-t, --timeout + Plugin time out in seconds (default = $utils::TIMEOUT ) +-V, --version + Show version and license information +-h, --help + Show this help screen + +Flexlm license managers usually run as a single server or three servers and a +quorum is needed. The plugin return OK if 1 (single) or 3 (triple) servers +are running, CRITICAL if 1(single) or 3 (triple) servers are down, and WARNING +if 1 or 2 of 3 servers are running\n +"; + support(); +} diff --git a/Monitoring/nagios/plugins/check_fping b/Monitoring/nagios/plugins/check_fping Binary files differnew file mode 100755 index 00000000..3d2b16f9 --- /dev/null +++ b/Monitoring/nagios/plugins/check_fping diff --git a/Monitoring/nagios/plugins/check_ftp b/Monitoring/nagios/plugins/check_ftp new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ftp @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_game b/Monitoring/nagios/plugins/check_game Binary files differnew file mode 100755 index 00000000..68c4bda4 --- /dev/null +++ b/Monitoring/nagios/plugins/check_game diff --git a/Monitoring/nagios/plugins/check_host b/Monitoring/nagios/plugins/check_host new file mode 120000 index 00000000..97878096 --- /dev/null +++ b/Monitoring/nagios/plugins/check_host @@ -0,0 +1 @@ +check_icmp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_hpjd b/Monitoring/nagios/plugins/check_hpjd Binary files differnew file mode 100755 index 00000000..75af60de --- /dev/null +++ b/Monitoring/nagios/plugins/check_hpjd diff --git a/Monitoring/nagios/plugins/check_http b/Monitoring/nagios/plugins/check_http Binary files differnew file mode 100755 index 00000000..2143dc6e --- /dev/null +++ b/Monitoring/nagios/plugins/check_http diff --git a/Monitoring/nagios/plugins/check_icmp b/Monitoring/nagios/plugins/check_icmp Binary files differnew file mode 100755 index 00000000..3e43c4d6 --- /dev/null +++ b/Monitoring/nagios/plugins/check_icmp diff --git a/Monitoring/nagios/plugins/check_ide_smart b/Monitoring/nagios/plugins/check_ide_smart Binary files differnew file mode 100755 index 00000000..e52727f4 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ide_smart diff --git a/Monitoring/nagios/plugins/check_ifoperstatus b/Monitoring/nagios/plugins/check_ifoperstatus new file mode 100755 index 00000000..23b25d5d --- /dev/null +++ b/Monitoring/nagios/plugins/check_ifoperstatus @@ -0,0 +1,472 @@ +#! /usr/bin/perl -w +# +# check_ifoperstatus.pl - nagios plugin +# +# Copyright (C) 2000 Christoph Kron, +# Modified 5/2002 to conform to updated Nagios Plugin Guidelines +# Added support for named interfaces per Valdimir Ivaschenko (S. Ghosh) +# Added SNMPv3 support (10/2003) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# Report bugs to: nagiosplug-help@lists.sourceforge.net +# +# 11.01.2000 Version 1.0 +# +# Patches from Guy Van Den Bergh to warn on ifadminstatus down interfaces +# instead of critical. +# +# Primary MIB reference - RFC 2863 + + +use POSIX; +use strict; +use lib "/usr/lib/nagios/plugins" ; +use utils qw($TIMEOUT %ERRORS &print_revision &support); + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('bundling'); + +my $PROGNAME = "check_ifoperstatus"; +sub print_help (); +sub usage ($); +sub print_usage (); +sub process_arguments (); + +my $timeout; +my $status; +my %ifOperStatus = ('1','up', + '2','down', + '3','testing', + '4','unknown', + '5','dormant', + '6','notPresent', + '7','lowerLayerDown'); # down due to the state of lower layer interface(s) + +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey = 0; +my $community = "public"; +my $maxmsgsize = 1472 ; # Net::SNMP default is 1472 +my ($seclevel, $authproto, $secname, $authpass, $privpass, $privproto, $auth, $priv, $context); +my $port = 161; +my @snmpoids; +my $sysUptime = '1.3.6.1.2.1.1.3.0'; +my $snmpIfDescr = '1.3.6.1.2.1.2.2.1.2'; +my $snmpIfType = '1.3.6.1.2.1.2.2.1.3'; +my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; +my $snmpIfOperStatus = '1.3.6.1.2.1.2.2.1.8'; +my $snmpIfName = '1.3.6.1.2.1.31.1.1.1.1'; +my $snmpIfLastChange = '1.3.6.1.2.1.2.2.1.9'; +my $snmpIfAlias = '1.3.6.1.2.1.31.1.1.1.18'; +my $snmpLocIfDescr = '1.3.6.1.4.1.9.2.2.1.1.28'; +my $hostname; +my $ifName; +my $session; +my $error; +my $response; +my $snmp_version = 1 ; +my $ifXTable; +my $opt_h ; +my $opt_V ; +my $ifdescr; +my $iftype; +my $key; +my $lastc; +my $dormantWarn; +my $adminWarn; +my $name; +my %session_opts; + +### Validate Arguments + +$status = process_arguments(); + + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; + +alarm($timeout); + +($session, $error) = Net::SNMP->session(%session_opts); + + +if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer\n"); + exit $ERRORS{$state}; +} + +## map ifdescr to ifindex - should look at being able to cache this value + +if (defined $ifdescr || defined $iftype) { + # escape "/" in ifdescr - very common in the Cisco world + if (defined $iftype) { + $status=fetch_ifindex($snmpIfType, $iftype); + } else { + $ifdescr =~ s/\//\\\//g; + $status=fetch_ifindex($snmpIfDescr, $ifdescr); # if using on device with large number of interfaces + # recommend use of SNMP v2 (get-bulk) + } + if ($status==0) { + $state = "UNKNOWN"; + printf "$state: could not retrive ifdescr/iftype snmpkey - $status-$snmpkey\n"; + $session->close; + exit $ERRORS{$state}; + } +} + + +## Main function + +$snmpIfAdminStatus = $snmpIfAdminStatus . "." . $snmpkey; +$snmpIfOperStatus = $snmpIfOperStatus . "." . $snmpkey; +$snmpIfDescr = $snmpIfDescr . "." . $snmpkey; +$snmpIfName = $snmpIfName . "." . $snmpkey ; +$snmpIfAlias = $snmpIfAlias . "." . $snmpkey ; + +push(@snmpoids,$snmpIfAdminStatus); +push(@snmpoids,$snmpIfOperStatus); +push(@snmpoids,$snmpIfDescr); +push(@snmpoids,$snmpIfName) if (defined $ifXTable) ; +push(@snmpoids,$snmpIfAlias) if (defined $ifXTable) ; + +if (!defined($response = $session->get_request(@snmpoids))) { + $answer=$session->error; + $session->close; + $state = 'WARNING'; + print ("$state: SNMP error: $answer\n"); + exit $ERRORS{$state}; +} + +$answer = sprintf("host '%s', %s(%s) is %s\n", + $hostname, + $response->{$snmpIfDescr}, + $snmpkey, + $ifOperStatus{$response->{$snmpIfOperStatus}} +); + + +## Check to see if ifName match is requested and it matches - exit if no match +## not the interface we want to monitor +if ( defined $ifName && not ($response->{$snmpIfName} eq $ifName) ) { + $state = 'UNKNOWN'; + $answer = "Interface name ($ifName) doesn't match snmp value ($response->{$snmpIfName}) (index $snmpkey)"; + print ("$state: $answer\n"); + exit $ERRORS{$state}; +} + +## define the interface name +if (defined $ifXTable) { + $name = $response->{$snmpIfName} ." - " .$response->{$snmpIfAlias} ; +}else{ + $name = $response->{$snmpIfDescr} ; +} + +## if AdminStatus is down - some one made a consious effort to change config +## +if ( not ($response->{$snmpIfAdminStatus} == 1) ) { + $answer = "Interface $name (index $snmpkey) is administratively down."; + if ( not defined $adminWarn or $adminWarn eq "w" ) { + $state = 'WARNING'; + } elsif ( $adminWarn eq "i" ) { + $state = 'OK'; + } elsif ( $adminWarn eq "c" ) { + $state = 'CRITICAL'; + } else { # If wrong value for -a, say warning + $state = 'WARNING'; + } +} +## Check operational status +elsif ( $response->{$snmpIfOperStatus} == 2 ) { + $state = 'CRITICAL'; + $answer = "Interface $name (index $snmpkey) is down."; +} elsif ( $response->{$snmpIfOperStatus} == 5 ) { + if (defined $dormantWarn ) { + if ($dormantWarn eq "w") { + $state = 'WARNING'; + $answer = "Interface $name (index $snmpkey) is dormant."; + }elsif($dormantWarn eq "c") { + $state = 'CRITICAL'; + $answer = "Interface $name (index $snmpkey) is dormant."; + }elsif($dormantWarn eq "i") { + $state = 'OK'; + $answer = "Interface $name (index $snmpkey) is dormant."; + } + }else{ + # dormant interface - but warning/critical/ignore not requested + $state = 'CRITICAL'; + $answer = "Interface $name (index $snmpkey) is dormant."; + } +} elsif ( $response->{$snmpIfOperStatus} == 6 ) { + $state = 'CRITICAL'; + $answer = "Interface $name (index $snmpkey) notPresent - possible hotswap in progress."; +} elsif ( $response->{$snmpIfOperStatus} == 7 ) { + $state = 'CRITICAL'; + $answer = "Interface $name (index $snmpkey) down due to lower layer being down."; +} elsif ( $response->{$snmpIfOperStatus} == 3 || $response->{$snmpIfOperStatus} == 4 ) { + $state = 'CRITICAL'; + $answer = "Interface $name (index $snmpkey) down (testing/unknown)."; +} else { + $state = 'OK'; + $answer = "Interface $name (index $snmpkey) is up."; +} + + + +print ("$state: $answer\n"); +exit $ERRORS{$state}; + + +### subroutines + +sub fetch_ifindex { + my $oid = shift; + my $lookup = shift; + + if (!defined ($response = $session->get_table($oid))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + printf ("$state: SNMP error with snmp version $snmp_version ($answer)\n"); + $session->close; + exit $ERRORS{$state}; + } + + foreach $key ( keys %{$response}) { + if ($response->{$key} =~ /^$lookup$/) { + $key =~ /.*\.(\d+)$/; + $snmpkey = $1; + #print "$lookup = $key / $snmpkey \n"; #debug + } + } + unless (defined $snmpkey) { + $session->close; + $state = 'CRITICAL'; + printf "$state: Could not match $ifdescr on $hostname\n"; + exit $ERRORS{$state}; + } + + return $snmpkey; +} + +sub usage($) { + print "$_[0]\n"; + print_usage(); + exit $ERRORS{"UNKNOWN"}; +} + +sub print_usage() { + printf "\n"; + printf "usage: \n"; + printf "check_ifoperstatus -k <IF_KEY> -H <HOSTNAME> [-C <community>]\n"; + printf "Copyright (C) 2000 Christoph Kron\n"; + printf "check_ifoperstatus.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; +} + +sub print_help() { + print_revision($PROGNAME, '1.4.15'); + print_usage(); + printf "check_ifoperstatus plugin for Nagios monitors operational \n"; + printf "status of a particular network interface on the target host\n"; + printf "\nUsage:\n"; + printf " -H (--hostname) Hostname to query - (required)\n"; + printf " -C (--community) SNMP read community (defaults to public,\n"; + printf " used with SNMP v1 and v2c\n"; + printf " -v (--snmp_version) 1 for SNMP v1 (default)\n"; + printf " 2 for SNMP v2c\n"; + printf " SNMP v2c will use get_bulk for less overhead\n"; + printf " if monitoring with -d\n"; + printf " -L (--seclevel) choice of \"noAuthNoPriv\", \"authNoPriv\", or \"authPriv\"\n"; + printf " -U (--secname) username for SNMPv3 context\n"; + printf " -c (--context) SNMPv3 context name (default is empty string)\n"; + printf " -A (--authpass) authentication password (cleartext ascii or localized key\n"; + printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; + printf " auth password and authEngineID\n"; + printf " -a (--authproto) Authentication protocol (MD5 or SHA1)\n"; + printf " -X (--privpass) privacy password (cleartext ascii or localized key\n"; + printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; + printf " privacy password and authEngineID\n"; + printf " -P (--privproto) privacy protocol (DES or AES; default: DES)\n"; + printf " -k (--key) SNMP IfIndex value\n"; + printf " -d (--descr) SNMP ifDescr value\n"; + printf " -T (--type) SNMP ifType integer value (see http://www.iana.org/assignments/ianaiftype-mib)\n"; + printf " -p (--port) SNMP port (default 161)\n"; + printf " -I (--ifmib) Agent supports IFMIB ifXTable. Do not use if\n"; + printf " you don't know what this is. \n"; + printf " -n (--name) the value should match the returned ifName\n"; + printf " (Implies the use of -I)\n"; + printf " -w (--warn =i|w|c) ignore|warn|crit if the interface is dormant (default critical)\n"; + printf " -D (--admin-down =i|w|c) same for administratively down interfaces (default warning)\n"; + printf " -M (--maxmsgsize) Max message size - usefull only for v1 or v2c\n"; + printf " -t (--timeout) seconds before the plugin times out (default=$TIMEOUT)\n"; + printf " -V (--version) Plugin version\n"; + printf " -h (--help) usage help \n\n"; + printf " -k or -d or -T must be specified\n\n"; + printf "Note: either -k or -d or -T must be specified and -d and -T are much more network \n"; + printf "intensive. Use it sparingly or not at all. -n is used to match against\n"; + printf "a much more descriptive ifName value in the IfXTable to verify that the\n"; + printf "snmpkey has not changed to some other network interface after a reboot.\n\n"; + +} + +sub process_arguments() { + $status = GetOptions( + "V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "v=i" => \$snmp_version, "snmp_version=i" => \$snmp_version, + "C=s" => \$community, "community=s" => \$community, + "L=s" => \$seclevel, "seclevel=s" => \$seclevel, + "a=s" => \$authproto, "authproto=s" => \$authproto, + "U=s" => \$secname, "secname=s" => \$secname, + "A=s" => \$authpass, "authpass=s" => \$authpass, + "X=s" => \$privpass, "privpass=s" => \$privpass, + "P=s" => \$privproto, "privproto=s" => \$privproto, + "c=s" => \$context, "context=s" => \$context, + "k=i" => \$snmpkey, "key=i",\$snmpkey, + "d=s" => \$ifdescr, "descr=s" => \$ifdescr, + "l=s" => \$lastc, "lastchange=s" => \$lastc, + "p=i" => \$port, "port=i" =>\$port, + "H=s" => \$hostname, "hostname=s" => \$hostname, + "I" => \$ifXTable, "ifmib" => \$ifXTable, + "n=s" => \$ifName, "name=s" => \$ifName, + "w=s" => \$dormantWarn, "warn=s" => \$dormantWarn, + "D=s" => \$adminWarn, "admin-down=s" => \$adminWarn, + "M=i" => \$maxmsgsize, "maxmsgsize=i" => \$maxmsgsize, + "t=i" => \$timeout, "timeout=i" => \$timeout, + "T=i" => \$iftype, "type=i" => \$iftype, + ); + + + if ($status == 0){ + print_help(); + exit $ERRORS{'OK'}; + } + + if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); + exit $ERRORS{'OK'}; + } + + if ($opt_h) { + print_help(); + exit $ERRORS{'OK'}; + } + + if (! utils::is_hostname($hostname)){ + usage("Hostname invalid or not given"); + } + + unless ($snmpkey > 0 || defined $ifdescr || defined $iftype){ + usage("Either a valid snmp key (-k) or a ifDescr (-d) must be provided"); + } + + if (defined $ifName) { + $ifXTable=1; + } + + if (defined $dormantWarn) { + unless ($dormantWarn =~ /^(w|c|i)$/ ) { + printf "Dormant alerts must be one of w|c|i \n"; + exit $ERRORS{'UNKNOWN'}; + } + } + + unless (defined $timeout) { + $timeout = $TIMEOUT; + } + + if ($snmp_version !~ /[123]/){ + $state='UNKNOWN'; + print ("$state: No support for SNMP v$snmp_version yet\n"); + exit $ERRORS{$state}; + } + + %session_opts = ( + -hostname => $hostname, + -port => $port, + -version => $snmp_version, + -maxmsgsize => $maxmsgsize + ); + + $session_opts{'-community'} = $community if (defined $community && $snmp_version =~ /[12]/); + + if ($snmp_version =~ /3/ ) { + # Must define a security level even though default is noAuthNoPriv + # v3 requires a security username + if (defined $seclevel && defined $secname) { + $session_opts{'-username'} = $secname; + + # Must define a security level even though defualt is noAuthNoPriv + unless ( grep /^$seclevel$/, qw(noAuthNoPriv authNoPriv authPriv) ) { + usage("Must define a valid security level even though default is noAuthNoPriv"); + } + + # Authentication wanted + if ( $seclevel eq 'authNoPriv' || $seclevel eq 'authPriv' ) { + if (defined $authproto && $authproto ne 'MD5' && $authproto ne 'SHA1') { + usage("Auth protocol can be either MD5 or SHA1"); + } + $session_opts{'-authprotocol'} = $authproto if(defined $authproto); + + if ( !defined $authpass) { + usage("Auth password/key is not defined"); + }else{ + if ($authpass =~ /^0x/ ) { + $session_opts{'-authkey'} = $authpass ; + }else{ + $session_opts{'-authpassword'} = $authpass ; + } + } + } + + # Privacy (DES encryption) wanted + if ($seclevel eq 'authPriv' ) { + if (! defined $privpass) { + usage("Privacy passphrase/key is not defined"); + }else{ + if ($privpass =~ /^0x/){ + $session_opts{'-privkey'} = $privpass; + }else{ + $session_opts{'-privpassword'} = $privpass; + } + } + + $session_opts{'-privprotocol'} = $privproto if(defined $privproto); + } + + # Context name defined or default + unless ( defined $context) { + $context = ""; + } + + }else { + usage("Security level or name is not defined"); + } + } # end snmpv3 + + +} +## End validation + diff --git a/Monitoring/nagios/plugins/check_ifstatus b/Monitoring/nagios/plugins/check_ifstatus new file mode 100755 index 00000000..b977675e --- /dev/null +++ b/Monitoring/nagios/plugins/check_ifstatus @@ -0,0 +1,425 @@ +#! /usr/bin/perl -w +# +# check_ifstatus.pl - nagios plugin +# +# +# Copyright (C) 2000 Christoph Kron +# Modified 5/2002 to conform to updated Nagios Plugin Guidelines (S. Ghosh) +# Added -x option (4/2003) +# Added -u option (4/2003) +# Added -M option (10/2003) +# Added SNMPv3 support (10/2003) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# Report bugs to: ck@zet.net, nagiosplug-help@lists.sf.net +# +# 11.01.2000 Version 1.0 +# + +use POSIX; +use strict; +use lib "/usr/lib/nagios/plugins" ; +use utils qw($TIMEOUT %ERRORS &print_revision &support); + +use Net::SNMP; +use Getopt::Long; +Getopt::Long::Configure('bundling'); + +my $PROGNAME = "check_ifstatus"; + +sub print_help (); +sub usage ($); +sub print_usage (); +sub process_arguments (); + + +my $status; +my %ifOperStatus = ('1','up', + '2','down', + '3','testing', + '4','unknown', + '5','dormant', + '6','notPresent', + '7','lowerLayerDown'); # down due to the state of lower layer interface(s)); + +my $timeout ; +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey=0; +my $snmpoid=0; +my $key=0; +my $community = "public"; +my $maxmsgsize = 1472 ; # Net::SNMP default is 1472 +my ($seclevel, $authproto, $secname, $authpass, $privpass, $privproto, $auth, $priv, $context); +my $port = 161; +my @snmpoids; +my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; +my $snmpIfDescr = '1.3.6.1.2.1.2.2.1.2'; +my $snmpIfOperStatus = '1.3.6.1.2.1.2.2.1.8'; +my $snmpIfName = '1.3.6.1.2.1.31.1.1.1.1'; +my $snmpIfAlias = '1.3.6.1.2.1.31.1.1.1.18'; +my $snmpLocIfDescr = '1.3.6.1.4.1.9.2.2.1.1.28'; +my $snmpIfType = '1.3.6.1.2.1.2.2.1.3'; +my $hostname; +my $session; +my $error; +my $response; +my %ifStatus; +my $ifup =0 ; +my $ifdown =0; +my $ifdormant = 0; +my $ifexclude = 0 ; +my $ifunused = 0; +my $ifmessage = ""; +my $snmp_version = 1; +my $ifXTable; +my $opt_h ; +my $opt_V ; +my $opt_u; +my $opt_x ; +my %excluded ; +my @unused_ports ; +my %session_opts; + + + + + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm timeout)\n"); + exit $ERRORS{"UNKNOWN"}; +}; + + +#Option checking +$status = process_arguments(); + +if ($status != 0) +{ + print_help() ; + exit $ERRORS{'OK'}; +} + + +alarm($timeout); +($session, $error) = Net::SNMP->session(%session_opts); + +if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer\n"); + exit $ERRORS{$state}; +} + + +push(@snmpoids,$snmpIfOperStatus); +push(@snmpoids,$snmpIfAdminStatus); +push(@snmpoids,$snmpIfDescr); +push(@snmpoids,$snmpIfType); +push(@snmpoids,$snmpIfName) if ( defined $ifXTable); +push(@snmpoids,$snmpIfAlias) if ( defined $ifXTable); + + + + +foreach $snmpoid (@snmpoids) { + + if (!defined($response = $session->get_table($snmpoid))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + if ( ( $snmpoid =~ $snmpIfName ) && defined $ifXTable ) { + print ("$state: Device does not support ifTable - try without -I option\n"); + }else{ + print ("$state: $answer for $snmpoid with snmp version $snmp_version\n"); + } + exit $ERRORS{$state}; + } + + foreach $snmpkey (keys %{$response}) { + $snmpkey =~ /.*\.(\d+)$/; + $key = $1; + $ifStatus{$key}{$snmpoid} = $response->{$snmpkey}; + } +} + + +$session->close; + +alarm(0); + +foreach $key (keys %ifStatus) { + + # skip unused interfaces + if (!defined($ifStatus{$key}{'notInUse'})) { + # check only if interface is administratively up + if ($ifStatus{$key}{$snmpIfAdminStatus} == 1 ) { + + # check only if interface type is not listed in %excluded + if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) { + if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ;} + if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) { + $ifdown++ ; + if (defined $ifXTable) { + $ifmessage .= sprintf("%s: down -> %s<BR>", + $ifStatus{$key}{$snmpIfName}, + $ifStatus{$key}{$snmpIfAlias}); + }else{ + $ifmessage .= sprintf("%s: down <BR>", + $ifStatus{$key}{$snmpIfDescr}); + } + } + if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;} + }else{ + $ifexclude++; + } + + } + }else{ + $ifunused++; + } +} + + if ($ifdown > 0) { + $state = 'CRITICAL'; + $answer = sprintf("host '%s', interfaces up: %d, down: %d, dormant: %d, excluded: %d, unused: %d<BR>", + $hostname, + $ifup, + $ifdown, + $ifdormant, + $ifexclude, + $ifunused); + $answer = $answer . $ifmessage . "\n"; + } + else { + $state = 'OK'; + $answer = sprintf("host '%s', interfaces up: %d, down: %d, dormant: %d, excluded: %d, unused: %d", + $hostname, + $ifup, + $ifdown, + $ifdormant, + $ifexclude, + $ifunused); + } +my $perfdata = sprintf("up=%d,down=%d,dormant=%d,excluded=%d,unused=%d",$ifup,$ifdown,$ifdormant,$ifexclude,$ifunused); +print ("$state: $answer |$perfdata\n"); +exit $ERRORS{$state}; + +sub usage($) { + print "$_[0]\n"; + print_usage(); + exit $ERRORS{"UNKNOWN"}; +} + +sub print_usage() { + printf "\n"; + printf "usage: \n"; + printf "check_ifstatus -C <READCOMMUNITY> -p <PORT> -H <HOSTNAME>\n"; + printf "Copyright (C) 2000 Christoph Kron\n"; + printf "Updates 5/2002 Subhendu Ghosh\n"; + support(); + printf "\n\n"; +} + +sub print_help() { + print_revision($PROGNAME, '1.4.15'); + print_usage(); + printf "check_ifstatus plugin for Nagios monitors operational \n"; + printf "status of each network interface on the target host\n"; + printf "\nUsage:\n"; + printf " -H (--hostname) Hostname to query - (required)\n"; + printf " -C (--community) SNMP read community (defaults to public,\n"; + printf " used with SNMP v1 and v2c\n"; + printf " -v (--snmp_version) 1 for SNMP v1 (default)\n"; + printf " 2 for SNMP v2c\n"; + printf " SNMP v2c will use get_bulk for less overhead\n"; + printf " 3 for SNMPv3 (requires -U option)"; + printf " -p (--port) SNMP port (default 161)\n"; + printf " -I (--ifmib) Agent supports IFMIB ifXTable. For Cisco - this will provide\n"; + printf " the descriptive name. Do not use if you don't know what this is. \n"; + printf " -x (--exclude) A comma separated list of ifType values that should be excluded \n"; + printf " from the report (default for an empty list is PPP(23).\n"; + printf " -u (--unused_ports) A comma separated list of ifIndex values that should be excluded \n"; + printf " from the report (default is an empty exclusion list).\n"; + printf " See the IANAifType-MIB for a list of interface types.\n"; + printf " -L (--seclevel) choice of \"noAuthNoPriv\", \"authNoPriv\", or \"authPriv\"\n"; + printf " -U (--secname) username for SNMPv3 context\n"; + printf " -c (--context) SNMPv3 context name (default is empty string)\n"; + printf " -A (--authpass) authentication password (cleartext ascii or localized key\n"; + printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; + printf " auth password and authEngineID\n"; + printf " -a (--authproto) Authentication protocol (MD5 or SHA1)\n"; + printf " -X (--privpass) privacy password (cleartext ascii or localized key\n"; + printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; + printf " privacy password and authEngineID\n"; + printf " -P (--privproto) privacy protocol (DES or AES; default: DES)\n"; + printf " -M (--maxmsgsize) Max message size - usefull only for v1 or v2c\n"; + printf " -t (--timeout) seconds before the plugin times out (default=$TIMEOUT)\n"; + printf " -V (--version) Plugin version\n"; + printf " -h (--help) usage help \n\n"; + print_revision($PROGNAME, '1.4.15'); + +} + +sub process_arguments() { + $status = GetOptions( + "V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "v=s" => \$snmp_version, "snmp_version=s" => \$snmp_version, + "C=s" => \$community,"community=s" => \$community, + "L=s" => \$seclevel, "seclevel=s" => \$seclevel, + "a=s" => \$authproto, "authproto=s" => \$authproto, + "U=s" => \$secname, "secname=s" => \$secname, + "A=s" => \$authpass, "authpass=s" => \$authpass, + "X=s" => \$privpass, "privpass=s" => \$privpass, + "P=s" => \$privproto, "privproto=s" => \$privproto, + "c=s" => \$context, "context=s" => \$context, + "p=i" =>\$port, "port=i" => \$port, + "H=s" => \$hostname, "hostname=s" => \$hostname, + "I" => \$ifXTable, "ifmib" => \$ifXTable, + "x:s" => \$opt_x, "exclude:s" => \$opt_x, + "u=s" => \$opt_u, "unused_ports=s" => \$opt_u, + "M=i" => \$maxmsgsize, "maxmsgsize=i" => \$maxmsgsize, + "t=i" => \$timeout, "timeout=i" => \$timeout, + ); + + if ($status == 0){ + print_help(); + exit $ERRORS{'OK'}; + } + + if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); + exit $ERRORS{'OK'}; + } + + if ($opt_h) { + print_help(); + exit $ERRORS{'OK'}; + } + + unless (defined $timeout) { + $timeout = $TIMEOUT; + } + + # Net::SNMP wants an integer + $snmp_version = 2 if $snmp_version eq "2c"; + + if ($snmp_version !~ /^[123]$/){ + $state='UNKNOWN'; + print ("$state: No support for SNMP v$snmp_version yet\n"); + exit $ERRORS{$state}; + } + + %session_opts = ( + -hostname => $hostname, + -port => $port, + -version => $snmp_version, + -maxmsgsize => $maxmsgsize + ); + + $session_opts{'-community'} = $community if (defined $community && $snmp_version =~ /[12]/); + + if ($snmp_version =~ /3/ ) { + # Must define a security level even though default is noAuthNoPriv + # v3 requires a security username + if (defined $seclevel && defined $secname) { + $session_opts{'-username'} = $secname; + + # Must define a security level even though defualt is noAuthNoPriv + unless ( grep /^$seclevel$/, qw(noAuthNoPriv authNoPriv authPriv) ) { + usage("Must define a valid security level even though default is noAuthNoPriv"); + } + + # Authentication wanted + if ( $seclevel eq 'authNoPriv' || $seclevel eq 'authPriv' ) { + if (defined $authproto && $authproto ne 'MD5' && $authproto ne 'SHA1') { + usage("Auth protocol can be either MD5 or SHA1"); + } + $session_opts{'-authprotocol'} = $authproto if(defined $authproto); + + if ( !defined $authpass) { + usage("Auth password/key is not defined"); + }else{ + if ($authpass =~ /^0x/ ) { + $session_opts{'-authkey'} = $authpass ; + }else{ + $session_opts{'-authpassword'} = $authpass ; + } + } + } + + # Privacy (DES encryption) wanted + if ($seclevel eq 'authPriv' ) { + if (! defined $privpass) { + usage("Privacy passphrase/key is not defined"); + }else{ + if ($privpass =~ /^0x/){ + $session_opts{'-privkey'} = $privpass; + }else{ + $session_opts{'-privpassword'} = $privpass; + } + } + + $session_opts{'-privprotocol'} = $privproto if(defined $privproto); + } + + # Context name defined or default + unless ( defined $context) { + $context = ""; + } + + }else { + usage("Security level or name is not defined"); + } + } # end snmpv3 + + # Excluded interfaces types (ifType) (backup interfaces, dial-on demand interfaces, PPP interfaces + if (defined $opt_x) { + my @x = split(/,/, $opt_x); + if ( @x) { + foreach $key (@x){ + $excluded{$key} = 1; + } + }else{ + $excluded{23} = 1; # default PPP(23) if empty list - note (AIX seems to think PPP is 22 according to a post) + } + } + + # Excluded interface ports (ifIndex) - management reasons + if ($opt_u) { + @unused_ports = split(/,/,$opt_u); + foreach $key (@unused_ports) { + $ifStatus{$key}{'notInUse'}++ ; + } + } + + if (! utils::is_hostname($hostname)){ + usage("Hostname invalid or not given"); + exit $ERRORS{"UNKNOWN"}; + } + + + if ($snmp_version !~ /[123]/) { + $state='UNKNOWN'; + print ("$state: No support for SNMP v$snmp_version yet\n"); + exit $ERRORS{$state}; + } + +return $ERRORS{"OK"}; +} diff --git a/Monitoring/nagios/plugins/check_imap b/Monitoring/nagios/plugins/check_imap new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_imap @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_ircd b/Monitoring/nagios/plugins/check_ircd new file mode 100755 index 00000000..21d367ed --- /dev/null +++ b/Monitoring/nagios/plugins/check_ircd @@ -0,0 +1,239 @@ +#! /usr/bin/perl -wT + +# ----------------------------------------------------------------------------- +# File Name: check_ircd.pl +# +# Author: Richard Mayhew - South Africa +# +# Date: 1999/09/20 +# +# +# Description: This script will check to see if an IRCD is running +# about how many users it has +# +# Email: netsaint@splash.co.za +# +# ----------------------------------------------------------------------------- +# Copyright 1999 (c) Richard Mayhew +# +# Credits go to Ethan Galstad for coding Nagios +# +# If any changes are made to this script, please mail me a copy of the +# changes :) +# +# Some code taken from Charlie Cook (check_disk.pl) +# +# License GPL +# +# ----------------------------------------------------------------------------- +# Date Author Reason +# ---- ------ ------ +# +# 1999/09/20 RM Creation +# +# 1999/09/20 TP Changed script to use strict, more secure by +# specifying $ENV variables. The bind command is +# still insecure through. Did most of my work +# with perl -wT and 'use strict' +# +# test using check_ircd.pl (irc-2.mit.edu|irc.erols.com|irc.core.com) +# 2002/05/02 SG Fixed for Embedded Perl +# + +# ----------------------------------------------------------------[ Require ]-- + +require 5.004; + +# -------------------------------------------------------------------[ Uses ]-- + +use Socket; +use strict; +use Getopt::Long; +use vars qw($opt_V $opt_h $opt_t $opt_p $opt_H $opt_w $opt_c $verbose); +use vars qw($PROGNAME); +use lib "/usr/lib/nagios/plugins"; +use utils qw($TIMEOUT %ERRORS &print_revision &support &usage); + +# ----------------------------------------------------[ Function Prototypes ]-- + +sub print_help (); +sub print_usage (); +sub connection ($$$$); +sub bindRemote ($$); + +# -------------------------------------------------------------[ Enviroment ]-- + +$ENV{PATH} = ""; +$ENV{ENV} = ""; +$ENV{BASH_ENV} = ""; + +# -----------------------------------------------------------------[ Global ]-- + +$PROGNAME = "check_ircd"; +my $NICK="ircd$$"; +my $USER_INFO="monitor localhost localhost : "; + +# -------------------------------------------------------------[ connection ]-- +sub connection ($$$$) +{ + my ($in_remotehost,$in_users,$in_warn,$in_crit) = @_; + my $state; + my $answer; + + print "connection(debug): users = $in_users\n" if $verbose; + $in_users =~ s/\ //g; + + if ($in_users >= 0) { + + if ($in_users > $in_crit) { + $state = "CRITICAL"; + $answer = "Critical Number Of Clients Connected : $in_users (Limit = $in_crit)\n"; + + } elsif ($in_users > $in_warn) { + $state = "WARNING"; + $answer = "Warning Number Of Clients Connected : $in_users (Limit = $in_warn)\n"; + + } else { + $state = "OK"; + $answer = "IRCD ok - Current Local Users: $in_users\n"; + } + + } else { + $state = "UNKNOWN"; + $answer = "Server $in_remotehost has less than 0 users! Something is Really WRONG!\n"; + } + + print ClientSocket "quit\n"; + print $answer; + exit $ERRORS{$state}; +} + +# ------------------------------------------------------------[ print_usage ]-- + +sub print_usage () { + print "Usage: $PROGNAME -H <host> [-w <warn>] [-c <crit>] [-p <port>]\n"; +} + +# -------------------------------------------------------------[ print_help ]-- + +sub print_help () +{ + print_revision($PROGNAME,'1.4.15'); + print "Copyright (c) 2000 Richard Mayhew/Karl DeBisschop + +Perl Check IRCD plugin for Nagios + +"; + print_usage(); + print " +-H, --hostname=HOST + Name or IP address of host to check +-w, --warning=INTEGER + Number of connected users which generates a warning state (Default: 50) +-c, --critical=INTEGER + Number of connected users which generates a critical state (Default: 100) +-p, --port=INTEGER + Port that the ircd daemon is running on <host> (Default: 6667) +-v, --verbose + Print extra debugging information +"; +} + +# -------------------------------------------------------------[ bindRemote ]-- + +sub bindRemote ($$) +{ + my ($in_remotehost, $in_remoteport) = @_; + my $proto = getprotobyname('tcp'); + my $sockaddr; + my $that; + my ($name, $aliases,$type,$len,$thataddr) = gethostbyname($in_remotehost); + + if (!socket(ClientSocket,AF_INET, SOCK_STREAM, $proto)) { + print "IRCD UNKNOWN: Could not start socket ($!)\n"; + exit $ERRORS{"UNKNOWN"}; + } + $sockaddr = 'S n a4 x8'; + $that = pack($sockaddr, AF_INET, $in_remoteport, $thataddr); + if (!connect(ClientSocket, $that)) { + print "IRCD UNKNOWN: Could not connect socket ($!)\n"; + exit $ERRORS{"UNKNOWN"}; + } + select(ClientSocket); $| = 1; select(STDOUT); + return \*ClientSocket; +} + +# ===================================================================[ MAIN ]== + +MAIN: +{ + my $hostname; + + Getopt::Long::Configure('bundling'); + GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "v" => \$verbose,"verbose" => \$verbose, + "t=i" => \$opt_t, "timeout=i" => \$opt_t, + "w=i" => \$opt_w, "warning=i" => \$opt_w, + "c=i" => \$opt_c, "critical=i" => \$opt_c, + "p=i" => \$opt_p, "port=i" => \$opt_p, + "H=s" => \$opt_H, "hostname=s" => \$opt_H); + + if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); + exit $ERRORS{'OK'}; + } + + if ($opt_h) {print_help(); exit $ERRORS{'OK'};} + + ($opt_H) || ($opt_H = shift @ARGV) || usage("Host name/address not specified\n"); + my $remotehost = $1 if ($opt_H =~ /([-.A-Za-z0-9]+)/); + ($remotehost) || usage("Invalid host: $opt_H\n"); + + ($opt_w) || ($opt_w = shift @ARGV) || ($opt_w = 50); + my $warn = $1 if ($opt_w =~ /^([0-9]+)$/); + ($warn) || usage("Invalid warning threshold: $opt_w\n"); + + ($opt_c) || ($opt_c = shift @ARGV) || ($opt_c = 100); + my $crit = $1 if ($opt_c =~ /^([0-9]+)$/); + ($crit) || usage("Invalid critical threshold: $opt_c\n"); + + ($opt_p) || ($opt_p = shift @ARGV) || ($opt_p = 6667); + my $remoteport = $1 if ($opt_p =~ /^([0-9]+)$/); + ($remoteport) || usage("Invalid port: $opt_p\n"); + + if ($opt_t && $opt_t =~ /^([0-9]+)$/) { $TIMEOUT = $1; } + + # Just in case of problems, let's not hang Nagios + $SIG{'ALRM'} = sub { + print "Somthing is Taking a Long Time, Increase Your TIMEOUT (Currently Set At $TIMEOUT Seconds)\n"; + exit $ERRORS{"UNKNOWN"}; + }; + + alarm($TIMEOUT); + + my ($name, $alias, $proto) = getprotobyname('tcp'); + + print "MAIN(debug): binding to remote host: $remotehost -> $remoteport\n" if $verbose; + my $ClientSocket = &bindRemote($remotehost,$remoteport); + + print ClientSocket "NICK $NICK\nUSER $USER_INFO\n"; + + while (<ClientSocket>) { + print "MAIN(debug): default var = $_\n" if $verbose; + + # DALnet,LagNet,UnderNet etc. Require this! + # Replies with a PONG when presented with a PING query. + # If a server doesn't require it, it will be ignored. + + if (m/^PING (.*)/) {print ClientSocket "PONG $1\n";} + + alarm(0); + + # Look for pattern in IRCD Output to gather Client Connections total. + connection($remotehost,$1,$warn,$crit) if (m/:I have\s+(\d+)/); + } + print "IRCD UNKNOWN: Unknown error - maybe could not authenticate\n"; + exit $ERRORS{"UNKNOWN"}; +} diff --git a/Monitoring/nagios/plugins/check_jabber b/Monitoring/nagios/plugins/check_jabber new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_jabber @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_ldap b/Monitoring/nagios/plugins/check_ldap Binary files differnew file mode 100755 index 00000000..ea4e3346 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ldap diff --git a/Monitoring/nagios/plugins/check_ldaps b/Monitoring/nagios/plugins/check_ldaps new file mode 120000 index 00000000..928c9e7c --- /dev/null +++ b/Monitoring/nagios/plugins/check_ldaps @@ -0,0 +1 @@ +check_ldap
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_linux_raid b/Monitoring/nagios/plugins/check_linux_raid new file mode 100755 index 00000000..ab982cd6 --- /dev/null +++ b/Monitoring/nagios/plugins/check_linux_raid @@ -0,0 +1,115 @@ +#!/usr/bin/perl -w + +# Copyright (c) 2002 ISOMEDIA, Inc. +# originally written by Steve Milton +# later updates by sean finney <seanius@seanius.net> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Usage: check_raid [raid-name] +# Example: check_raid md0 +# WARNING md0 status=[UUU_U], recovery=46.4%, finish=123.0min + +use strict; +use lib "/usr/lib/nagios/plugins"; +use utils qw(%ERRORS); + +# die with an error if we're not on Linux +if ($^O ne 'linux') { + print "This plugin only applicable on Linux.\n"; + exit $ERRORS{'UNKNOWN'}; +} + +sub max_state($$){ + my ($a, $b) = @_; + if ($a eq "CRITICAL" || $b eq "CRITICAL") { return "CRITICAL"; } + elsif ($a eq "WARNING" || $b eq "WARNING") { return "WARNING"; } + elsif ($a eq "OK" || $b eq "OK") { return "OK"; } + elsif ($a eq "UNKNOWN" || $b eq "UNKNOWN") { return "UNKNOWN"; } + elsif ($a eq "DEPENDENT" || $b eq "DEPENDENT") { return "DEPENDENT"; } + return "UNKNOWN"; +} + +my $nextdev; +if(defined $ARGV[0]) { $nextdev = shift; } +else { $nextdev = "md[0-9]+"; } + +my $code = "UNKNOWN"; +my $msg = ""; +my %status; +my %recovery; +my %finish; +my %active; +my %devices; + +while(defined $nextdev){ + open (MDSTAT, "< /proc/mdstat") or die "Failed to open /proc/mdstat"; + my $device = undef; + while(<MDSTAT>) { + if (defined $device) { + if (/(\[[_U]+\])/) { + $status{$device} = $1; + } elsif (/recovery = (.*?)\s/) { + $recovery{$device} = $1; + ($finish{$device}) = /finish=(.*?min)/; + $device=undef; + } elsif (/^\s*$/) { + $device=undef; + } + } elsif (/^($nextdev)\s*:/) { + $device=$1; + $devices{$device}=$device; + if (/\sactive/) { + $status{$device} = ''; # Shall be filled later if available + $active{$device} = 1; + } + } + } + $nextdev = shift; +} + +foreach my $k (sort keys %devices){ + if (!exists($status{$k})) { + $msg .= sprintf " %s inactive with no status information.", + $devices{$k}; + $code = max_state($code, "CRITICAL"); + } elsif ($status{$k} =~ /_/) { + if (defined $recovery{$k}) { + $msg .= sprintf " %s status=%s, recovery=%s, finish=%s.", + $devices{$k}, $status{$k}, $recovery{$k}, $finish{$k}; + $code = max_state($code, "WARNING"); + } else { + $msg .= sprintf " %s status=%s.", $devices{$k}, $status{$k}; + $code = max_state($code, "CRITICAL"); + } + } elsif ($status{$k} =~ /U+/) { + $msg .= sprintf " %s status=%s.", $devices{$k}, $status{$k}; + $code = max_state($code, "OK"); + } else { + if ($active{$k}) { + $msg .= sprintf " %s active with no status information.", + $devices{$k}; + $code = max_state($code, "OK"); + } else { + # This should't run anymore, but is left as a catch-all + $msg .= sprintf " %s does not exist.\n", $devices{$k}; + $code = max_state($code, "CRITICAL"); + } + } +} + +print $code, $msg, "\n"; +exit ($ERRORS{$code}); + diff --git a/Monitoring/nagios/plugins/check_load b/Monitoring/nagios/plugins/check_load Binary files differnew file mode 100755 index 00000000..8501ea65 --- /dev/null +++ b/Monitoring/nagios/plugins/check_load diff --git a/Monitoring/nagios/plugins/check_log b/Monitoring/nagios/plugins/check_log new file mode 100755 index 00000000..4b60b5de --- /dev/null +++ b/Monitoring/nagios/plugins/check_log @@ -0,0 +1,219 @@ +#! /bin/bash +# +# Log file pattern detector plugin for Nagios +# Written by Ethan Galstad (nagios@nagios.org) +# Last Modified: 07-31-1999 +# +# Usage: ./check_log <log_file> <old_log_file> <pattern> +# +# Description: +# +# This plugin will scan a log file (specified by the <log_file> option) +# for a specific pattern (specified by the <pattern> option). Successive +# calls to the plugin script will only report *new* pattern matches in the +# log file, since an copy of the log file from the previous run is saved +# to <old_log_file>. +# +# Output: +# +# On the first run of the plugin, it will return an OK state with a message +# of "Log check data initialized". On successive runs, it will return an OK +# state if *no* pattern matches have been found in the *difference* between the +# log file and the older copy of the log file. If the plugin detects any +# pattern matches in the log diff, it will return a CRITICAL state and print +# out a message is the following format: "(x) last_match", where "x" is the +# total number of pattern matches found in the file and "last_match" is the +# last entry in the log file which matches the pattern. +# +# Notes: +# +# If you use this plugin make sure to keep the following in mind: +# +# 1. The "max_attempts" value for the service should be 1, as this +# will prevent Nagios from retrying the service check (the +# next time the check is run it will not produce the same results). +# +# 2. The "notify_recovery" value for the service should be 0, so that +# Nagios does not notify you of "recoveries" for the check. Since +# pattern matches in the log file will only be reported once and not +# the next time, there will always be "recoveries" for the service, even +# though recoveries really don't apply to this type of check. +# +# 3. You *must* supply a different <old_file_log> for each service that +# you define to use this plugin script - even if the different services +# check the same <log_file> for pattern matches. This is necessary +# because of the way the script operates. +# +# Examples: +# +# Check for login failures in the syslog... +# +# check_log /var/log/messages ./check_log.badlogins.old "LOGIN FAILURE" +# +# Check for port scan alerts generated by Psionic's PortSentry software... +# +# check_log /var/log/message ./check_log.portscan.old "attackalert" +# + +# Paths to commands used in this script. These +# may have to be modified to match your system setup. +# TV: removed PATH restriction. Need to think more about what this means overall +#PATH="" + +ECHO="/bin/echo" +GREP="/bin/egrep" +DIFF="/usr/bin/diff" +TAIL="/usr/bin/tail" +CAT="/bin/cat" +RM="/bin/rm" +CHMOD="/bin/chmod" +TOUCH="/bin/touch" + +PROGNAME=`/usr/bin/basename $0` +PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'` +REVISION="1.4.15" + +. $PROGPATH/utils.sh + +print_usage() { + echo "Usage: $PROGNAME -F logfile -O oldlog -q query" + echo "Usage: $PROGNAME --help" + echo "Usage: $PROGNAME --version" +} + +print_help() { + print_revision $PROGNAME $REVISION + echo "" + print_usage + echo "" + echo "Log file pattern detector plugin for Nagios" + echo "" + support +} + +# Make sure the correct number of command line +# arguments have been supplied + +if [ $# -lt 1 ]; then + print_usage + exit $STATE_UNKNOWN +fi + +# Grab the command line arguments + +#logfile=$1 +#oldlog=$2 +#query=$3 +exitstatus=$STATE_WARNING #default +while test -n "$1"; do + case "$1" in + --help) + print_help + exit $STATE_OK + ;; + -h) + print_help + exit $STATE_OK + ;; + --version) + print_revision $PROGNAME $REVISION + exit $STATE_OK + ;; + -V) + print_revision $PROGNAME $REVISION + exit $STATE_OK + ;; + --filename) + logfile=$2 + shift + ;; + -F) + logfile=$2 + shift + ;; + --oldlog) + oldlog=$2 + shift + ;; + -O) + oldlog=$2 + shift + ;; + --query) + query=$2 + shift + ;; + -q) + query=$2 + shift + ;; + -x) + exitstatus=$2 + shift + ;; + --exitstatus) + exitstatus=$2 + shift + ;; + *) + echo "Unknown argument: $1" + print_usage + exit $STATE_UNKNOWN + ;; + esac + shift +done + +# If the source log file doesn't exist, exit + +if [ ! -e $logfile ]; then + $ECHO "Log check error: Log file $logfile does not exist!\n" + exit $STATE_UNKNOWN +elif [ ! -r $logfile ] ; then + $ECHO "Log check error: Log file $logfile is not readable!\n" + exit $STATE_UNKNOWN +fi + +# If the old log file doesn't exist, this must be the first time +# we're running this test, so copy the original log file over to +# the old diff file and exit + +if [ ! -e $oldlog ]; then + $CAT $logfile > $oldlog + $ECHO "Log check data initialized...\n" + exit $STATE_OK +fi + +# The old log file exists, so compare it to the original log now + +# The temporary file that the script should use while +# processing the log file. +if [ -x /bin/mktemp ]; then + tempdiff=`/bin/mktemp /tmp/check_log.XXXXXXXXXX` +else + tempdiff=`/bin/date '+%H%M%S'` + tempdiff="/tmp/check_log.${tempdiff}" + $TOUCH $tempdiff + $CHMOD 600 $tempdiff +fi + +$DIFF $logfile $oldlog | $GREP -v "^>" > $tempdiff + +# Count the number of matching log entries we have +count=`$GREP -c "$query" $tempdiff` + +# Get the last matching entry in the diff file +lastentry=`$GREP "$query" $tempdiff | $TAIL -1` + +$RM -f $tempdiff +$CAT $logfile > $oldlog + +if [ "$count" = "0" ]; then # no matches, exit with no error + $ECHO "Log check ok - 0 pattern matches found\n" + exitstatus=$STATE_OK +else # Print total matche count and the last entry we found + $ECHO "($count) $lastentry" + exitstatus=$STATE_CRITICAL +fi + +exit $exitstatus diff --git a/Monitoring/nagios/plugins/check_mailq b/Monitoring/nagios/plugins/check_mailq new file mode 100755 index 00000000..01a147b9 --- /dev/null +++ b/Monitoring/nagios/plugins/check_mailq @@ -0,0 +1,608 @@ +#! /usr/bin/perl -w + +# check_mailq - check to see how many messages are in the smtp queue awating +# transmittal. +# +# Initial version support sendmail's mailq command +# Support for mutiple sendmail queues (Carlos Canau) +# Support for qmail (Benjamin Schmid) + +# License Information: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +############################################################################ + +use POSIX; +use strict; +use Getopt::Long; +use vars qw($opt_V $opt_h $opt_v $verbose $PROGNAME $opt_w $opt_c $opt_t + $opt_M $mailq $status $state $msg $msg_q $msg_p $opt_W $opt_C $mailq @lines + %srcdomains %dstdomains); +use lib "/usr/lib/nagios/plugins"; +use utils qw(%ERRORS &print_revision &support &usage ); + + +sub print_help (); +sub print_usage (); +sub process_arguments (); + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; +$PROGNAME = "check_mailq"; +$mailq = 'sendmail'; # default +$msg_q = 0 ; +$msg_p = 0 ; +$state = $ERRORS{'UNKNOWN'}; + +Getopt::Long::Configure('bundling'); +$status = process_arguments(); +if ($status){ + print "ERROR: processing arguments\n"; + exit $ERRORS{"UNKNOWN"}; +} + +$SIG{'ALRM'} = sub { + print ("ERROR: timed out waiting for $utils::PATH_TO_MAILQ \n"); + exit $ERRORS{"WARNING"}; +}; +alarm($opt_t); + +# switch based on MTA + +if ($mailq eq "sendmail") { + + ## open mailq + if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) { + if (! open (MAILQ, "$utils::PATH_TO_MAILQ | " ) ) { + print "ERROR: could not open $utils::PATH_TO_MAILQ \n"; + exit $ERRORS{'UNKNOWN'}; + } + }elsif( defined $utils::PATH_TO_MAILQ){ + unless (-x $utils::PATH_TO_MAILQ) { + print "ERROR: $utils::PATH_TO_MAILQ is not executable by (uid $>:gid($)))\n"; + exit $ERRORS{'UNKNOWN'}; + } + } else { + print "ERROR: \$utils::PATH_TO_MAILQ is not defined\n"; + exit $ERRORS{'UNKNOWN'}; + } +# single queue empty +##/var/spool/mqueue is empty +# single queue: 1 +## /var/spool/mqueue (1 request) +##----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------ +##h32E30p01763 2782 Wed Apr 2 15:03 <silvaATkpnqwest.pt> +## 8BITMIME +## <silvaATeunet.pt> + +# multi queue empty +##/var/spool/mqueue/q0/df is empty +##/var/spool/mqueue/q1/df is empty +##/var/spool/mqueue/q2/df is empty +##/var/spool/mqueue/q3/df is empty +##/var/spool/mqueue/q4/df is empty +##/var/spool/mqueue/q5/df is empty +##/var/spool/mqueue/q6/df is empty +##/var/spool/mqueue/q7/df is empty +##/var/spool/mqueue/q8/df is empty +##/var/spool/mqueue/q9/df is empty +##/var/spool/mqueue/qA/df is empty +##/var/spool/mqueue/qB/df is empty +##/var/spool/mqueue/qC/df is empty +##/var/spool/mqueue/qD/df is empty +##/var/spool/mqueue/qE/df is empty +##/var/spool/mqueue/qF/df is empty +## Total Requests: 0 +# multi queue: 1 +##/var/spool/mqueue/q0/df is empty +##/var/spool/mqueue/q1/df is empty +##/var/spool/mqueue/q2/df is empty +## /var/spool/mqueue/q3/df (1 request) +##----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------ +##h32De2f23534* 48 Wed Apr 2 14:40 nocol +## nouserATEUnet.pt +## canau +##/var/spool/mqueue/q4/df is empty +##/var/spool/mqueue/q5/df is empty +##/var/spool/mqueue/q6/df is empty +##/var/spool/mqueue/q7/df is empty +##/var/spool/mqueue/q8/df is empty +##/var/spool/mqueue/q9/df is empty +##/var/spool/mqueue/qA/df is empty +##/var/spool/mqueue/qB/df is empty +##/var/spool/mqueue/qC/df is empty +##/var/spool/mqueue/qD/df is empty +##/var/spool/mqueue/qE/df is empty +##/var/spool/mqueue/qF/df is empty +## Total Requests: 1 + + + while (<MAILQ>) { + + # match email addr on queue listing + if ( (/<.*@.*\.(\w+\.\w+)>/) || (/<.*@(\w+\.\w+)>/) ) { + my $domain = $1; + if (/^\w+/) { + print "$utils::PATH_TO_MAILQ = srcdomain = $domain \n" if $verbose ; + $srcdomains{$domain} ++; + } + next; + } + + # + # ... + # sendmail considers a message with more than one destiny, say N, to the same MX + # to have N messages in queue. + # we will only consider one in this code + if (( /\s\(reply:\sread\serror\sfrom\s.*\.(\w+\.\w+)\.$/ ) || ( /\s\(reply:\sread\serror\sfrom\s(\w+\.\w+)\.$/ ) || + ( /\s\(timeout\swriting\smessage\sto\s.*\.(\w+\.\w+)\.:/ ) || ( /\s\(timeout\swriting\smessage\sto\s(\w+\.\w+)\.:/ ) || + ( /\s\(host\smap:\slookup\s\(.*\.(\w+\.\w+)\):/ ) || ( /\s\(host\smap:\slookup\s\((\w+\.\w+)\):/ ) || + ( /\s\(Deferred:\s.*\s.*\.(\w+\.\w+)\.\)/ ) || ( /\s\(Deferred:\s.*\s(\w+\.\w+)\.\)/ ) ) { + + print "$utils::PATH_TO_MAILQ = dstdomain = $1 \n" if $verbose ; + $dstdomains{$1} ++; + } + + if (/\s+\(I\/O\serror\)/) { + print "$utils::PATH_TO_MAILQ = dstdomain = UNKNOWN \n" if $verbose ; + $dstdomains{'UNKNOWN'} ++; + } + + # Finally look at the overall queue length + # + if (/mqueue/) { + print "$utils::PATH_TO_MAILQ = $_ "if $verbose ; + if (/ \((\d+) request/) { + # + # single queue: first line + # multi queue: one for each queue. overwrite on multi queue below + $msg_q = $1 ; + } + } elsif (/^\s+Total\sRequests:\s(\d+)$/i) { + print "$utils::PATH_TO_MAILQ = $_ \n" if $verbose ; + # + # multi queue: last line + $msg_q = $1 ; + } + + } + + + ## close mailq + + close (MAILQ); + + if ( $? ) { + print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ",$/; + exit $ERRORS{CRITICAL}; + } + + ## shut off the alarm + alarm(0); + + + + ## now check the queue length(s) + + if ($msg_q == 0) { + $msg = "OK: mailq is empty"; + $state = $ERRORS{'OK'}; + } else { + print "msg_q = $msg_q warn=$opt_w crit=$opt_c\n" if $verbose; + + # overall queue length + if ($msg_q < $opt_w) { + $msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)"; + $state = $ERRORS{'OK'}; + }elsif ($msg_q >= $opt_w && $msg_q < $opt_c) { + $msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)"; + $state = $ERRORS{'WARNING'}; + }else { + $msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)"; + $state = $ERRORS{'CRITICAL'}; + } + + # check for domain specific queue lengths if requested + if (defined $opt_W) { + + # Apply threshold to queue lengths FROM domain + my @srckeys = sort { $srcdomains{$b} <=> $srcdomains{$a} } keys %srcdomains; + my $srcmaxkey = $srckeys[0]; + print "src max is $srcmaxkey with $srcdomains{$srcmaxkey} messages\n" if $verbose; + + if ($srcdomains{$srcmaxkey} >= $opt_W && $srcdomains{$srcmaxkey} < $opt_C) { + if ($state == $ERRORS{'OK'}) { + $msg = "WARNING: $srcdomains{$srcmaxkey} messages in queue FROM $srcmaxkey (threshold W = $opt_W)"; + $state = $ERRORS{'WARNING'}; + } elsif (($state == $ERRORS{'WARNING'}) || ($state == $ERRORS{'CRITICAL'})){ + $msg .= " -and- $srcdomains{$srcmaxkey} messages in queue FROM $srcmaxkey (threshold W = $opt_W)"; + } else { + $msg = "WARNING: $srcdomains{$srcmaxkey} messages in queue FROM $srcmaxkey (threshold W = $opt_W)"; + $state = $ERRORS{'WARNING'}; + } + } elsif ($srcdomains{$srcmaxkey} >= $opt_C) { + if ($state == $ERRORS{'OK'}) { + $msg = "CRITICAL: $srcdomains{$srcmaxkey} messages in queue FROM $srcmaxkey (threshold C = $opt_C)"; + $state = $ERRORS{'CRITICAL'}; + } elsif ($state == $ERRORS{'WARNING'}) { + $msg = "CRITICAL: $srcdomains{$srcmaxkey} messages in queue FROM $srcmaxkey (threshold C = $opt_C) -and- " . $msg; + $msg =~ s/WARNING: //; + } elsif ($state == $ERRORS{'CRITICAL'}) { + $msg .= " -and- $srcdomains{$srcmaxkey} messages in queue FROM $srcmaxkey (threshold W = $opt_W)"; + } else { + $msg = "CRITICAL: $srcdomains{$srcmaxkey} messages in queue FROM $srcmaxkey (threshold W = $opt_W)"; + $state = $ERRORS{'CRITICAL'}; + } + } else { + if ($srcdomains{$srcmaxkey} > 0) { + $msg .= " $srcdomains{$srcmaxkey} msgs. FROM $srcmaxkey is below threshold ($opt_W/$opt_C)"; + } + } + + # Apply threshold to queue lengths TO domain + my @dstkeys = sort { $dstdomains{$b} <=> $dstdomains{$a} } keys %dstdomains; + my $dstmaxkey = $dstkeys[0]; + print "dst max is $dstmaxkey with $dstdomains{$dstmaxkey} messages\n" if $verbose; + + if ($dstdomains{$dstmaxkey} >= $opt_W && $dstdomains{$dstmaxkey} < $opt_C) { + if ($state == $ERRORS{'OK'}) { + $msg = "WARNING: $dstdomains{$dstmaxkey} messages in queue TO $dstmaxkey (threshold W = $opt_W)"; + $state = $ERRORS{'WARNING'}; + } elsif (($state == $ERRORS{'WARNING'}) || ($state == $ERRORS{'CRITICAL'})){ + $msg .= " -and- $dstdomains{$dstmaxkey} messages in queue TO $dstmaxkey (threshold W = $opt_W)"; + } else { + $msg = "WARNING: $dstdomains{$dstmaxkey} messages in queue TO $dstmaxkey (threshold W = $opt_W)"; + $state = $ERRORS{'WARNING'}; + } + } elsif ($dstdomains{$dstmaxkey} >= $opt_C) { + if ($state == $ERRORS{'OK'}) { + $msg = "CRITICAL: $dstdomains{$dstmaxkey} messages in queue TO $dstmaxkey (threshold C = $opt_C)"; + $state = $ERRORS{'CRITICAL'}; + } elsif ($state == $ERRORS{'WARNING'}) { + $msg = "CRITICAL: $dstdomains{$dstmaxkey} messages in queue TO $dstmaxkey (threshold C = $opt_C) -and- " . $msg; + $msg =~ s/WARNING: //; + } elsif ($state == $ERRORS{'CRITICAL'}) { + $msg .= " -and- $dstdomains{$dstmaxkey} messages in queue TO $dstmaxkey (threshold W = $opt_W)"; + } else { + $msg = "CRITICAL: $dstdomains{$dstmaxkey} messages in queue TO $dstmaxkey (threshold W = $opt_W)"; + $state = $ERRORS{'CRITICAL'}; + } + } else { + if ($dstdomains{$dstmaxkey} > 0) { + $msg .= " $dstdomains{$dstmaxkey} msgs. TO $dstmaxkey is below threshold ($opt_W/$opt_C)"; + } + } + + } # End of queue length thresholds + + } + +} # end of ($mailq eq "sendmail") +elsif ( $mailq eq "postfix" ) { + + ## open mailq + if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) { + if (! open (MAILQ, "$utils::PATH_TO_MAILQ | " ) ) { + print "ERROR: could not open $utils::PATH_TO_MAILQ \n"; + exit $ERRORS{'UNKNOWN'}; + } + }elsif( defined $utils::PATH_TO_MAILQ){ + unless (-x $utils::PATH_TO_MAILQ) { + print "ERROR: $utils::PATH_TO_MAILQ is not executable by (uid $>:gid($)))\n"; + exit $ERRORS{'UNKNOWN'}; + } + } else { + print "ERROR: \$utils::PATH_TO_MAILQ is not defined\n"; + exit $ERRORS{'UNKNOWN'}; + } + + + @lines = reverse <MAILQ>; + + # close qmail-qstat + close MAILQ; + + if ( $? ) { + print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ",$/; + exit $ERRORS{CRITICAL}; + } + + ## shut off the alarm + alarm(0); + + # check queue length + if ($lines[0]=~/Kbytes in (\d+)/) { + $msg_q = $1 ; + }elsif ($lines[0]=~/Mail queue is empty/) { + $msg_q = 0; + }else{ + print "Couldn't match $utils::PATH_TO_QMAIL_QSTAT output\n"; + exit $ERRORS{'UNKNOWN'}; + } + + # check messages not processed + #if ($lines[1]=~/^messages in queue but not yet preprocessed: (\d+)/) { + # my $msg_p = $1; + #}else{ + # print "Couldn't match $utils::PATH_TO_QMAIL_QSTAT output\n"; + # exit $ERRORS{'UNKNOWN'}; + #} + + # check queue length(s) + if ($msg_q == 0){ + $msg = "OK: mailq reports queue is empty"; + $state = $ERRORS{'OK'}; + } else { + print "msg_q = $msg_q warn=$opt_w crit=$opt_c\n" if $verbose; + + # overall queue length + if ($msg_q < $opt_w) { + $msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)"; + $state = $ERRORS{'OK'}; + }elsif ($msg_q >= $opt_w && $msg_q < $opt_c) { + $msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)"; + $state = $ERRORS{'WARNING'}; + }else { + $msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)"; + $state = $ERRORS{'CRITICAL'}; + } + + # check messages not yet preprocessed (only compare is $opt_W and $opt_C + # are defined) + + #if (defined $opt_W) { + # $msg .= "[Preprocessed = $msg_p]"; + # if ($msg_p >= $opt_W && $msg_p < $opt_C ) { + # $state = $state == $ERRORS{"CRITICAL"} ? $ERRORS{"CRITICAL"} : $ERRORS{"WARNING"} ; + # }elsif ($msg_p >= $opt_C ) { + # $state = $ERRORS{"CRITICAL"} ; + # } + #} + } +} # end of ($mailq eq "postfixl") +elsif ( $mailq eq "qmail" ) { + + # open qmail-qstat + if ( defined $utils::PATH_TO_QMAIL_QSTAT && -x $utils::PATH_TO_QMAIL_QSTAT ) { + if (! open (MAILQ, "$utils::PATH_TO_QMAIL_QSTAT | " ) ) { + print "ERROR: could not open $utils::PATH_TO_QMAIL_QSTAT \n"; + exit $ERRORS{'UNKNOWN'}; + } + }elsif( defined $utils::PATH_TO_QMAIL_QSTAT){ + unless (-x $utils::PATH_TO_QMAIL_QSTAT) { + print "ERROR: $utils::PATH_TO_QMAIL_QSTAT is not executable by (uid $>:gid($)))\n"; + exit $ERRORS{'UNKNOWN'}; + } + } else { + print "ERROR: \$utils::PATH_TO_QMAIL_QSTAT is not defined\n"; + exit $ERRORS{'UNKNOWN'}; + } + + @lines = <MAILQ>; + + # close qmail-qstat + close MAILQ; + + if ( $? ) { + print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ",$/; + exit $ERRORS{CRITICAL}; + } + + ## shut off the alarm + alarm(0); + + # check queue length + if ($lines[0]=~/^messages in queue: (\d+)/) { + $msg_q = $1 ; + }else{ + print "Couldn't match $utils::PATH_TO_QMAIL_QSTAT output\n"; + exit $ERRORS{'UNKNOWN'}; + } + + # check messages not processed + if ($lines[1]=~/^messages in queue but not yet preprocessed: (\d+)/) { + my $msg_p = $1; + }else{ + print "Couldn't match $utils::PATH_TO_QMAIL_QSTAT output\n"; + exit $ERRORS{'UNKNOWN'}; + } + + + # check queue length(s) + if ($msg_q == 0){ + $msg = "OK: qmail-qstat reports queue is empty"; + $state = $ERRORS{'OK'}; + } else { + print "msg_q = $msg_q warn=$opt_w crit=$opt_c\n" if $verbose; + + # overall queue length + if ($msg_q < $opt_w) { + $msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)"; + $state = $ERRORS{'OK'}; + }elsif ($msg_q >= $opt_w && $msg_q < $opt_c) { + $msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)"; + $state = $ERRORS{'WARNING'}; + }else { + $msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)"; + $state = $ERRORS{'CRITICAL'}; + } + + # check messages not yet preprocessed (only compare is $opt_W and $opt_C + # are defined) + + if (defined $opt_W) { + $msg .= "[Preprocessed = $msg_p]"; + if ($msg_p >= $opt_W && $msg_p < $opt_C ) { + $state = $state == $ERRORS{"CRITICAL"} ? $ERRORS{"CRITICAL"} : $ERRORS{"WARNING"} ; + }elsif ($msg_p >= $opt_C ) { + $state = $ERRORS{"CRITICAL"} ; + } + } + } + + + +} # end of ($mailq eq "qmail") +elsif ( $mailq eq "exim" ) { + ## open mailq + if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) { + if (! open (MAILQ, "$utils::PATH_TO_MAILQ | " ) ) { + print "ERROR: could not open $utils::PATH_TO_MAILQ \n"; + exit $ERRORS{'UNKNOWN'}; + } + }elsif( defined $utils::PATH_TO_MAILQ){ + unless (-x $utils::PATH_TO_MAILQ) { + print "ERROR: $utils::PATH_TO_MAILQ is not executable by (uid $>:gid($)))\n"; + exit $ERRORS{'UNKNOWN'}; + } + } else { + print "ERROR: \$utils::PATH_TO_MAILQ is not defined\n"; + exit $ERRORS{'UNKNOWN'}; + } + + while (<MAILQ>) { + #22m 1.7K 19aEEr-0007hx-Dy <> *** frozen *** + #root@exlixams.glups.fr + + if (/\s[\w\d]{6}-[\w\d]{6}-[\w\d]{2}\s/) { # message id 19aEEr-0007hx-Dy + $msg_q++ ; + } + } + close(MAILQ) ; + + if ( $? ) { + print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ",$/; + exit $ERRORS{CRITICAL}; + } + if ($msg_q < $opt_w) { + $msg = "OK: mailq ($msg_q) is below threshold ($opt_w/$opt_c)"; + $state = $ERRORS{'OK'}; + }elsif ($msg_q >= $opt_w && $msg_q < $opt_c) { + $msg = "WARNING: mailq is $msg_q (threshold w = $opt_w)"; + $state = $ERRORS{'WARNING'}; + }else { + $msg = "CRITICAL: mailq is $msg_q (threshold c = $opt_c)"; + $state = $ERRORS{'CRITICAL'}; + } +} # end of ($mailq eq "exim") + +# Perfdata support +print "$msg|unsent=$msg_q;$opt_w;$opt_c;0\n"; +exit $state; + + +##################################### +#### subs + + +sub process_arguments(){ + GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "v" => \$opt_v, "verbose" => \$opt_v, + "h" => \$opt_h, "help" => \$opt_h, + "M:s" => \$opt_M, "mailserver:s" => \$opt_M, # mailserver (default sendmail) + "w=i" => \$opt_w, "warning=i" => \$opt_w, # warning if above this number + "c=i" => \$opt_c, "critical=i" => \$opt_c, # critical if above this number + "t=i" => \$opt_t, "timeout=i" => \$opt_t + ); + + if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); + exit $ERRORS{'OK'}; + } + + if ($opt_h) { + print_help(); + exit $ERRORS{'OK'}; + } + + if (defined $opt_v ){ + $verbose = $opt_v; + } + + unless (defined $opt_t) { + $opt_t = $utils::TIMEOUT ; # default timeout + } + + unless ( defined $opt_w && defined $opt_c ) { + print_usage(); + exit $ERRORS{'UNKNOWN'}; + } + + if ( $opt_w >= $opt_c) { + print "Warning (-w) cannot be greater than Critical (-c)!\n"; + exit $ERRORS{'UNKNOWN'}; + } + + if (defined $opt_W && ! defined !$opt_C) { + print "Need -C if using -W\n"; + exit $ERRORS{'UNKNOWN'}; + }elsif(defined $opt_W && defined $opt_C) { + if ($opt_W >= $opt_C) { + print "Warning (-W) cannot be greater than Critical (-C)!\n"; + exit $ERRORS{'UNKNOWN'}; + } + } + + if (defined $opt_M) { + if ($opt_M =~ /^(sendmail|qmail|postfix|exim)$/) { + $mailq = $opt_M ; + }elsif( $opt_M eq ''){ + $mailq = 'sendmail'; + }else{ + print "-M: $opt_M is not supported\n"; + exit $ERRORS{'UNKNOWN'}; + } + }else{ + $mailq = 'sendmail' ; + } + + return $ERRORS{'OK'}; +} + +sub print_usage () { + print "Usage: $PROGNAME -w <warn> -c <crit> [-W <warn>] [-C <crit>] [-M <MTA>] [-t <timeout>] [-v verbose]\n"; +} + +sub print_help () { + print_revision($PROGNAME,'1.4.15'); + print "Copyright (c) 2002 Subhendu Ghosh/Carlos Canau/Benjamin Schmid\n"; + print "\n"; + print_usage(); + print "\n"; + print " Checks the number of messages in the mail queue (supports multiple sendmail queues, qmail)\n"; + print " Feedback/patches to support non-sendmail mailqueue welcome\n\n"; + print "-w (--warning) = Min. number of messages in queue to generate warning\n"; + print "-c (--critical) = Min. number of messages in queue to generate critical alert ( w < c )\n"; + print "-W (--Warning) = Min. number of messages for same domain in queue to generate warning\n"; + print "-C (--Critical) = Min. number of messages for same domain in queue to generate critical alert ( W < C )\n"; + print "-t (--timeout) = Plugin timeout in seconds (default = $utils::TIMEOUT)\n"; + print "-M (--mailserver) = [ sendmail | qmail | postfix | exim ] (default = sendmail)\n"; + print "-h (--help)\n"; + print "-V (--version)\n"; + print "-v (--verbose) = debugging output\n"; + print "\n\n"; + print "Note: -w and -c are required arguments. -W and -C are optional.\n"; + print " -W and -C are applied to domains listed on the queues - both FROM and TO. (sendmail)\n"; + print " -W and -C are applied message not yet preproccessed. (qmail)\n"; + print " This plugin uses the system mailq command (sendmail) or qmail-stat (qmail)\n"; + print " to look at the queues. Mailq can usually only be accessed by root or \n"; + print " a TrustedUser. You will have to set appropriate permissions for the plugin to work.\n"; + print ""; + print "\n\n"; + support(); +} diff --git a/Monitoring/nagios/plugins/check_mem.pl b/Monitoring/nagios/plugins/check_mem.pl new file mode 100755 index 00000000..99e2b1f7 --- /dev/null +++ b/Monitoring/nagios/plugins/check_mem.pl @@ -0,0 +1,263 @@ +#!/usr/bin/perl -w +# $Id: check_mem.pl 2 2002-02-28 06:42:51Z egalstad $ + +# Original script stolen from: +# check_mem.pl Copyright (C) 2000 Dan Larsson <dl@tyfon.net> +# hacked by +# Justin Ellison <justin@techadvise.com> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# you should have received a copy of the GNU General Public License +# along with this program (or with Nagios); if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA + +# Tell Perl what we need to use +use strict; +use Getopt::Std; + +#TODO - Convert to Nagios::Plugin +#TODO - Use an alarm + +# Predefined exit codes for Nagios +use vars qw($opt_c $opt_f $opt_u $opt_w $opt_C $opt_v %exit_codes); +%exit_codes = ('UNKNOWN' ,-1, + 'OK' , 0, + 'WARNING' , 1, + 'CRITICAL', 2, + ); + +# Get our variables, do our checking: +init(); + +# Get the numbers: +my ($free_memory_kb,$used_memory_kb,$caches_kb) = get_memory_info(); +print "$free_memory_kb Free\n$used_memory_kb Used\n$caches_kb Cache\n" if ($opt_v); + +if ($opt_C) { #Do we count caches as free? + $used_memory_kb -= $caches_kb; + $free_memory_kb += $caches_kb; +} + +# Round to the nearest KB +$free_memory_kb = sprintf('%d',$free_memory_kb); +$used_memory_kb = sprintf('%d',$used_memory_kb); +$caches_kb = sprintf('%d',$caches_kb); + +# Tell Nagios what we came up with +tell_nagios($used_memory_kb,$free_memory_kb,$caches_kb); + + +sub tell_nagios { + my ($used,$free,$caches) = @_; + + # Calculate Total Memory + my $total = $free + $used; + print "$total Total\n" if ($opt_v); + + my $perfdata = "|TOTAL=${total}KB;;;; USED=${used}KB;;;; FREE=${free}KB;;;; CACHES=${caches}KB;;;;"; + + if ($opt_f) { + my $percent = sprintf "%.1f", ($free / $total * 100); + if ($percent <= $opt_c) { + finish("CRITICAL - $percent% ($free kB) free!$perfdata",$exit_codes{'CRITICAL'}); + } + elsif ($percent <= $opt_w) { + finish("WARNING - $percent% ($free kB) free!$perfdata",$exit_codes{'WARNING'}); + } + else { + finish("OK - $percent% ($free kB) free.$perfdata",$exit_codes{'OK'}); + } + } + elsif ($opt_u) { + my $percent = sprintf "%.1f", ($used / $total * 100); + if ($percent >= $opt_c) { + finish("CRITICAL - $percent% ($used kB) used!$perfdata",$exit_codes{'CRITICAL'}); + } + elsif ($percent >= $opt_w) { + finish("WARNING - $percent% ($used kB) used!$perfdata",$exit_codes{'WARNING'}); + } + else { + finish("OK - $percent% ($used kB) used.$perfdata",$exit_codes{'OK'}); + } + } +} + +# Show usage +sub usage() { + print "\ncheck_mem.pl v1.0 - Nagios Plugin\n\n"; + print "usage:\n"; + print " check_mem.pl -<f|u> -w <warnlevel> -c <critlevel>\n\n"; + print "options:\n"; + print " -f Check FREE memory\n"; + print " -u Check USED memory\n"; + print " -C Count OS caches as FREE memory\n"; + print " -w PERCENT Percent free/used when to warn\n"; + print " -c PERCENT Percent free/used when critical\n"; + print "\nCopyright (C) 2000 Dan Larsson <dl\@tyfon.net>\n"; + print "check_mem.pl comes with absolutely NO WARRANTY either implied or explicit\n"; + print "This program is licensed under the terms of the\n"; + print "GNU General Public License (check source code for details)\n"; + exit $exit_codes{'UNKNOWN'}; +} + +sub get_memory_info { + my $used_memory_kb = 0; + my $free_memory_kb = 0; + my $total_memory_kb = 0; + my $caches_kb = 0; + + my $uname; + if ( -e '/usr/bin/uname') { + $uname = `/usr/bin/uname -a`; + } + elsif ( -e '/bin/uname') { + $uname = `/bin/uname -a`; + } + else { + die "Unable to find uname in /usr/bin or /bin!\n"; + } + print "uname returns $uname" if ($opt_v); + if ( $uname =~ /Linux/ ) { + my @meminfo = `/bin/cat /proc/meminfo`; + foreach (@meminfo) { + chomp; + if (/^Mem(Total|Free):\s+(\d+) kB/) { + my $counter_name = $1; + if ($counter_name eq 'Free') { + $free_memory_kb = $2; + } + elsif ($counter_name eq 'Total') { + $total_memory_kb = $2; + } + } + elsif (/^(Buffers|Cached):\s+(\d+) kB/) { + $caches_kb += $2; + } + } + $used_memory_kb = $total_memory_kb - $free_memory_kb; + } + elsif ( $uname =~ /SunOS/ ) { + eval "use Sun::Solaris::Kstat"; + if ($@) { #Kstat not available + if ($opt_C) { + print "You can't report on Solaris caches without Sun::Solaris::Kstat available!\n"; + exit $exit_codes{UNKNOWN}; + } + my @vmstat = `/usr/bin/vmstat 1 2`; + my $line; + foreach (@vmstat) { + chomp; + $line = $_; + } + $free_memory_kb = (split(/ /,$line))[5] / 1024; + my @prtconf = `/usr/sbin/prtconf`; + foreach (@prtconf) { + if (/^Memory size: (\d+) Megabytes/) { + $total_memory_kb = $1 * 1024; + } + } + $used_memory_kb = $total_memory_kb - $free_memory_kb; + + } + else { # We have kstat + my $kstat = Sun::Solaris::Kstat->new(); + my $phys_pages = ${kstat}->{unix}->{0}->{system_pages}->{physmem}; + my $free_pages = ${kstat}->{unix}->{0}->{system_pages}->{freemem}; + # We probably should account for UFS caching here, but it's unclear + # to me how to determine UFS's cache size. There's inode_cache, + # and maybe the physmem variable in the system_pages module?? + # In the real world, it looks to be so small as not to really matter, + # so we don't grab it. If someone can give me code that does this, + # I'd be glad to put it in. + my $arc_size = (exists ${kstat}->{zfs} && ${kstat}->{zfs}->{0}->{arcstats}->{size}) ? + ${kstat}->{zfs}->{0}->{arcstats}->{size} / 1024 + : 0; + $caches_kb += $arc_size; + my $pagesize = `pagesize`; + + $total_memory_kb = $phys_pages * $pagesize / 1024; + $free_memory_kb = $free_pages * $pagesize / 1024; + $used_memory_kb = $total_memory_kb - $free_memory_kb; + } + } + elsif ( $uname =~ /AIX/ ) { + my @meminfo = `/usr/bin/vmstat -v`; + foreach (@meminfo) { + chomp; + if (/^\s*([0-9.]+)\s+(.*)/) { + my $counter_name = $2; + if ($counter_name eq 'memory pages') { + $total_memory_kb = $1*4; + } + if ($counter_name eq 'free pages') { + $free_memory_kb = $1*4; + } + if ($counter_name eq 'file pages') { + $caches_kb = $1*4; + } + } + } + $used_memory_kb = $total_memory_kb - $free_memory_kb; + } + else { + if ($opt_C) { + print "You can't report on $uname caches!\n"; + exit $exit_codes{UNKNOWN}; + } + my $command_line = `vmstat | tail -1 | awk '{print \$4,\$5}'`; + chomp $command_line; + my @memlist = split(/ /, $command_line); + + # Define the calculating scalars + $used_memory_kb = $memlist[0]/1024; + $free_memory_kb = $memlist[1]/1024; + $total_memory_kb = $used_memory_kb + $free_memory_kb; + } + return ($free_memory_kb,$used_memory_kb,$caches_kb); +} + +sub init { + # Get the options + if ($#ARGV le 0) { + &usage; + } + else { + getopts('c:fuCvw:'); + } + + # Shortcircuit the switches + if (!$opt_w or $opt_w == 0 or !$opt_c or $opt_c == 0) { + print "*** You must define WARN and CRITICAL levels!\n"; + &usage; + } + elsif (!$opt_f and !$opt_u) { + print "*** You must select to monitor either USED or FREE memory!\n"; + &usage; + } + + # Check if levels are sane + if ($opt_w <= $opt_c and $opt_f) { + print "*** WARN level must not be less than CRITICAL when checking FREE memory!\n"; + &usage; + } + elsif ($opt_w >= $opt_c and $opt_u) { + print "*** WARN level must not be greater than CRITICAL when checking USED memory!\n"; + &usage; + } +} + +sub finish { + my ($msg,$state) = @_; + print "$msg\n"; + exit $state; +} diff --git a/Monitoring/nagios/plugins/check_mrtg b/Monitoring/nagios/plugins/check_mrtg Binary files differnew file mode 100755 index 00000000..33a912e6 --- /dev/null +++ b/Monitoring/nagios/plugins/check_mrtg diff --git a/Monitoring/nagios/plugins/check_mrtgtraf b/Monitoring/nagios/plugins/check_mrtgtraf Binary files differnew file mode 100755 index 00000000..ca686d72 --- /dev/null +++ b/Monitoring/nagios/plugins/check_mrtgtraf diff --git a/Monitoring/nagios/plugins/check_mysql b/Monitoring/nagios/plugins/check_mysql Binary files differnew file mode 100755 index 00000000..5dd232b2 --- /dev/null +++ b/Monitoring/nagios/plugins/check_mysql diff --git a/Monitoring/nagios/plugins/check_mysql_query b/Monitoring/nagios/plugins/check_mysql_query Binary files differnew file mode 100755 index 00000000..c456440f --- /dev/null +++ b/Monitoring/nagios/plugins/check_mysql_query diff --git a/Monitoring/nagios/plugins/check_nagios b/Monitoring/nagios/plugins/check_nagios Binary files differnew file mode 100755 index 00000000..4cb2614e --- /dev/null +++ b/Monitoring/nagios/plugins/check_nagios diff --git a/Monitoring/nagios/plugins/check_nntp b/Monitoring/nagios/plugins/check_nntp new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_nntp @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_nntps b/Monitoring/nagios/plugins/check_nntps new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_nntps @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_nt b/Monitoring/nagios/plugins/check_nt Binary files differnew file mode 100755 index 00000000..d1fd06e0 --- /dev/null +++ b/Monitoring/nagios/plugins/check_nt diff --git a/Monitoring/nagios/plugins/check_ntp b/Monitoring/nagios/plugins/check_ntp Binary files differnew file mode 100755 index 00000000..8fdc6857 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ntp diff --git a/Monitoring/nagios/plugins/check_ntp_peer b/Monitoring/nagios/plugins/check_ntp_peer Binary files differnew file mode 100755 index 00000000..967b2a76 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ntp_peer diff --git a/Monitoring/nagios/plugins/check_ntp_time b/Monitoring/nagios/plugins/check_ntp_time Binary files differnew file mode 100755 index 00000000..e8a78e05 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ntp_time diff --git a/Monitoring/nagios/plugins/check_nwstat b/Monitoring/nagios/plugins/check_nwstat Binary files differnew file mode 100755 index 00000000..ad53275f --- /dev/null +++ b/Monitoring/nagios/plugins/check_nwstat diff --git a/Monitoring/nagios/plugins/check_oracle b/Monitoring/nagios/plugins/check_oracle new file mode 100755 index 00000000..95cb68b6 --- /dev/null +++ b/Monitoring/nagios/plugins/check_oracle @@ -0,0 +1,287 @@ +#! /bin/bash +# +# latigid010@yahoo.com +# 01/06/2000 +# +# This Nagios plugin was created to check Oracle status +# + +PROGNAME=`basename $0` +PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'` +REVISION="1.4.15" + +. $PROGPATH/utils.sh + + +print_usage() { + echo "Usage:" + echo " $PROGNAME --tns <Oracle Sid or Hostname/IP address>" + echo " $PROGNAME --db <ORACLE_SID>" + echo " $PROGNAME --login <ORACLE_SID>" + echo " $PROGNAME --cache <ORACLE_SID> <USER> <PASS> <CRITICAL> <WARNING>" + echo " $PROGNAME --tablespace <ORACLE_SID> <USER> <PASS> <TABLESPACE> <CRITICAL> <WARNING>" + echo " $PROGNAME --oranames <Hostname>" + echo " $PROGNAME --help" + echo " $PROGNAME --version" +} + +print_help() { + print_revision $PROGNAME $REVISION + echo "" + print_usage + echo "" + echo "Check Oracle status" + echo "" + echo "--tns SID/IP Address" + echo " Check remote TNS server" + echo "--db SID" + echo " Check local database (search /bin/ps for PMON process) and check" + echo " filesystem for sgadefORACLE_SID.dbf" + echo "--login SID" + echo " Attempt a dummy login and alert if not ORA-01017: invalid username/password" + echo "--cache" + echo " Check local database for library and buffer cache hit ratios" + echo " ---> Requires Oracle user/password and SID specified." + echo " ---> Requires select on v_$sysstat and v_$librarycache" + echo "--tablespace" + echo " Check local database for tablespace capacity in ORACLE_SID" + echo " ---> Requires Oracle user/password specified." + echo " ---> Requires select on dba_data_files and dba_free_space" + echo "--oranames Hostname" + echo " Check remote Oracle Names server" + echo "--help" + echo " Print this help screen" + echo "--version" + echo " Print version and license information" + echo "" + echo "If the plugin doesn't work, check that the ORACLE_HOME environment" + echo "variable is set, that ORACLE_HOME/bin is in your PATH, and the" + echo "tnsnames.ora file is locatable and is properly configured." + echo "" + echo "When checking local database status your ORACLE_SID is case sensitive." + echo "" + echo "If you want to use a default Oracle home, add in your oratab file:" + echo "*:/opt/app/oracle/product/7.3.4:N" + echo "" + support +} + +case "$1" in +1) + cmd='--tns' + ;; +2) + cmd='--db' + ;; +*) + cmd="$1" + ;; +esac + +# Information options +case "$cmd" in +--help) + print_help + exit $STATE_OK + ;; +-h) + print_help + exit $STATE_OK + ;; +--version) + print_revision $PROGNAME $REVISION + exit $STATE_OK + ;; +-V) + print_revision $PROGNAME $REVISION + exit $STATE_OK + ;; +esac + +# Hunt down a reasonable ORACLE_HOME +if [ -z "$ORACLE_HOME" ] ; then + # Adjust to taste + for oratab in /var/opt/oracle/oratab /etc/oratab + do + [ ! -f $oratab ] && continue + ORACLE_HOME=`IFS=: + while read SID ORACLE_HOME junk; + do + if [ "$SID" = "$2" -o "$SID" = "*" ] ; then + echo $ORACLE_HOME; + exit; + fi; + done < $oratab` + [ -n "$ORACLE_HOME" ] && break + done +fi +# Last resort +[ -z "$ORACLE_HOME" -a -d $PROGPATH/oracle ] && ORACLE_HOME=$PROGPATH/oracle + +if [ "$cmd" != "--db" ]; then + if [ -z "$ORACLE_HOME" -o ! -d "$ORACLE_HOME" ] ; then + echo "Cannot determine ORACLE_HOME for sid $2" + exit $STATE_UNKNOWN + fi +fi +PATH=$PATH:$ORACLE_HOME/bin +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib +export ORACLE_HOME PATH LD_LIBRARY_PATH + +case "$cmd" in +--tns) + tnschk=` tnsping $2` + tnschk2=` echo $tnschk | grep -c OK` + if [ ${tnschk2} -eq 1 ] ; then + tnschk3=` echo $tnschk | sed -e 's/.*(//' -e 's/).*//'` + echo "OK - reply time ${tnschk3} from $2" + exit $STATE_OK + else + echo "No TNS Listener on $2" + exit $STATE_CRITICAL + fi + ;; +--oranames) + namesctl status $2 | awk ' + /Server has been running for:/ { + msg = "OK: Up" + for (i = 6; i <= NF; i++) { + msg = msg " " $i + } + status = '$STATE_OK' + } + /error/ { + msg = "CRITICAL: " $0 + status = '$STATE_CRITICAL' + } + END { + print msg + exit status + }' + ;; +--db) + pmonchk=`ps -ef | grep -v grep | grep -c "ora_pmon_${2}$"` + if [ ${pmonchk} -ge 1 ] ; then + echo "${2} OK - ${pmonchk} PMON process(es) running" + exit $STATE_OK + #if [ -f $ORACLE_HOME/dbs/sga*${2}* ] ; then + #if [ ${pmonchk} -eq 1 ] ; then + #utime=`ls -la $ORACLE_HOME/dbs/sga*$2* | cut -c 43-55` + #echo "${2} OK - running since ${utime}" + #exit $STATE_OK + #fi + else + echo "${2} Database is DOWN" + exit $STATE_CRITICAL + fi + ;; +--login) + loginchk=`sqlplus dummy/user@$2 < /dev/null` + loginchk2=` echo $loginchk | grep -c ORA-01017` + if [ ${loginchk2} -eq 1 ] ; then + echo "OK - dummy login connected" + exit $STATE_OK + else + loginchk3=` echo "$loginchk" | grep "ORA-" | head -1` + echo "CRITICAL - $loginchk3" + exit $STATE_CRITICAL + fi + ;; +--cache) + if [ ${5} -gt ${6} ] ; then + echo "UNKNOWN - Warning level is less then Crit" + exit $STATE_UNKNOWN + fi + result=`sqlplus -s ${3}/${4}@${2} << EOF +set pagesize 0 +set numf '9999999.99' +select (1-(pr.value/(dbg.value+cg.value)))*100 +from v\\$sysstat pr, v\\$sysstat dbg, v\\$sysstat cg +where pr.name='physical reads' +and dbg.name='db block gets' +and cg.name='consistent gets'; +EOF` + + if [ -n "`echo $result | grep ORA-`" ] ; then + error=` echo "$result" | grep "ORA-" | head -1` + echo "CRITICAL - $error" + exit $STATE_CRITICAL + fi + + buf_hr=`echo "$result" | awk '/^[0-9\. \t]+$/ {print int($1)}'` + buf_hrx=`echo "$result" | awk '/^[0-9\. \t]+$/ {print $1}'` + result=`sqlplus -s ${3}/${4}@${2} << EOF +set pagesize 0 +set numf '9999999.99' +select sum(lc.pins)/(sum(lc.pins)+sum(lc.reloads))*100 +from v\\$librarycache lc; +EOF` + + if [ -n "`echo $result | grep ORA-`" ] ; then + error=` echo "$result" | grep "ORA-" | head -1` + echo "CRITICAL - $error" + exit $STATE_CRITICAL + fi + + lib_hr=`echo "$result" | awk '/^[0-9\. \t]+$/ {print int($1)}'` + lib_hrx=`echo "$result" | awk '/^[0-9\. \t]+$/ {print $1}'` + + if [ $buf_hr -le ${5} -o $lib_hr -le ${5} ] ; then + echo "${2} CRITICAL - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx%;${6};${5};0;100 buffer=$buf_hrx%;${6};${5};0;100" + exit $STATE_CRITICAL + fi + if [ $buf_hr -le ${6} -o $lib_hr -le ${6} ] ; then + echo "${2} WARNING - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx%;${6};${5};0;100 buffer=$buf_hrx%;${6};${5};0;100" + exit $STATE_WARNING + fi + echo "${2} OK - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx%;${6};${5};0;100 buffer=$buf_hrx%;${6};${5};0;100" + + exit $STATE_OK + ;; +--tablespace) + if [ ${6} -lt ${7} ] ; then + echo "UNKNOWN - Warning level is more then Crit" + exit $STATE_UNKNOWN + fi + result=`sqlplus -s ${3}/${4}@${2} << EOF +set pagesize 0 +set numf '9999999.99' +select NVL(b.free,0.0),a.total,100 - trunc(NVL(b.free,0.0)/a.total * 1000) / 10 prc +from ( +select tablespace_name,sum(bytes)/1024/1024 total +from dba_data_files group by tablespace_name) A +LEFT OUTER JOIN +( select tablespace_name,sum(bytes)/1024/1024 free +from dba_free_space group by tablespace_name) B +ON a.tablespace_name=b.tablespace_name WHERE a.tablespace_name='${5}'; +EOF` + + if [ -n "`echo $result | grep ORA-`" ] ; then + error=` echo "$result" | grep "ORA-" | head -1` + echo "CRITICAL - $error" + exit $STATE_CRITICAL + fi + + ts_free=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($1)}'` + ts_total=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($2)}'` + ts_pct=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($3)}'` + ts_pctx=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print $3}'` + if [ "$ts_free" -eq 0 -a "$ts_total" -eq 0 -a "$ts_pct" -eq 0 ] ; then + echo "No data returned by Oracle - tablespace $5 not found?" + exit $STATE_UNKNOWN + fi + if [ "$ts_pct" -ge ${6} ] ; then + echo "${2} : ${5} CRITICAL - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${5}=$ts_pctx%;${7};${6};0;100" + exit $STATE_CRITICAL + fi + if [ "$ts_pct" -ge ${7} ] ; then + echo "${2} : ${5} WARNING - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${5}=$ts_pctx%;${7};${6};0;100" + exit $STATE_WARNING + fi + echo "${2} : ${5} OK - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${5}=$ts_pctx%;${7};${6};0;100" + exit $STATE_OK + ;; +*) + print_usage + exit $STATE_UNKNOWN +esac diff --git a/Monitoring/nagios/plugins/check_overcr b/Monitoring/nagios/plugins/check_overcr Binary files differnew file mode 100755 index 00000000..d179627b --- /dev/null +++ b/Monitoring/nagios/plugins/check_overcr diff --git a/Monitoring/nagios/plugins/check_pgsql b/Monitoring/nagios/plugins/check_pgsql Binary files differnew file mode 100755 index 00000000..0940a678 --- /dev/null +++ b/Monitoring/nagios/plugins/check_pgsql diff --git a/Monitoring/nagios/plugins/check_ping b/Monitoring/nagios/plugins/check_ping Binary files differnew file mode 100755 index 00000000..eac2e9a9 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ping diff --git a/Monitoring/nagios/plugins/check_pop b/Monitoring/nagios/plugins/check_pop new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_pop @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_procs b/Monitoring/nagios/plugins/check_procs Binary files differnew file mode 100755 index 00000000..92c08b4a --- /dev/null +++ b/Monitoring/nagios/plugins/check_procs diff --git a/Monitoring/nagios/plugins/check_radius b/Monitoring/nagios/plugins/check_radius Binary files differnew file mode 100755 index 00000000..71253c3e --- /dev/null +++ b/Monitoring/nagios/plugins/check_radius diff --git a/Monitoring/nagios/plugins/check_real b/Monitoring/nagios/plugins/check_real Binary files differnew file mode 100755 index 00000000..408fb8ff --- /dev/null +++ b/Monitoring/nagios/plugins/check_real diff --git a/Monitoring/nagios/plugins/check_rpc b/Monitoring/nagios/plugins/check_rpc new file mode 100755 index 00000000..10a847ef --- /dev/null +++ b/Monitoring/nagios/plugins/check_rpc @@ -0,0 +1,375 @@ +#! /usr/bin/perl -w +# +# check_rpc plugin for nagios +# +# usage: +# check_rpc host service +# +# Check if an rpc serice is registered and running +# using rpcinfo - $proto $host $prognum 2>&1 |"; +# +# Use these hosts.cfg entries as examples +# +# command[check_nfs]=/some/path/libexec/check_rpc $HOSTADDRESS$ nfs +# service[check_nfs]=NFS;24x7;3;5;5;unix-admin;60;24x7;1;1;1;;check_rpc +# +# initial version: 3 May 2000 by Truongchinh Nguyen and Karl DeBisschop +# Modified May 2002 Subhendu Ghosh - support for ePN and patches +# +# Copyright Notice: GPL +# + +use strict; +use lib "/usr/lib/nagios/plugins"; +use utils qw($TIMEOUT %ERRORS &print_revision &support); +use vars qw($PROGNAME); +my ($verbose,@proto,%prognum,$host,$response,$prognum,$port,$cmd,$progver,$state); +my ($array_ref,$test,$element,@progkeys,$proto,$a,$b); +my ($opt_V,$opt_h,$opt_C,$opt_p,$opt_H,$opt_c,$opt_u,$opt_t); +my ($line, @progvers, $response2,$response3); +$opt_V = $opt_h = $opt_C = $opt_p = $opt_H = $opt_u = $opt_t =''; +$state = 'UNKNOWN'; +$progver = $response=$response2= $response3 =''; + +$PROGNAME = "check_rpc"; +sub print_help (); +sub print_usage (); +sub in ($$); + +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; +$ENV{'PATH'}=''; +$ENV{'LC_ALL'}='C'; + +#Initialise protocol for each progname number +# 'u' for UDP, 't' for TCP +$proto[10003]='u'; +$proto[10004]='u'; +$proto[10007]='u'; + +use Getopt::Long; +Getopt::Long::Configure('bundling'); +GetOptions( + "V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "C=s" => \$opt_C, "command=s" => \$opt_C, + "p=i" => \$opt_p, "port=i" => \$opt_p, + "H=s" => \$opt_H, "hostname=s" => \$opt_H, + "c=s" => \$opt_c, "progver=s" => \$opt_c, + "v+" => \$verbose, "verbose+" => \$verbose, + "u" => \$opt_u, "udp" => \$opt_u, + "t" => \$opt_t, "tcp" => \$opt_t +); + +# -h means display verbose help screen +if ($opt_h) { print_help(); exit $ERRORS{'OK'}; } + +# -V means display version number +if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); + exit $ERRORS{'OK'}; +} + +# Hash containing all RPC program names and numbers +# Add to the hash if support for new RPC program is required + +%prognum = ( + "portmapper" => 100000 , + "portmap" => 100000 , + "sunrpc" => 100000 , + "rpcbind" => 100000 , + "rstatd" => 100001 , + "rstat" => 100001 , + "rup" => 100001 , + "perfmeter" => 100001 , + "rstat_svc" => 100001 , + "rusersd" => 100002 , + "rusers" => 100002 , + "nfs" => 100003 , + "nfsprog" => 100003 , + "ypserv" => 100004 , + "ypprog" => 100004 , + "mountd" => 100005 , + "mount" => 100005 , + "showmount" => 100005 , + "ypbind" => 100007 , + "walld" => 100008 , + "rwall" => 100008 , + "shutdown" => 100008 , + "yppasswdd" => 100009 , + "yppasswd" => 100009 , + "etherstatd" => 100010 , + "etherstat" => 100010 , + "rquotad" => 100011 , + "rquotaprog" => 100011 , + "quota" => 100011 , + "rquota" => 100011 , + "sprayd" => 100012 , + "spray" => 100012 , + "3270_mapper" => 100013 , + "rje_mapper" => 100014 , + "selection_svc" => 100015 , + "selnsvc" => 100015 , + "database_svc" => 100016 , + "rexd" => 100017 , + "rex" => 100017 , + "alis" => 100018 , + "sched" => 100019 , + "llockmgr" => 100020 , + "nlockmgr" => 100021 , + "x25_inr" => 100022 , + "statmon" => 100023 , + "status" => 100024 , + "bootparam" => 100026 , + "ypupdated" => 100028 , + "ypupdate" => 100028 , + "keyserv" => 100029 , + "keyserver" => 100029 , + "sunlink_mapper" => 100033 , + "tfsd" => 100037 , + "nsed" => 100038 , + "nsemntd" => 100039 , + "showfhd" => 100043 , + "showfh" => 100043 , + "ioadmd" => 100055 , + "rpc.ioadmd" => 100055 , + "NETlicense" => 100062 , + "sunisamd" => 100065 , + "debug_svc" => 100066 , + "dbsrv" => 100066 , + "ypxfrd" => 100069 , + "rpc.ypxfrd" => 100069 , + "bugtraqd" => 100071 , + "kerbd" => 100078 , + "event" => 100101 , + "na.event" => 100101 , + "logger" => 100102 , + "na.logger" => 100102 , + "sync" => 100104 , + "na.sync" => 100104 , + "hostperf" => 100107 , + "na.hostperf" => 100107 , + "activity" => 100109 , + "na.activity" => 100109 , + "hostmem" => 100112 , + "na.hostmem" => 100112 , + "sample" => 100113 , + "na.sample" => 100113 , + "x25" => 100114 , + "na.x25" => 100114 , + "ping" => 100115 , + "na.ping" => 100115 , + "rpcnfs" => 100116 , + "na.rpcnfs" => 100116 , + "hostif" => 100117 , + "na.hostif" => 100117 , + "etherif" => 100118 , + "na.etherif" => 100118 , + "iproutes" => 100120 , + "na.iproutes" => 100120 , + "layers" => 100121 , + "na.layers" => 100121 , + "snmp" => 100122 , + "na.snmp" => 100122 , + "snmp-cmc" => 100122 , + "snmp-synoptics" => 100122 , + "snmp-unisys" => 100122 , + "snmp-utk" => 100122 , + "traffic" => 100123 , + "na.traffic" => 100123 , + "nfs_acl" => 100227 , + "sadmind" => 100232 , + "nisd" => 100300 , + "rpc.nisd" => 100300 , + "nispasswd" => 100303 , + "rpc.nispasswdd" => 100303 , + "ufsd" => 100233 , + "ufsd" => 100233 , + "pcnfsd" => 150001 , + "pcnfs" => 150001 , + "amd" => 300019 , + "amq" => 300019 , + "bwnfsd" => 545580417 , + "fypxfrd" => 600100069 , + "freebsd-ypxfrd" => 600100069 , +); + +# -v means verbose, -v-v means verbose twice = print above hash +if (defined $verbose && ($verbose > 1) ){ + my $key; + print "Supported programs:\n"; + print " name\t=>\tnumber\n"; + print " ===============================\n"; + foreach $key (sort keys %prognum) { + print " $key \t=>\t$prognum{$key} \n"; + } + print "\n\n"; + print_usage(); + exit $ERRORS{'OK'}; +} + +# -H means host name +unless ($opt_H) { print_usage(); exit $ERRORS{'UNKNOWN'}; } + +if (! utils::is_hostname($opt_H)){ + print "$opt_H is not a valid host name\n"; + print_usage(); + exit $ERRORS{"UNKNOWN"}; +}else{ + $host = $opt_H; +} + +if ($opt_t && $opt_u) { + print "Cannot define tcp AND udp\n"; + print_usage(); + exit $ERRORS{'UNKNOWN'}; +} + + +# -C means command name or number +$opt_C = shift unless ($opt_C); +unless ($opt_C) { print_usage(); exit -1; } +@progkeys = keys %prognum; +if ($opt_C =~ m/^([0-9]+)$/){ +# $response = "RPC ok: program $opt_C (version "; + $prognum = $1; +} elsif ( in( \@progkeys, $opt_C)) { +# $response = "RPC ok: $opt_C (version "; + $prognum = $prognum{$opt_C}; +} else { + print "Program $opt_C is not defined\n"; + exit $ERRORS{'UNKNOWN'}; +} + +# -p means port number +if($opt_p =~ /^([0-9]+)$/){ + $port = "-n $1"; +} else { + $port = ""; +} + +$proto = 'u'; +$proto = $proto[$prognum] if ($proto[$prognum]); +$proto = 't' if ($opt_t); +$proto = 'u' if ($opt_u); + + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No response from RPC server (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + +# -c is progver - if we need to check multiple specified versions. +if (defined $opt_c ) { + my $vers; + @progvers = split(/,/ ,$opt_c ); + foreach $vers (sort @progvers) { + if($vers =~ /^([0-9]+)$/){ + $progver = "$1"; + print "Checking $opt_C version $progver proto $proto\n" if $verbose; + get_rpcinfo(); + }else{ + print "Version $vers is not an integer\n" if $verbose; + } + + } +}else{ + get_rpcinfo(); +} + + +## translate proto for output +if ($proto eq "u" ){ + $proto = "udp"; +}else{ + $proto = "tcp"; +} + +if ($state eq 'OK') { + print "$state: RPC program $opt_C".$response." $proto running\n"; +}else{ + if($response){ + print "$state: RPC program $opt_C".$response2." $proto is not running,".$response." $proto is running\n"; + }else{ + print "$state: RPC program $opt_C $response2 $proto is not running\n"; + } +} +exit $ERRORS{$state}; + + +######## Subroutines ========================== + +sub get_rpcinfo { + $cmd = "$utils::PATH_TO_RPCINFO $port -" . "$proto $host $prognum $progver 2>&1 |"; + print "$cmd\n" if ($verbose); + open CMD, $cmd or die "Can't fork for rpcinfo: $!\n" ; + + while ( $line = <CMD> ) { + printf "$line " if $verbose; + chomp $line; + + if ( $line =~ /program $prognum version ([0-9]*) ready and waiting/ ) { + $response .= " version $1"; + $state = 'OK' unless $state ne 'UNKNOWN'; + print "1:$response \n" if $verbose; + } + + if ( $line =~ /program $prognum version ([0-9]*) is not available/ ) { + $response2 .= " version $1"; + $state = 'CRITICAL'; + print "2:$response2 \n" if $verbose; + } + if ( $line =~ /program $prognum is not available/ ) { + $response3 = ""; + $response3 = "tcp" if $opt_t; + $response3 = "udp" if $opt_u; + $state = 'CRITICAL'; + print "3:$response3 \n" if $verbose; + } + } + close CMD; +} + + +sub print_help() { + print_revision($PROGNAME,'1.4.15'); + print "Copyright (c) 2002 Karl DeBisschop/Truongchinh Nguyen/Subhendu Ghosh\n"; + print "\n"; + print "Check if a rpc service is registered and running using\n"; + print " rpcinfo -H host -C rpc_command \n"; + print "\n"; + print_usage(); + print "\n"; + print " <host> The server providing the rpc service\n"; + print " <rpc_command> The program name (or number).\n"; + print " <program_version> The version you want to check for (one or more)\n"; + print " Should prevent checks of unknown versions being syslogged\n"; + print " e.g. 2,3,6 to check v2, v3, and v6\n"; + print " [-u | -t] Test UDP or TCP\n"; + print " [-v] Verbose \n"; + print " [-v -v] Verbose - will print supported programs and numbers \n"; + print "\n"; + support(); +} + +sub print_usage () { + print "Usage: \n"; + print " $PROGNAME -H host -C rpc_command [-p port] [-c program_version] [-u|-t] [-v]\n"; + print " $PROGNAME [-h | --help]\n"; + print " $PROGNAME [-V | --version]\n"; +} + +sub in ($$) { + $array_ref = shift; + $test = shift; + + while ( $element = shift @{$array_ref} ) { + if ($test eq $element) { + return 1; + } + } + return 0; +} + diff --git a/Monitoring/nagios/plugins/check_rta_multi b/Monitoring/nagios/plugins/check_rta_multi new file mode 120000 index 00000000..97878096 --- /dev/null +++ b/Monitoring/nagios/plugins/check_rta_multi @@ -0,0 +1 @@ +check_icmp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_sensors b/Monitoring/nagios/plugins/check_sensors new file mode 100755 index 00000000..857a4d5a --- /dev/null +++ b/Monitoring/nagios/plugins/check_sensors @@ -0,0 +1,65 @@ +#! /bin/bash + +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin + +PROGNAME=`basename $0` +PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'` +REVISION="1.4.15" + +. $PROGPATH/utils.sh + + +print_usage() { + echo "Usage: $PROGNAME" +} + +print_help() { + print_revision $PROGNAME $REVISION + echo "" + print_usage + echo "" + echo "This plugin checks hardware status using the lm_sensors package." + echo "" + support + exit 0 +} + +case "$1" in + --help) + print_help + exit 0 + ;; + -h) + print_help + exit 0 + ;; + --version) + print_revision $PROGNAME $REVISION + exit 0 + ;; + -V) + print_revision $PROGNAME $REVISION + exit 0 + ;; + *) + sensordata=`sensors 2>&1` + status=$? + if test "$1" = "-v" -o "$1" = "--verbose"; then + echo ${sensordata} + fi + if test ${status} -eq 127; then + echo "SENSORS UNKNOWN - command not found (did you install lmsensors?)" + exit -1 + elif test ${status} -ne 0 ; then + echo "WARNING - sensors returned state $status" + exit 1 + fi + if echo ${sensordata} | egrep ALARM > /dev/null; then + echo SENSOR CRITICAL - Sensor alarm detected! + exit 2 + else + echo sensor ok + exit 0 + fi + ;; +esac diff --git a/Monitoring/nagios/plugins/check_shinken.py b/Monitoring/nagios/plugins/check_shinken.py new file mode 100755 index 00000000..a3827000 --- /dev/null +++ b/Monitoring/nagios/plugins/check_shinken.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +#Copyright (C) 2009-2011 : +# Denis GERMAIN, dt.germain@gmail.com +# Gabes Jean, naparuba@gmail.com +# Gerhard Lausser, Gerhard.Lausser@consol.de +# Gregory Starck, g.starck@gmail.com +# Hartmut Goebel, h.goebel@goebel-consult.de +# +#This file is part of Shinken. +# +#Shinken is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#Shinken is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU Affero General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with Shinken. If not, see <http://www.gnu.org/licenses/>. + +################################################ +# check_shinken.py : +# This check is getting daemons state from +# a arbiter connection. +################################################ + +import os + +# Exit statuses recognized by Nagios and thus by Shinken +OK = 0 +WARNING = 1 +CRITICAL = 2 +UNKNOWN = 3 + +#Name of the Pyro Object we are searching +PYRO_OBJECT = 'ForArbiter' +daemon_types = ['arbiter', 'broker', 'scheduler', 'poller', 'reactionner'] + +try: + import shinken +except ImportError: + # If importing shinken fails, try to load from current directory + # or parent directory to support running without installation. + # Submodules will then be loaded from there, too. + import imp + if not hasattr(os, "getuid") or os.getuid() != 0: + imp.load_module('shinken', *imp.find_module('shinken', [".", ".."])) + + +from optparse import OptionParser +try: + import shinken.pyro_wrapper as pyro + from shinken.pyro_wrapper import Pyro +except ImportError, exp: + print 'CRITICAL : check_shinken requires the Python Pyro and the shinken.pyro_wrapper module. Please install it. (%s)' % exp + raise SystemExit, CRITICAL + + +def check_deamons_numbers(result, target): + total_number = len(result) + alive_number = len([e for e in result.values() if e['alive']]) + total_spare_number = len([e for e in result.values() if e['spare']]) + alive_spare_number = len([e for e in result.values() if e['spare'] and e['alive']]) + dead_number = total_number - alive_number + dead_list = ','.join([n for n in result if not result[n]['alive']]) + #TODO : perfdata to graph deamons would be nice (in big HA architectures) + #if alive_number <= critical, then we have a big problem + if alive_number <= options.critical: + print "CRITICAL - only %d/%d %s(s) UP. Down elements : %s" % (alive_number, total_number, target, dead_list) + raise SystemExit, CRITICAL + #We are not in a case where there is no more daemons, but are there daemons down? + elif dead_number >= options.warning: + print "WARNING - %d/%d %s(s) DOWN :%s" % (dead_number, total_number, target, dead_list) + raise SystemExit, WARNING + #Everything seems fine. But that's no surprise, is it? + else : + print "OK - %d/%d %s(s) UP, with %d/%d spare(s) UP" % (alive_number, total_number, target, alive_spare_number, total_spare_number) + raise SystemExit, OK + +# Adding options. None are required, check_shinken will use shinken defaults +#TODO : Add more control in args problem and usage than the default OptionParser one +parser = OptionParser() +parser.add_option('-a', '--hostname', dest='hostname', default='127.0.0.1') +parser.add_option('-p', '--portnumber', dest='portnum', default=7770) +parser.add_option('-s', '--ssl', dest='ssl', default=False) +#TODO : Add a list of correct values for target and don't authorize anything else +parser.add_option('-t', '--target', dest='target') +parser.add_option('-d', '--daemonname', dest='daemon', default='') +#In HA architectures, a warning should be displayed if there's one daemon down +parser.add_option('-w','--warning', dest='warning', default = 1) +#If no deamon is left, display a critical (but shinken will be probably dead already) +parser.add_option('-c', '--critical', dest='critical', default = 0) + +#Retrieving options +options, args = parser.parse_args() +#TODO : for now, helpme doesn't work as desired +options.helpme = False + +# Check for required option target +if not getattr(options, 'target'): + print 'CRITICAL - target is not specified; You must specify which daemons you want to check!' + parser.print_help() + raise SystemExit, CRITICAL +elif options.target not in daemon_types: + print 'CRITICAL - target %s is not a Shinken daemon!' % options.target + parser.print_help() + raise SystemExit, CRITICAL + +uri = pyro.create_uri(options.hostname, options.portnum, PYRO_OBJECT , options.ssl) + +if options.daemon: + # We just want a check for a single satellite daemon + # Only OK or CRITICAL here + daemon_name = options.daemon + try: + result = Pyro.core.getProxyForURI(uri).get_satellite_status(options.target, daemon_name) + except Pyro.errors.ProtocolError, exp: + print "CRITICAL : the Arbiter is not reachable : (%s)." % exp + raise SystemExit, CRITICAL + + if result: + if result['alive']: + print 'OK - %s alive' % daemon_name + raise SystemExit, OK + else: + print 'CRITICAL - %s down' % daemon_name + raise SystemExit, CRITICAL + else: + print 'UNKNOWN - %s status could not be retrieved' % daemon_name + raise SystemExit, UNKNOWN +else: + # If no daemonname is specified, we want a general overview of the "target" daemons + result = {} + + try: + daemon_list = Pyro.core.getProxyForURI(uri).get_satellite_list(options.target) + except Pyro.errors.ProtocolError, exp: + print "CRITICAL : the Arbiter is not reachable : (%s)." % exp + raise SystemExit, CRITICAL + + for daemon_name in daemon_list: + # Getting individual daemon and putting status info in the result dictionnary + try: + result[daemon_name] = Pyro.core.getProxyForURI(uri).get_satellite_status(options.target, daemon_name) + except Pyro.errors.ProtocolError, exp: + print "CRITICAL : the Arbiter is not reachable : (%s)." % exp + raise SystemExit, CRITICAL + + # Now we have all data + if result: + check_deamons_numbers(result, options.target) + else : + print 'UNKNOWN - Arbiter could not retrieve status for %s' % options.target + raise SystemExit, UNKNOWN diff --git a/Monitoring/nagios/plugins/check_simap b/Monitoring/nagios/plugins/check_simap new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_simap @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_sip b/Monitoring/nagios/plugins/check_sip new file mode 100755 index 00000000..24374727 --- /dev/null +++ b/Monitoring/nagios/plugins/check_sip @@ -0,0 +1,252 @@ +#!/usr/bin/perl -w +# +# check_sip plugin for nagios +# $Revision: 1.2 $ +# +# Nagios plugin to check SIP servers +# +# By Sam Bashton, Bashton Ltd +# bashton.com/content/nagiosplugins +# Michael Hirschbichler, Institute of Broadband Communications, +# Vienna University of Technology +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +use strict; +use lib "/usr/lib/nagios/plugins"; +use utils qw($TIMEOUT %ERRORS &print_revision &support); +use vars qw($PROGNAME); +use IO::Socket::INET; +#use Sys::Hostname; +use Time::HiRes qw(gettimeofday); +use Net::Domain qw (hostname hostfqdn hostdomain); + +$PROGNAME = "check_sip"; +my $VERSION = "1.2"; + +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; +$ENV{'PATH'}=''; +$ENV{'LC_ALL'}='C'; + +my ($opt_V,$opt_h,$opt_u,$opt_p,$opt_H, $opt_w, $opt_s, $opt_f); +$opt_V = $opt_h = $opt_u = $opt_p = $opt_H = $opt_w = $opt_s = $opt_f = ''; + +my $state = 'UNKNOWN'; + +use Getopt::Long; +Getopt::Long::Configure('bundling'); +GetOptions( + "V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "s" => \$opt_s, + "f=s" => \$opt_f, "fromuri=s" => \$opt_f, + "u=s" => \$opt_u, "uri=s" => \$opt_u, + "p=s" => \$opt_p, "port=s" => \$opt_p, + "H=s" => \$opt_H, "host=s" => \$opt_H, + "w=s" => \$opt_w, "warn=s" => \$opt_w +); + +# -h displays help +if ($opt_h) { printHelp(); exit $ERRORS{'OK'}; } + +# -V display version number +if ($opt_V) { + print_revision($PROGNAME, $VERSION); + exit $ERRORS{'OK'}; +}; + +# Check the sip URI is OK +unless ($opt_u) { printHelp(); exit $ERRORS{'UNKNOWN'} } + +# Port is 5060 unless otherwise specified +unless ($opt_p) { $opt_p = 5060 } + +# Determine the host from the sip URI if it wasn't specified with -H +unless ($opt_H) { $opt_H = hostFromURI($opt_u) } + +# Check the host is valid +unless (utils::is_hostname($opt_H)) +{ + print "$opt_H is not a valid hostname\n"; + printHelp(); + exit $ERRORS{"UNKNOWN"}; +} + +unless ($opt_w) { $opt_w = 5 } # Warn if response takes longer than 5 seconds + +### Main code ############################################################### + +# Timeout if we don't recieve a response within a suitable timeframe.. +$SIG{'ALRM'} = sub { + print ("SIP timeout: No response from SIP server after $TIMEOUT seconds\n"); + exit $ERRORS{"CRITICAL"}; +}; +alarm($TIMEOUT); + +my $localhost = hostfqdn(); +$opt_f = getFromURI($opt_f,$localhost,$opt_p); +my $user=getUserPart($opt_f); +my $socket = uconnect($opt_H, $opt_p); +my @localinfo = unpack_sockaddr_in($socket->sockname); +my $req = buildReq($localinfo[0], $opt_u, $opt_f,$user,$localhost); +my (undef, $starttime) = gettimeofday; +$socket->send($req); +my $response; +$socket->recv($response, 1024) or $state = 'CRITICAL'; + +#get rid of the 100 Trying - provisional response ... +if (getResponseCode($response) eq "100"){ + $socket->recv($response, 1024) or $state = 'CRITICAL'; +} + +my (undef, $finishtime) = gettimeofday; +my $rtime = ($finishtime - $starttime) / 1000000; # Time taken in seconds +if(checkResponse($response,$rtime,$opt_s)) +{ + if ($rtime > $opt_w) { $state = 'WARNING' } + else { $state = 'OK' } +} +else { $state = 'CRITICAL' } + +exit $ERRORS{$state}; + +### Subroutines ############################################################## + + +sub uconnect +{ + my ($host, $port) = @_; + my $socket = new IO::Socket::INET->new(PeerPort=>$port, Proto=>'udp', PeerAddr=>$host); + unless ($socket) { print "Unable to connect to $host\n"; exit $ERRORS{'UNKNOWN'} } + return $socket; +} + +sub getFromURI{ + my ($from, $localhost,$localport) = @_; + if (!("$from" eq "")){ + return "$from:$localport"; + }else + { + return "sip:checksip\@$localhost:$localport"; + } +} + +sub getUserPart{ + my ($uri) = @_; + my @uris=split(/\@/,$uri); + my $user=$uris[0]; + return $user; +} + +sub hostFromURI +{ + my ($uri) = @_; + $uri =~ s/sip:[^\@]+@//; + return $uri; +} + +sub getResponseCode +{ + my ($message) = @_; + my @messageparts=split(/\ /,$message); + return $messageparts[1]; +} + +sub buildReq +{ + my ($localport, $dsturi, $fromuri,$user,$localhost) = @_; + + my $req; + my $tag = genTag(); + my $idtag = genTag(); + $req.= "OPTIONS $dsturi SIP/2.0\r\n"; + $req.= "Via: SIP/2.0/UDP $localhost:$localport;branch=z9hG4bKhjhs8ass877\r\n"; + $req.= "Max-Forwards: 70\r\n"; + $req.= "To: $dsturi\r\n"; + $req.= "From: $fromuri;tag=$tag\r\n"; + $req.= "Call-ID: $idtag\@$localhost\r\n"; + $req.= "CSeq: 1 OPTIONS\r\n"; + $req.= "Contact: <$user\@$localhost:$localport>\r\n"; + $req.= "Accept: application/sdp\r\n"; + $req.= "Content-Length: 0\r\n\r\n"; + return $req; +} + +sub genTag +{ + my $tag; + my @chars = ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', + 'q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8', + '9'); + + for (my $i = 0; $i < 6; $i++) + { + $tag .= $chars[rand(scalar @chars)]; + } + return $tag; +} + +sub printHelp +{ + print "This plugin tests the sip service on the specified host.\n\n"; + print "Usage: $PROGNAME -u sip:uri\@example.com [-H host -p PORT -f sip:fromuri\@example.com -w WARNTIME -s]\n"; + print " $PROGNAME [-h | --help]\n"; + print " $PROGNAME [-V | --version]\n\n"; + print "Options:\n"; + print " -u sip:uri\@example.com\n"; + print " Full SIP uri, eg sip:uri\@example.com\n"; + print " -h, --help\n"; + print " Print this help\n"; + print " -V, --version\n"; + print " Print version information\n"; + print " -H host\n"; + print " Host name or IP Address to connect to\n"; + print " -p port\n"; + print " Port to connect to\n"; + print " -f sip:fromuri\@example.com\n"; + print " Full SIP uri, will be used for the \"From:\"-Header\n"; + print " -s\n"; + print " Changes default behavior: all SIP-responses will result in an \"OK\"\n\n"; + + +} + +sub checkResponse +{ + my ($response, $rtime, $sp_behavior) = @_; + my @header=split(/\r/,$response); + my $tstring=$header[0]; + my $rcode=getResponseCode($response); + if (!$sp_behavior){ + #in this case, we want to see if the SIP-server is respoding positively to our request + # Some SUT respond with 100 Trying - assume everything is OK if we get this + if ($response =~ /^SIP.+[12]00/){ + print "$tstring, $rtime seconds response time|rtt=".$rtime."s;0.5s;1s;0:10; code=".$rcode."\n"; + return 1; + } + elsif ($response =~ /^SIP.+404 Not Found/) { + print "$tstring, $rtime seconds response time|rtt=".$rtime."s;0.5s;1s;0:10; code=".$rcode."\n"; + return 0 } + else { print "Unknown error: $tstring, $rtime seconds response time|rtt=".$rtime."s;0.5s;1s;0:10; code=".$rcode."\n"; return 0; } + }else{ + #in this case, we accept every response from the server, as long it is SIP + if ($response =~ /^SIP./){ + print "$tstring, $rtime seconds response time|rtt=".$rtime."s;0.5s;1s;0:10; code=".$rcode."\n"; + return 1; + } + else { print "Unknown error: $tstring, $rtime seconds response time|rtt=".$rtime."s;0.5s;1s;0:10; code=".$rcode."\n"; return 0; } + } +} diff --git a/Monitoring/nagios/plugins/check_smtp b/Monitoring/nagios/plugins/check_smtp Binary files differnew file mode 100755 index 00000000..d70a48f0 --- /dev/null +++ b/Monitoring/nagios/plugins/check_smtp diff --git a/Monitoring/nagios/plugins/check_snmp b/Monitoring/nagios/plugins/check_snmp Binary files differnew file mode 100755 index 00000000..d3fcd068 --- /dev/null +++ b/Monitoring/nagios/plugins/check_snmp diff --git a/Monitoring/nagios/plugins/check_speed b/Monitoring/nagios/plugins/check_speed new file mode 100755 index 00000000..14a5b612 --- /dev/null +++ b/Monitoring/nagios/plugins/check_speed @@ -0,0 +1,34 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +#TODO check_speed is nearly the same as check_speeder, consolidate both scripts, probably by giving HIGH:LOW as params +import sys +import urllib + +if len(sys.argv) < 2 or '-h' in sys.argv: + print ("?? usage: %s URL [low-mhashes] ..." % sys.argv[0]) + print ("?? Server reply should look like this: '2011-07-11T09:00 400.0'") + exit(3) + +URL=sys.argv[1] +thresholds=[ float(i) for i in sys.argv[2:]] + +ecode=0 +try: + ret = urllib.urlopen(URL).read().split() + date = ret[0] + speeds = [float(i) for i in ret[1:]] + print ("** %s : %s Mhashes" % (date,' '.join([str(i) for i in speeds]))) + if len(speeds) != len(thresholds): + raise Exception("!! Number of speeds != number of given thresholds") + for i,speed in enumerate(speeds): + if speed < thresholds[i]: + print ("!! %.2f Mhash < %.2f Mhash ! (field %d)" %(speed,thresholds[i],i)) + ecode=2 +except Exception,e: + print("!! Something aweful happened: "+str(e)) + exit (1) +#TODO return WARNING if date is too old +if not ecode: + print ("** Everything is fine!") + +exit(ecode) diff --git a/Monitoring/nagios/plugins/check_spop b/Monitoring/nagios/plugins/check_spop new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_spop @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_ssh b/Monitoring/nagios/plugins/check_ssh Binary files differnew file mode 100755 index 00000000..a9d69666 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ssh diff --git a/Monitoring/nagios/plugins/check_ssmtp b/Monitoring/nagios/plugins/check_ssmtp new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_ssmtp @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_swap b/Monitoring/nagios/plugins/check_swap Binary files differnew file mode 100755 index 00000000..6015a7a2 --- /dev/null +++ b/Monitoring/nagios/plugins/check_swap diff --git a/Monitoring/nagios/plugins/check_tcp b/Monitoring/nagios/plugins/check_tcp Binary files differnew file mode 100755 index 00000000..b084eda3 --- /dev/null +++ b/Monitoring/nagios/plugins/check_tcp diff --git a/Monitoring/nagios/plugins/check_temper b/Monitoring/nagios/plugins/check_temper new file mode 100755 index 00000000..95191026 --- /dev/null +++ b/Monitoring/nagios/plugins/check_temper @@ -0,0 +1,31 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import sys +import urllib + +if len(sys.argv) < 2 or '-h' in sys.argv: + print ("?? usage: %s URL [high-val field 1] [high field 2] ..." % sys.argv[0]) + print ("?? Server reply should look like this: '2011-07-11T09:00 50.0 40.0'") + exit(3) + +URL=sys.argv[1] +thresholds=[ float(i) for i in sys.argv[2:]] + +ecode=0 +try: + ret = urllib.urlopen(URL).read().split() + date = ret[0] + temps = [float(i) for i in ret[1:]] + print ("** %s : %s" % (date,' '.join([str(i)+"°C" for i in temps]))) + if len(temps) != len(thresholds): + raise Exception("Number of temps != number of given thresholds") + for i,temp in enumerate(temps): + if temp > thresholds[i]: + print ("!! %.2f°°C > %.2f°C (field %d)!" %(temp,thresholds[i],i)) + ecode=2 +except Exception,e: + print("!! Something awful happened: "+str(e)) + exit (1) +if not ecode: + print ("** Everything is fine!") +exit(ecode) diff --git a/Monitoring/nagios/plugins/check_time b/Monitoring/nagios/plugins/check_time Binary files differnew file mode 100755 index 00000000..73a12209 --- /dev/null +++ b/Monitoring/nagios/plugins/check_time diff --git a/Monitoring/nagios/plugins/check_udp b/Monitoring/nagios/plugins/check_udp new file mode 120000 index 00000000..e838da97 --- /dev/null +++ b/Monitoring/nagios/plugins/check_udp @@ -0,0 +1 @@ +check_tcp
\ No newline at end of file diff --git a/Monitoring/nagios/plugins/check_ups b/Monitoring/nagios/plugins/check_ups Binary files differnew file mode 100755 index 00000000..cf641a5f --- /dev/null +++ b/Monitoring/nagios/plugins/check_ups diff --git a/Monitoring/nagios/plugins/check_users b/Monitoring/nagios/plugins/check_users Binary files differnew file mode 100755 index 00000000..a0617fd4 --- /dev/null +++ b/Monitoring/nagios/plugins/check_users diff --git a/Monitoring/nagios/plugins/check_wave b/Monitoring/nagios/plugins/check_wave new file mode 100755 index 00000000..efef4680 --- /dev/null +++ b/Monitoring/nagios/plugins/check_wave @@ -0,0 +1,122 @@ +#! /usr/bin/perl -wT +# + + +use strict; +use lib "/usr/lib/nagios/plugins"; +use utils qw($TIMEOUT %ERRORS &print_revision &support); +use vars qw($PROGNAME); +use Getopt::Long; +use vars qw($opt_V $opt_h $verbose $opt_w $opt_c $opt_H); +my (@test, $low1, $med1, $high1, $snr, $low2, $med2, $high2); +my ($low, $med, $high, $lowavg, $medavg, $highavg, $tot, $ss); + +$PROGNAME = "check_wave"; +sub print_help (); +sub print_usage (); + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +Getopt::Long::Configure('bundling'); +GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "v" => \$verbose, "verbose" => \$verbose, + "w=s" => \$opt_w, "warning=s" => \$opt_w, + "c=s" => \$opt_c, "critical=s" => \$opt_c, + "H=s" => \$opt_H, "hostname=s" => \$opt_H); + +if ($opt_V) { + print_revision($PROGNAME,'1.4.15'); #' + exit $ERRORS{'OK'}; +} + +if ($opt_h) { + print_help(); + exit $ERRORS{'OK'}; +} + +$opt_H = shift unless ($opt_H); +print_usage() unless ($opt_H); +my $host = $1 if ($opt_H =~ m/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z][-a-zA-Z0]+(\.[a-zA-Z][-a-zA-Z0]+)*)$/); +print_usage() unless ($host); + +($opt_c) || ($opt_c = shift) || ($opt_c = 120); +my $critical = $1 if ($opt_c =~ /([0-9]+)/); + +($opt_w) || ($opt_w = shift) || ($opt_w = 60); +my $warning = $1 if ($opt_w =~ /([0-9]+)/); + +$low1 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.8.1`; +@test = split(/ /,$low1); +$low1 = $test[2]; + +$med1 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.9.1`; +@test = split(/ /,$med1); +$med1 = $test[2]; + +$high1 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.10.1`; +@test = split(/ /,$high1); +$high1 = $test[2]; + +sleep(2); + +$snr = `snmpget $host public .1.3.6.1.4.1.762.2.5.2.1.17.1`; +@test = split(/ /,$snr); +$snr = $test[2]; +$snr = int($snr*25); + +$low2 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.8.1`; +@test = split(/ /,$low2); +$low2 = $test[2]; + +$med2 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.9.1`; +@test = split(/ /,$med2); +$med2 = $test[2]; + +$high2 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.10.1`; +@test = split(/ /,$high2); +$high2 = $test[2]; + +$low = $low2 - $low1; +$med = $med2 - $med1; +$high = $high2 - $high1; + +$tot = $low + $med + $high; + +if ($tot==0) { + $ss = 0; +} else { + $lowavg = $low / $tot; + $medavg = $med / $tot; + $highavg = $high / $tot; + $ss = ($medavg*50) + ($highavg*100); +} + +printf("Signal Strength at: %3.0f%, SNR at $snr%",$ss); + +if ($ss<$critical) { + exit(2); +} elsif ($ss<$warning) { + exit(1); +} else { + exit(0); +} + + +sub print_usage () { + print "Usage: $PROGNAME -H <host> [-w <warn>] [-c <crit>]\n"; +} + +sub print_help () { + print_revision($PROGNAME,'1.4.15'); + print "Copyright (c) 2000 Jeffery Blank/Karl DeBisschop\n"; + print "\n"; + print_usage(); + print "\n"; + print "<warn> = Signal strength at which a warning message will be generated.\n"; + print "<crit> = Signal strength at which a critical message will be generated.\n\n"; + support(); +} diff --git a/Monitoring/nagios/plugins/getwmic.sh b/Monitoring/nagios/plugins/getwmic.sh new file mode 100755 index 00000000..05ba8f21 --- /dev/null +++ b/Monitoring/nagios/plugins/getwmic.sh @@ -0,0 +1,7 @@ +wget http://dev.zenoss.org/svn/trunk/inst/externallibs/wmi-1.3.14.tar.bz2 +tar xvf wmi-1.3.14.tar.bz2 +cd wmi-1.3.14/ +sed -i 's/all: install/ZENHOME=..\/..\nall: install/' GNUmakefile +make +#cp bin/* /usr/local/bin/ +#cp lib/python/* /usr/local/lib/python diff --git a/Monitoring/nagios/plugins/link_vmware_host_vm.py b/Monitoring/nagios/plugins/link_vmware_host_vm.py new file mode 100755 index 00000000..b64cefa8 --- /dev/null +++ b/Monitoring/nagios/plugins/link_vmware_host_vm.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +#Copyright (C) 2009-2010 : +# Gabes Jean, naparuba@gmail.com +# Gerhard Lausser, Gerhard.Lausser@consol.de +# Gregory Starck, g.starck@gmail.com +# Hartmut Goebel <h.goebel@goebel-consult.de> +# +#This file is part of Shinken. +# +#Shinken is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#Shinken is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU Affero General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with Shinken. If not, see <http://www.gnu.org/licenses/>. + +import os +import sys +import shlex +import shutil +import optparse +from subprocess import Popen, PIPE + +# Try to load json (2.5 and higer) or simplejson if failed (python2.4) +try: + import json +except ImportError: + # For old Python version, load + # simple json (it can be hard json?! It's 2 functions guy!) + try: + import simplejson as json + except ImportError: + sys.exit("Error : you need the json or simplejson module for this script") + +VERSION = '0.1' + + +# Split and clean the rules from a string to a list +def _split_rules(rules): + return [r.strip() for r in rules.split('|')] + +# Apply all rules on the objects names +def _apply_rules(name, rules): + if 'nofqdn' in rules: + name = name.split('.', 1)[0] + if 'lower' in rules: + name = name.lower() + return name + +# Get all vmware hosts from a VCenter and return the list +def get_vmware_hosts(check_esx_path, vcenter, user, password): + list_host_cmd = [check_esx_path, '-D', vcenter, '-u', user, '-p', password, + '-l', 'runtime', '-s', 'listhost'] + + output = Popen(list_host_cmd, stdout=PIPE).communicate() + + parts = output[0].split(':') + hsts_raw = parts[1].split('|')[0] + hsts_raw_lst = hsts_raw.split(',') + + hosts = [] + for hst_raw in hsts_raw_lst: + hst_raw = hst_raw.strip() + # look as server4.mydomain(UP) + elts = hst_raw.split('(') + hst = elts[0] + hosts.append(hst) + + return hosts + + +# For a specific host, ask all VM on it to the VCenter +def get_vm_of_host(check_esx_path, vcenter, host, user, password): + print "Listing host", host + list_vm_cmd = [check_esx_path, '-D', vcenter, '-H', host, + '-u', user, '-p', password, + '-l', 'runtime', '-s', 'list'] + output = Popen(list_vm_cmd, stdout=PIPE).communicate() + parts = output[0].split(':') + # Maybe we got a 'CRITICAL - There are no VMs.' message, + # if so, we bypass this host + if len(parts) < 2: + return None + + vms_raw = parts[1].split('|')[0] + vms_raw_lst = vms_raw.split(',') + + lst = [] + for vm_raw in vms_raw_lst: + vm_raw = vm_raw.strip() + # look as MYVM(UP) + elts = vm_raw.split('(') + vm = elts[0] + lst.append(vm) + return lst + + +# Create all tuples of the links for the hosts +def create_all_links(res, rules): + r = [] + for host in res: + for vm in res[host]: + # First we apply rules on the names + host_name = _apply_rules(host, rules) + vm_name = _apply_rules(vm, rules) + v = (('host', host_name),('host', vm_name)) + r.append(v) + return r + + +def write_output(r, path): + try: + f = open(path+'.tmp', 'wb') + buf = json.dumps(r) + f.write(buf) + f.close() + shutil.move(path+'.tmp', path) + print "File %s wrote" % path + except IOError, exp: + sys.exit("Error writing the file %s : %s" % (path, exp)) + + +def main(check_esx_path, vcenter, user, password, output, rules): + rules = _split_rules(rules) + res = {} + hosts = get_vmware_hosts(check_esx_path, vcenter, user, password) + + for host in hosts: + lst = get_vm_of_host(check_esx_path, vcenter, host, user, password) + if lst: + res[host] = lst + + r = create_all_links(res, rules) + print "Created %d links" % len(r) + + write_output(r, output) + print "Finished!" + + +# Here we go! +if __name__ == "__main__": + # Manage the options + parser = optparse.OptionParser( + version="Shinken VMware links dumping script version %s" % VERSION) + parser.add_option("-o", "--output", + help="Path of the generated mapping file.") + parser.add_option("-x", "--esx3-path", dest='check_esx_path', + default='/usr/local/nagios/libexec/check_esx3.pl', + help="Full path of the check_esx3.pl script (default: %default)") + parser.add_option("-V", "--vcenter", '--Vcenter', + help="tThe IP/DNS address of your Vcenter host.") + parser.add_option("-u", "--user", + help="User name to connect to this Vcenter") + parser.add_option("-p", "--password", + help="The password of this user") + parser.add_option('-r', '--rules', default='', + help="Rules of name transformation. Valid names are: " + "`lower`: to lower names, " + "`nofqdn`: keep only the first name (server.mydomain.com -> server)." + "You can use several rules like `lower|nofqdn`") + + opts, args = parser.parse_args() + if args: + parser.error("does not take any positional arguments") + + if opts.vcenter is None: + parser.error("missing -V or --Vcenter option for the vcenter IP/DNS address") + if opts.user is None: + parser.error("missing -u or --user option for the vcenter username") + if opts.password is None: + error = True + parser.error("missing -p or --password option for the vcenter password") + if not os.path.exists(opts.check_esx_path): + parser.error("the path %s for the check_esx3.pl script is wrong, missing file" % opts.check_esx_path) + if opts.output is None: + parser.error("missing -o or --output option for the output mapping file") + + main(**opts.__dict__) diff --git a/Monitoring/nagios/plugins/negate b/Monitoring/nagios/plugins/negate Binary files differnew file mode 100755 index 00000000..5bfacfaa --- /dev/null +++ b/Monitoring/nagios/plugins/negate diff --git a/Monitoring/nagios/plugins/nmap_discovery_runner.py b/Monitoring/nagios/plugins/nmap_discovery_runner.py new file mode 100755 index 00000000..338e211f --- /dev/null +++ b/Monitoring/nagios/plugins/nmap_discovery_runner.py @@ -0,0 +1,419 @@ +#!/usr/bin/env python +#Copyright (C) 2009-2010 : +# Gabes Jean, naparuba@gmail.com +# Gerhard Lausser, Gerhard.Lausser@consol.de +# Gregory Starck, g.starck@gmail.com +# +#This file is part of Shinken. +# +#Shinken is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#Shinken is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU Affero General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with Shinken. If not, see <http://www.gnu.org/licenses/>. + +#sudo nmap 192.168.0.1 -T4 -O --traceroute -oX toto.xml + +import optparse +import sys +import os +import tempfile +import subprocess + +try: + # xml.etree.ElementTree is new in Python 2.5 + from xml.etree.ElementTree import ElementTree +except ImportError: + sys.exit("This script needs the Python ElementTree module. Please install it") + +VERSION = '0.1' + +parser = optparse.OptionParser( + "%prog [options] -t nmap scanning targets", + version="%prog " + VERSION) + +parser.add_option('-t', '--targets', dest="targets", + help="NMap scanning targets.") +parser.add_option('-v', '--verbose', dest="verbose", action='store_true', + help="Verbose output.") + +targets = [] +opts, args = parser.parse_args() +if not opts.targets: + parser.error("Requires at least one nmap target for scanning (option -t/--targets") +else: + targets.append(opts.targets) + +if not opts.verbose: + verbose = False +else: + verbose = True + +if args: + targets.extend(args) + +print "Got our target", targets + +def debug(txt): + if verbose: + print txt + +# Says if a host is up or not +def is_up(h): + status = h.find('status') + state = status.attrib['state'] + return state == 'up' + + + +class DetectedHost: + def __init__(self): + self.ip = '' + self.mac_vendor = '' + self.host_name = '' + + self.os_possibilities = [] + self.os = ('', '') + self.open_ports = [] + + self.parent = '' + + + # Keep the first name we've got + def set_host_name(self, name): + if self.host_name == '': + self.host_name = name + + + # Get a identifier for this host + def get_name(self): + if self.host_name != '': + return self.host_name + if self.ip != '': + return self.ip + return None + + # We look for the host VMWare + def is_vmware_esx(self): + # If it's not a virtual machine bail out + if self.mac_vendor != 'VMware': + return False + # If we got all theses ports, we are quite ok for + # a VMWare host + needed_ports = [22, 80, 443, 902, 903, 5989] + for p in needed_ports: + if p not in self.open_ports: + # find one missing port, not a VMWare host + return False + # Ok all ports are found, we are a ESX :) + return True + + # Says if we are a virtual machine or not + def is_vmware_vm(self): + # special case : the esx host itself + if self.is_vmware_esx(): + return False + # Else, look at the mac vendor + return self.mac_vendor == 'VMware' + + + # Fill the different os possibilities + def add_os_possibility(self, os, osgen, accuracy): + self.os_possibilities.append( (os, osgen, accuracy) ) + + + # We search if our potential parent is present in the + # other detected hosts. If so, set it as my parent + def look_for_parent(self, all_hosts): + self.parents = [] + parent = self.parent + debug("Look for my parent %s -> %s" % (self.get_name(), parent)) + # Ok, we didn't find any parent + # we bail out + if parent == '': + return + for h in all_hosts: + debug("Is it you? %s" % h.get_name()) + if h.get_name() == parent: + debug("Houray, we find our parent %s -> %s" % (self.get_name(), h.get_name())) + self.parents.append(h.get_name()) + + + + + # Look at ours oses and see which one is the better + def compute_os(self): + self.os_name = 'Unknown OS' + self.os_version = 'Unknown Version' + + # bailout if we got no os :( + if len(self.os_possibilities) == 0: + return + + max_accuracy = 0 + for (os, osgen, accuracy) in self.os_possibilities: + if accuracy > max_accuracy: + max_accuracy = accuracy + + # now get the entry with the max value + for (os, osgen, accuracy) in self.os_possibilities: + print "Can be", (os, osgen, accuracy) + if accuracy == max_accuracy: + self.os = (os, osgen) + + print "Try to match", self.os + + #Ok, unknown os... not good + if self.os == ('', ''): + return + + map = {('Windows', '2000') : 'windows', + ('Windows', '2003') : 'windows', + ('Windows', '7') : 'windows', + ('Windows', 'XP') : 'windows', + # ME? you are a stupid moron! + ('Windows', 'Me') : 'windows', + ('Windows', '2008') : 'windows', + # that's a good boy :) + ('Linux', '2.6.X') : 'linux', + ('Linux', '2.4.X') : 'linux', + # HPUX? I think you didn't choose... + ('HP-UX', '11.X') : 'hpux', + ('HP-UX', '10.X') : 'hpux', + } + + if self.os not in map: + return + + self.os_name = map[self.os] + self.os_version = self.os[1] +# self.templates.append(t) +# +# # Look for VMWare VM or hosts +# if self.h.is_vmware_vm(): +# self.templates.append('vmware-vm') +# # Now is an host? +# if self.h.is_vmware_esx(): +# self.templates.append('vmware-host') + + + # Return the string of the 'discovery' items + def get_discovery_output(self): + r = [] + r.append('%s::isup=1' % self.get_name()) + r.append(self.get_discovery_system()) + r.append(self.get_discovery_macvendor()) + op = self.get_discovery_ports() + if op != '': + r.append(op) + par = self.get_discovery_parents() + if par != '': + r.append(par) + fqdn = self.get_dicovery_fqdn() + if fqdn != '': + r.append(fqdn) + ip = self.get_discovery_ip() + if ip != '': + r.append(ip) + return r + + + # for system output + def get_discovery_system(self): + r = '%s::os=%s' % (self.get_name(), self.os_name)+'\n' + r += '%s::osversion=%s' % (self.get_name(), self.os_version) + return r + + def get_discovery_macvendor(self): + return '%s::macvendor=%s' % (self.get_name(), self.mac_vendor) + + def get_discovery_ports(self): + if self.open_ports == []: + return '' + return '%s::openports=%s' % (self.get_name(), ','.join([str(p) for p in self.open_ports])) + + def get_discovery_parents(self): + if self.parents == []: + return '' + return '%s::parents=%s' % (self.get_name(), ','.join(self.parents)) + + def get_dicovery_fqdn(self): + if self.host_name == '': + return '' + return '%s::fqdn=%s' % (self.get_name(), self.host_name) + + def get_discovery_ip(self): + if self.ip == '': + return '' + return '%s::ip=%s' % (self.get_name(), self.ip) + + +(_, tmppath) = tempfile.mkstemp() + +print "propose a tmppath", tmppath + +cmd = "sudo nmap %s -T4 -O --traceroute -oX %s" % (' '.join(targets) , tmppath) +print "Launching command,", cmd +try: + nmap_process = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + close_fds=True, shell=True) +except OSError , exp: + print "Debug : Error in launching command:", cmd, exp + sys.exit(2) + +print "Try to communicate" +(stdoutdata, stderrdata) = nmap_process.communicate() + +if nmap_process.returncode != 0: + print "Error : the nmap return an error : '%s'" % stderrdata + sys.exit(2) + +print "Got it", (stdoutdata, stderrdata) + +xml_input = tmppath + +tree = ElementTree() +try: + tree.parse(xml_input) +except IOError, exp: + print "Error opening file '%s' : %s" % (xml_input, exp) + sys.exit(2) + +hosts = tree.findall('host') +debug("Number of hosts : %d" % len(hosts)) + + +all_hosts = [] + +for h in hosts: + # Bypass non up hosts + if not is_up(h): + continue + + dh = DetectedHost() + + # Now we get the ipaddr and the mac vendor + # for future VMWare matching + #print h.__dict__ + addrs = h.findall('address') + for addr in addrs: + #print "Address", addr.__dict__ + addrtype = addr.attrib['addrtype'] + if addrtype == 'ipv4': + dh.ip = addr.attrib['addr'] + if addrtype == "mac": + if 'vendor' in addr.attrib: + dh.mac_vendor = addr.attrib['vendor'] + + + # Now we've got the hostnames + host_names = h.findall('hostnames') + for h_name in host_names: + h_names = h_name.findall('hostname') + for h_n in h_names: + #print 'hname', h_n.__dict__ + #print 'Host name', h_n.attrib['name'] + dh.set_host_name(h_n.attrib['name']) + + + # Now print the traceroute + traces = h.findall('trace') + for trace in traces: + #print trace.__dict__ + hops = trace.findall('hop') + #print "Number of hops", len(hops) + distance = len(hops) + if distance >= 2: + for hop in hops: + ttl = int(hop.attrib['ttl']) + #We search for the direct father + if ttl == distance-1: + #print ttl + #print "Super hop", hop.__dict__ + # Get the host name if possible, if not + # take the IP + if 'host' in hop.attrib: + dh.parent = hop.attrib['host'] + else: + dh.parent = hop.attrib['ipaddr'] + + + # Now the OS detection + ios = h.find('os') + #print os.__dict__ + cls = ios.findall('osclass') + for c in cls: + #print "Class", c.__dict__ + family = c.attrib['osfamily'] + accuracy = c.attrib['accuracy'] + if 'osgen' in c.attrib: + osgen = c.attrib['osgen'] + else: + osgen = None + #print "Type:", family, osgen, accuracy + dh.add_os_possibility(family, osgen, accuracy) + # Ok we can compute our OS now :) + dh.compute_os() + + + # Now the ports :) + allports = h.findall('ports') + for ap in allports: + ports = ap.findall('port') + for p in ports: + #print "Port", p.__dict__ + p_id = p.attrib['portid'] + s = p.find('state') + #print s.__dict__ + state = s.attrib['state'] + if state == 'open': + dh.open_ports.append(int(p_id)) + + #print dh.__dict__ + all_hosts.append(dh) + #print "\n\n" + + + +for h in all_hosts: + name = h.get_name() + if not name: + continue + + debug("Doing name %s" % name) + #path = os.path.join(output_dir, name+'.discover') + #print "Want path", path + #f = open(path, 'wb') + #cPickle.dump(h, f) + #f.close() + debug(str(h.__dict__)) + # And generate the configuration too + h.look_for_parent(all_hosts) + #c.fill_system_conf() + #c.fill_ports_services() + #c.fill_system_services() +# c.write_host_configuration() + #print "Host config", c.get_cfg_for_host() +# c.write_services_configuration() + #print "Service config" + #print c.get_cfg_for_services() + #print c.__dict__ + print '\n'.join(h.get_discovery_output()) + #print "\n\n\n" + + +# Try to remove the temppath +try: + os.unlink(tmppath) +except Exception: + pass + diff --git a/Monitoring/nagios/plugins/notify.sh b/Monitoring/nagios/plugins/notify.sh new file mode 100755 index 00000000..0c88305c --- /dev/null +++ b/Monitoring/nagios/plugins/notify.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +echo "" >> ~/notify.log +echo `date` >> ~/notify.log +echo $* >> ~/notify.log + diff --git a/Monitoring/nagios/plugins/notify_irc b/Monitoring/nagios/plugins/notify_irc new file mode 100755 index 00000000..e1de0866 --- /dev/null +++ b/Monitoring/nagios/plugins/notify_irc @@ -0,0 +1,87 @@ +#! /usr/bin/env python +# +# Example program using irclib.py. +# +# This program is free without restrictions; do anything you like with +# it. +# +# Joel Rosdahl <joel@rosdahl.net> + +import irclib +import sys +#irclib.DEBUG= True +class IRCCat(irclib.SimpleIRCClient): + def __init__(self, target,msg=""): + irclib.SimpleIRCClient.__init__(self) + self.target = target + self.msg = msg + + def on_welcome(self, connection, event): + if irclib.is_channel(self.target): + connection.join(self.target) + else: + self.send_it() + + def on_join(self, connection, event): + self.send_it() + + def on_disconnect(self, connection, event): + sys.exit(0) + + def send_it(self): + if self.msg: + print "writing given argv privmsg",self.msg + self.connection.privmsg(self.target, self.msg) + else: + print "writing stdin privmsg:" + while 1: + line = sys.stdin.readline() + if not line: + break + print line + self.connection.privmsg(self.target, line) + self.connection.quit("Using irclib.py") +def findGreatNick(prefix='shinken'): + import random + import re + dic="/usr/share/dict/danish" + found=False + while not found: + w = random.choice(list(open(dic))) + found = re.match(r"^[a-zA-Z_-]+$",w) + return prefix +"|"+w.strip() + +def main(): + if len(sys.argv) < 3: + print "Usage: notify_irc <server[:port]> <target> [message]" + print "\ntarget is a nickname or a channel." + sys.exit(1) + + s = sys.argv[1].split(":", 1) + server = s[0] + if len(s) == 2: + try: + port = int(s[1]) + except ValueError: + print "Error: Erroneous port." + sys.exit(1) + else: + port = 6667 + import random + nickname = findGreatNick() + print nickname + target = sys.argv[2] + msg = "" + if len(sys.argv) == 4: + msg = sys.argv[3] + c = IRCCat(target,msg) + try: + print "trying to connect to ",server,port,nickname + c.connect(server, port, nickname ) + except irclib.ServerConnectionError, x: + print x + sys.exit(1) + c.start() + +if __name__ == "__main__": + main() diff --git a/Monitoring/nagios/plugins/nsca_client.py b/Monitoring/nagios/plugins/nsca_client.py new file mode 100755 index 00000000..76e551db --- /dev/null +++ b/Monitoring/nagios/plugins/nsca_client.py @@ -0,0 +1,184 @@ +### This is a very quick and dirty code for David so he can work on its sikuli agent +# and report as nsca the results. +# This need to be clean a lot, it's still a server and should be a client class :) +# I can do it after my "new baby holidays" are finished ;) +# J.Gabes + + + +import time +import select +import socket +import struct +import sys +import random + + +def decrypt_xor(data, key): + keylen = len(key) + crypted = [chr(ord(data[i]) ^ ord(key[i % keylen])) for i in xrange(len(data))] + return ''.join(crypted) + + + +#Just print some stuff +class NSCA_client(): + def __init__(self, host, port, encryption_method, password): + self.host = host + self.port = port + self.encryption_method = encryption_method + self.password = password + self.rng = random.Random(password) + + + #Ok, main function that is called in the CONFIGURATION phase + def get_objects(self): + print "[Dummy] ask me for objects to return" + r = {'hosts' : []} + h = {'name' : 'dummy host from dummy arbiter module', + 'register' : '0', + } + + r['hosts'].append(h) + print "[Dummy] Returning to Arbiter the hosts:", r + return r + + def send_init_packet(self, socket): + ''' + Build an init packet + 00-127 : IV + 128-131 : unix timestamp + ''' + iv = ''.join([chr(self.rng.randrange(256)) for i in xrange(128)]) + init_packet = struct.pack("!128sI", iv, int(time.mktime(time.gmtime()))) + socket.send(init_packet) + return iv + + def read_check_result(self, data, iv): + ''' + Read the check result + 00-01 : Version + 02-05 : CRC32 + 06-09 : Timestamp + 10-11 : Return code + 12-75 : hostname + 76-203 : service + 204-715 : output of the plugin + 716-720 : padding + ''' + if len(data) != 720: + return None + + if self.encryption_method == 1: + data = decrypt_xor(data,self.password) + data = decrypt_xor(data,iv) + + (version, pad1, crc32, timestamp, rc, hostname_dirty, service_dirty, output_dirty, pad2) = struct.unpack("!hhIIh64s128s512sh",data) + hostname = hostname_dirty.partition("\0", 1)[0] + service = service_dirty.partition("\0", 1)[0] + output = output_dirty.partition("\0", 1)[0] + return (timestamp, rc, hostname, service, output) + + def post_command(self, timestamp, rc, hostname, service, output): + ''' + Send a check result command to the arbiter + ''' + if len(service) == 0: + extcmd = "[%lu] PROCESS_HOST_CHECK_RESULT;%s;%d;%s\n" % (timestamp,hostname,rc,output) + else: + extcmd = "[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n" % (timestamp,hostname,service,rc,output) + + print "want to send", extcmd + + #e = ExternalCommand(extcmd) + #self.from_q.put(e) + + + # When you are in "external" mode, that is the main loop of your process + def main(self): + #self.set_exit_handler() + self.interrupted = False + backlog = 5 + size = 8192 + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + #server.setblocking(0) + server.connect((self.host, self.port)) + #server.listen(backlog) + input = [server] + databuffer = {} + IVs = {} + + init = server.recv(size) + print "got init", init + + #init_packet = struct.pack("!128sI",iv,int(time.mktime(time.gmtime()))) + (iv, t) = struct.unpack("!128sI",init) + print "IV", iv + print "T", t + + version = 0 + pad1 = 0 + crc32= 0 + timestamp = int(time.time()) + rc = 2 + hostname_dirty = "moncul" + service_dirty = "fonctionnne" + output_dirty = "blablalba" + pad2=0 + ''' + Read the check result + 00-01 : Version + 02-05 : CRC32 + 06-09 : Timestamp + 10-11 : Return code + 12-75 : hostname + 76-203 : service + 204-715 : output of the plugin + 716-720 : padding + ''' + init_packet = struct.pack("!hhIIh64s128s512sh", version, pad1, crc32, timestamp, rc, hostname_dirty, service_dirty, output_dirty, pad2) + print "Create packent len", len(init_packet) + #(version, pad1, crc32, timestamp, rc, hostname_dirty, service_dirty, output_dirty, pad2) = struct.unpack("!hhIIh64s128s512sh",data) + + data = decrypt_xor(init_packet,iv) + data = decrypt_xor(data,self.password) + + + server.send(data) + sys.exit(0) + + while not self.interrupted: + print "Loop" + inputready,outputready,exceptready = select.select(input,[],[], 1) + + for s in inputready: + if s == server: + # handle the server socket + #client, address = server.accept() + iv = self.send_init_packet(client) + IVs[client] = iv + input.append(client) + else: + # handle all other sockets + data = s.recv(size) + if s in databuffer: + databuffer[s] += data + else: + databuffer[s] = data + if len(databuffer[s]) == 720: + # end-of-transmission or an empty line was received + (timestamp, rc, hostname, service, output)=self.read_check_result(databuffer[s],IVs[s]) + del databuffer[s] + del IVs[s] + self.post_command(timestamp,rc,hostname,service,output) + try: + s.shutdown(2) + except Exception , exp: + print exp + s.close() + input.remove(s) + + + +nsca = NSCA_client('localhost', 5667, 1, 'toto') +nsca.main() diff --git a/Monitoring/nagios/plugins/sendmailhost.pl b/Monitoring/nagios/plugins/sendmailhost.pl new file mode 100755 index 00000000..51e85670 --- /dev/null +++ b/Monitoring/nagios/plugins/sendmailhost.pl @@ -0,0 +1,96 @@ +#!/usr/bin/perl +use MIME::QuotedPrint; +use HTML::Entities; +use Mail::Sendmail 0.75; # doesn't work with v. 0.74! + +$NOTIFICATIONTYPE=$ARGV[0]; +$HOSTNAME=$ARGV[1]; +$HOSTSTATE=$ARGV[2]; +$HOSTADDRESS=$ARGV[3]; +$HOSTOUTPUT=$ARGV[4]; +$SHORTDATETIME=$ARGV[5]; +$TO=$ARGV[6]; +#$HOSTNAME=$ARGV[7]; +#$DOWNTIME=$ARGV[8]; + +$boundary = "====" . time() . "===="; + +$text = "***** Notification Shinken *****\n\n" + . "Notification : $NOTIFICATIONTYPE\n\n" + . "Host : $HOSTNAME\n\n" + . "Address : $HOSTADDRESS\n" + . "State : $HOSTSTATE\n\n" + . "Date/Time : $SHORTDATETIME\n\n" + . "Host output : $HOSTOUTPUT"; + +$texthtml = " <center><table border='11><th><strong>***** Notification Shinken *****</strong></th></table></center>\n"; + +$color="blue"; +if ($NOTIFICATIONTYPE =~ /RECOVERY/) { + $color="#339933"; +} +if ($NOTIFICATIONTYPE =~ /PROBLEM/) { + $color="#FF0000"; +} + +$HOSTOUTPUT =~ s/=/=/g; + +$texthtml = $texthtml . "<strong>Notification type : <span style='ccolor:$color> $NOTIFICATIONTYPE </span></strong>\n\n"; + +if ($DOWNTIME != 0) { + $color="#3333FF"; + $texthtml = $texthtml . "<strong><i><span style='ccolor:$color>This device is actually in maintenance.</span></i></strong>\n\n"; +} + +if ($HOSTSTATE =~ /DOWN/) { + $color="#FF0000"; +} +if ($HOSTSTATE =~ /UP/) { + $color="#339933"; +} +if ($HOSTSTATE =~ /UNREACHABLE/) { + $color="#00CCCC"; +} + +$texthtml = $texthtml . "<strong>Impacted host</strong> : $HOSTNAME\n" + . "<strong>Address</strong> : <i>$HOSTADDRESS</i> \n" + . "<strong>Host State : <span style='ccolor:$color> $HOSTSTATE </span></strong>\n" + . "<strong>Date/Time</strong> : <i>$SHORTDATETIME</i> \n\n" + . "<strong>Host Output</strong> : $HOSTOUTPUT \n\n\n\n"; + + +%mail = ( + from => 'Monitoring Agent <monitor-agent@invaliddomain.org>', + to => $TO, + subject => "$HOSTNAME is $HOSTSTATE !", + 'content-type' => "multipart/alternative; boundary=\"$boundary\"", + 'Auto-Submitted' => "auto-generated" + ); + +$plain = encode_qp $text; + +#$html = encode_entities($texthtml); +$html = $texthtml; +$html =~ s/\n\n/\n\n<p>/g; +$html =~ s/\n/<br>\n/g; +$html = "<p>" . $html . "</p>"; + +$boundary = '--'.$boundary; + +$mail{body} = <<END_OF_BODY; +$boundary +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: quoted-printable + +$plain + +$boundary +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: quoted-printable + +<html>$html</html> +$boundary-- +END_OF_BODY + +sendmail(%mail) || print "Error: $Mail::Sendmail::error\n"; + diff --git a/Monitoring/nagios/plugins/sendmailservices.pl b/Monitoring/nagios/plugins/sendmailservices.pl new file mode 100755 index 00000000..ab5464cf --- /dev/null +++ b/Monitoring/nagios/plugins/sendmailservices.pl @@ -0,0 +1,105 @@ +#!/usr/bin/perl +use MIME::QuotedPrint; +use HTML::Entities; +use Mail::Sendmail 0.75; # doesn't work with v. 0.74! + +$NOTIFICATIONTYPE=$ARGV[0]; +$SERVICEDESC=$ARGV[1]; +$HOSTNAME=$ARGV[2]; +$HOSTADDRESS=$ARGV[3]; +$SERVICESTATE=$ARGV[4]; +$SHORTDATETIME=$ARGV[5]; +$SERVICEOUTPUT=$ARGV[6]; +$TO=$ARGV[7]; +#$HOSTNAME=$ARGV[8]; + +$boundary = "====" . time() . "===="; + +$text = "***** Notification Shinken *****\n\n" + . "Notification : $NOTIFICATIONTYPE\n\n" + . "Impacted service : $SERVICEDESC\n" + . "State : $SERVICESTATE\n\n" + . "Related host : $HOSTNAME\n" + . "Address : $HOSTADDRESS\n" + . "Date/Time : $SHORTDATETIME\n\n" + . "Service output : $SERVICEOUTPUT"; + +$texthtml = " <center><table border='11><th><strong>***** Shinken Notification *****</strong></th></table></center>\n"; + +$color="blue"; +$colorstate="black"; + +if ($NOTIFICATIONTYPE =~ /RECOVERY/ | $NOTIFICATIONTYPE =~ ACKNOWLEDGEMENT) { + $color="#339933"; + if ($SERVICESTATE =~ /OK/){ + $colorstate="#339933"; + } +} + +if ($NOTIFICATIONTYPE =~ /PROBLEM/) { + $color="#FF0000"; + + if ($SERVICESTATE =~ /CRITICAL/) { + $colorstate="#FF0000"; + } + if ($SERVICESTATE =~ /WARNING/) { + $colorstate="#FF9900"; + } + if ($SERVICESTATE =~ /UNKNOWN/) { + $colorstate="#999999"; + } +} + +$SERVICEOUTPUT =~ s/=/=/g; + +if ($NOTIFICATIONTYPE =~ /RECOVERY/){ + if ($SERVICESTATE =~ /OK/){ + $colorstate="#339933"; + } +} + +$texthtml = $texthtml . "<strong>Notification : <span style='ccolor:$color>$NOTIFICATIONTYPE</span></strong>\n\n" + . "<strong>Impacted service : <i>$SERVICEDESC</i></strong>\n" + . "<strong>State : <span style='ccolor:$colorstate>$SERVICESTATE</span></strong>\n\n"; + +$texthtml = $texthtml . "<strong>Host</strong> : $HOSTNAME\n" + . "<strong>Address</strong> : <i>$HOSTADDRESS</i>\n" + . "<strong>Date/Time</strong> : <i>$SHORTDATETIME</i>\n\n" + . "<strong>Service output</strong> : $SERVICEOUTPUT\n\n\n\n"; + +%mail = ( + from => 'Monitoring Agent <monitor-agent@invaliddomain.org>', + to => $TO, + subject => "$SERVICEDESC $SERVICESTATE on $HOSTNAME", + 'content-type' => "multipart/alternative; boundary=\"$boundary\"", + 'Auto-Submitted' => "auto-generated" + ); + +$plain = encode_qp $text; + +#$html = encode_entities($texthtml); +$html = $texthtml; +$html =~ s/\n\n/\n\n<p>/g; +$html =~ s/\n/<br>\n/g; +$html = "<p>" . $html . "</p>"; + +$boundary = '--'.$boundary; + + +$mail{body} = <<END_OF_BODY; +$boundary +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: quoted-printable + +$plain + +$boundary +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: quoted-printable + +<html>$html</html> +$boundary-- +END_OF_BODY + +sendmail(%mail) || print "Error: $Mail::Sendmail::error\n"; + diff --git a/Monitoring/nagios/plugins/urlize b/Monitoring/nagios/plugins/urlize Binary files differnew file mode 100755 index 00000000..119be020 --- /dev/null +++ b/Monitoring/nagios/plugins/urlize diff --git a/Monitoring/nagios/plugins/utils.pm b/Monitoring/nagios/plugins/utils.pm new file mode 100644 index 00000000..676a06fe --- /dev/null +++ b/Monitoring/nagios/plugins/utils.pm @@ -0,0 +1,67 @@ +# Utility drawer for Nagios plugins. +# +# This will be deprecated soon. Please use Nagios::Plugin from CPAN +# for new plugins + +package utils; + +require Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw($TIMEOUT %ERRORS &print_revision &support &usage); + +#use strict; +#use vars($TIMEOUT %ERRORS); +sub print_revision ($$); +sub usage; +sub support(); +sub is_hostname; + +## updated by autoconf +$PATH_TO_RPCINFO = "/usr/bin/rpcinfo" ; +$PATH_TO_LMSTAT = "" ; +$PATH_TO_SMBCLIENT = "/usr/bin/smbclient" ; +$PATH_TO_MAILQ = "/usr/bin/mailq"; +$PATH_TO_QMAIL_QSTAT = ""; + +## common variables +$TIMEOUT = 15; +%ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + +## utility subroutines +sub print_revision ($$) { + my $commandName = shift; + my $pluginRevision = shift; + print "$commandName v$pluginRevision (nagios-plugins 1.4.15)\n"; + print "The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\ncopies of the plugins under the terms of the GNU General Public License.\nFor more information about these matters, see the file named COPYING.\n"; +} + +sub support () { + my $support='Send email to nagios-users@lists.sourceforge.net if you have questions\nregarding use of this software. To submit patches or suggest improvements,\nsend email to nagiosplug-devel@lists.sourceforge.net.\nPlease include version information with all correspondence (when possible,\nuse output from the --version option of the plugin itself).\n'; + $support =~ s/@/\@/g; + $support =~ s/\\n/\n/g; + print $support; +} + +sub usage { + my $format=shift; + printf($format,@_); + exit $ERRORS{'UNKNOWN'}; +} + +sub is_hostname { + my $host1 = shift; + return 0 unless defined $host1; + if ($host1 =~ m/^[\d\.]+$/ && $host1 !~ /\.$/) { + if ($host1 =~ m/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { + return 1; + } else { + return 0; + } + } elsif ($host1 =~ m/^[a-zA-Z0-9][-a-zA-Z0-9]*(\.[a-zA-Z0-9][-a-zA-Z0-9]*)*\.?$/) { + return 1; + } else { + return 0; + } +} + +1; diff --git a/Monitoring/nagios/plugins/utils.sh b/Monitoring/nagios/plugins/utils.sh new file mode 100755 index 00000000..299a5e52 --- /dev/null +++ b/Monitoring/nagios/plugins/utils.sh @@ -0,0 +1,23 @@ +#! /bin/sh + +STATE_OK=0 +STATE_WARNING=1 +STATE_CRITICAL=2 +STATE_UNKNOWN=3 +STATE_DEPENDENT=4 + +if test -x /usr/bin/printf; then + ECHO=/usr/bin/printf +else + ECHO=echo +fi + +print_revision() { + echo "$1 v$2 (nagios-plugins 1.4.15)" + $ECHO "The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\ncopies of the plugins under the terms of the GNU General Public License.\nFor more information about these matters, see the file named COPYING.\n" | sed -e 's/\n/ /g' +} + +support() { + $ECHO "Send email to nagios-users@lists.sourceforge.net if you have questions\nregarding use of this software. To submit patches or suggest improvements,\nsend email to nagiosplug-devel@lists.sourceforge.net.\nPlease include version information with all correspondence (when possible,\nuse output from the --version option of the plugin itself).\n" | sed -e 's/\n/ /g' +} + diff --git a/Monitoring/nagios/plugins/vmware_discovery_runner.py b/Monitoring/nagios/plugins/vmware_discovery_runner.py new file mode 100755 index 00000000..3a17c765 --- /dev/null +++ b/Monitoring/nagios/plugins/vmware_discovery_runner.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python +#Copyright (C) 2009-2010 : +# Gabes Jean, naparuba@gmail.com +# Gerhard Lausser, Gerhard.Lausser@consol.de +# Gregory Starck, g.starck@gmail.com +# Hartmut Goebel <h.goebel@goebel-consult.de> +# +#This file is part of Shinken. +# +#Shinken is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#Shinken is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU Affero General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with Shinken. If not, see <http://www.gnu.org/licenses/>. + +import os +import sys +import shlex +import shutil +import optparse +from subprocess import Popen, PIPE + +# Try to load json (2.5 and higer) or simplejson if failed (python2.4) +try: + import json +except ImportError: + # For old Python version, load + # simple json (it can be hard json?! It's 2 functions guy!) + try: + import simplejson as json + except ImportError: + sys.exit("Error : you need the json or simplejson module for this script") + +VERSION = '0.1' + +# Search if we can findthe check_esx3.pl file somewhere +def search_for_check_esx3(): + me = os.path.abspath( __file__ ) + my_dir = os.path.dirname(me) + possible_paths = [os.path.join(my_dir, 'check_esx3.pl'), + '/var/lib/nagios/check_esx3.pl', + '/var/lib/plugins/nagios/check_esx3.pl', + '/var/lib/shinken/check_esx3.pl', + '/usr/local/nagios/libexec/check_esx3.pl', + '/usr/local/shinken/libexec/check_esx3.pl', + 'c:\\shinken\\libexec\\check_esx3.pl'] + + for p in possible_paths: + print "Look for", p + if os.path.exists(p): + print "Found a check_esx3.pl at", p + return p + return None + + +# Split and clean the rules from a string to a list +def _split_rules(rules): + return [r.strip() for r in rules.split('|')] + +# Apply all rules on the objects names +def _apply_rules(name, rules): + if 'nofqdn' in rules: + name = name.split('.', 1)[0] + if 'lower' in rules: + name = name.lower() + return name + +# Get all vmware hosts from a VCenter and return the list +def get_vmware_hosts(check_esx_path, vcenter, user, password): + list_host_cmd = [check_esx_path, '-D', vcenter, '-u', user, '-p', password, + '-l', 'runtime', '-s', 'listhost'] + + print "Got host list" + print ' '.join(list_host_cmd) + p = Popen(list_host_cmd, stdout=PIPE, stderr=PIPE) + output = p.communicate() + + print "Exit status", p.returncode + if p.returncode == 2: + print "Error : the check_esx3.pl return in error :", output + sys.exit(2) + + parts = output[0].split(':') + hsts_raw = parts[1].split('|')[0] + hsts_raw_lst = hsts_raw.split(',') + + hosts = [] + for hst_raw in hsts_raw_lst: + hst_raw = hst_raw.strip() + # look as server4.mydomain(UP) + elts = hst_raw.split('(') + hst = elts[0] + hosts.append(hst) + + return hosts + + +# For a specific host, ask all VM on it to the VCenter +def get_vm_of_host(check_esx_path, vcenter, host, user, password): + print "Listing host", host + list_vm_cmd = [check_esx_path, '-D', vcenter, '-H', host, + '-u', user, '-p', password, + '-l', 'runtime', '-s', 'list'] + print ' '.join(list_vm_cmd) + p = Popen(list_vm_cmd, stdout=PIPE) + output = p.communicate() + + print "Exit status", p.returncode + if p.returncode == 2: + print "Error : the check_esx3.pl return in error :", output + sys.exit(2) + + parts = output[0].split(':') + # Maybe we got a 'CRITICAL - There are no VMs.' message, + # if so, we bypass this host + if len(parts) < 2: + return None + + vms_raw = parts[1].split('|')[0] + vms_raw_lst = vms_raw.split(',') + + lst = [] + for vm_raw in vms_raw_lst: + vm_raw = vm_raw.strip() + # look as MYVM(UP) + elts = vm_raw.split('(') + vm = elts[0] + lst.append(vm) + return lst + + +# Create all tuples of the links for the hosts +def print_all_links(res, rules): + r = [] + for host in res: + host_name = _apply_rules(host, rules) + print "%s::isesxhost=1" % host_name + for vm in res[host]: + # First we apply rules on the names + vm_name = _apply_rules(vm, rules) + #v = (('host', host_name),('host', vm_name)) + print "%s::isesxvm=1" % vm_name + print "%s::esxhost=%s" % (vm_name, host_name) + #r.append(v) + return r + + +def write_output(r, path): + try: + f = open(path+'.tmp', 'wb') + buf = json.dumps(r) + f.write(buf) + f.close() + shutil.move(path+'.tmp', path) + print "File %s wrote" % path + except IOError, exp: + sys.exit("Error writing the file %s : %s" % (path, exp)) + + +def main(check_esx_path, vcenter, user, password, rules): + rules = _split_rules(rules) + res = {} + hosts = get_vmware_hosts(check_esx_path, vcenter, user, password) + + for host in hosts: + lst = get_vm_of_host(check_esx_path, vcenter, host, user, password) + if lst: + res[host] = lst + + + print_all_links(res, rules) + + #write_output(r, output) + print "Finished!" + + +# Here we go! +if __name__ == "__main__": + # Manage the options + parser = optparse.OptionParser( + version="Shinken VMware links dumping script version %s" % VERSION) + parser.add_option("-x", "--esx3-path", dest='check_esx_path', + default='/usr/local/nagios/libexec/check_esx3.pl', + help="Full path of the check_esx3.pl script (default: %default)") + parser.add_option("-V", "--vcenter", '--Vcenter', + help="tThe IP/DNS address of your Vcenter host.") + parser.add_option("-u", "--user", + help="User name to connect to this Vcenter") + parser.add_option("-p", "--password", + help="The password of this user") + parser.add_option('-r', '--rules', default='', + help="Rules of name transformation. Valid names are: " + "`lower`: to lower names, " + "`nofqdn`: keep only the first name (server.mydomain.com -> server)." + "You can use several rules like `lower|nofqdn`") + + opts, args = parser.parse_args() + if args: + parser.error("does not take any positional arguments") + + if opts.vcenter is None: + parser.error("missing -V or --Vcenter option for the vcenter IP/DNS address") + if opts.user is None: + parser.error("missing -u or --user option for the vcenter username") + if opts.password is None: + error = True + parser.error("missing -p or --password option for the vcenter password") + if not os.path.exists(opts.check_esx_path): + parser.error("the path %s for the check_esx3.pl script is wrong, missing file" % opts.check_esx_path) + else: + # Not given, try to find one + p = search_for_check_esx3() + if p is None: + parser.error("Sorry, I cannot find check_esx3.pl, please specify it with -x") + #else set it :) + opts.check_esx_path = p + + main(**opts.__dict__) |
