Code

more contribs
authorSubhendu Ghosh <sghosh@users.sourceforge.net>
Sun, 9 Feb 2003 14:16:29 +0000 (14:16 +0000)
committerSubhendu Ghosh <sghosh@users.sourceforge.net>
Sun, 9 Feb 2003 14:16:29 +0000 (14:16 +0000)
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@300 f882894a-f735-0410-b71e-b25c423dba1c

contrib/check_remote_nagios_status.pl [new file with mode: 0644]
contrib/check_wins.pl [new file with mode: 0755]
contrib/sched_downtime.pl [new file with mode: 0644]

diff --git a/contrib/check_remote_nagios_status.pl b/contrib/check_remote_nagios_status.pl
new file mode 100644 (file)
index 0000000..dc99705
--- /dev/null
@@ -0,0 +1,666 @@
+#!/usr/bin/perl -w
+
+# check_status.pl Nagios Plugin - Version 1.3
+# Last Updated: 1/9/2003
+#
+# Report any bugs/questions to Russell Scibetti at russell@quadrix.com
+#
+# check_status Change Log:
+#
+# To do for 1.4
+# - Better help and documentation (separate doc?)
+# - Take argument (patterns to match) from a separate spec file
+#
+# New Addition to 1.3
+# - Added ChangeLog information and updated --help output
+# - hostdown (hd) argument for how a service check should respond
+#   when its host is Down/Unreachable
+#   (--hostdown="ok|warning|critical|unknown")
+# - Changed name from check_state to check_status
+# - Set hostdown to default to OK when the argument isn't specified
+# - Number of Hosts checked is now output in OK result
+#
+# Version 1.2 additions:
+#
+# - Added ability to handle ack'd and downtimed services differently 
+#   depending on argument provided 
+#   (--ack="ok|warning|critical|unknown|down|unreachable" 
+#    --dt="ok|warning|critical|unknown|down|unreachable")
+#
+# Version 1.1 additions:
+#
+# - Added --host=<regex>, --servhost=<regex> to allow for specific field
+#   matching (host for matching hostname in host checks, servhost for
+#   matching the hostname in service checks, service for matching the 
+#   service name in service checks)
+# - Output the number of OK services for an OK output
+#
+# Version 1.0 features:
+#
+# - Freshness check of status.log (timestamp) 
+# - Match service or host checks
+# - Can ignore acknowledged or downtimes services/hosts (--ack, --dt)
+# - Can output different levels of detail dependent on # of problems
+# - Can check for number of critical, warning, or unknowns
+#
+#############################################################
+
+use Getopt::Long;
+use File::stat;
+
+Getopt::Long::Configure('bundling');
+
+GetOptions
+        ("V"   => \$version,   "version"       => \$version,
+         "h"   => \$help,      "help"          => \$help,
+        "v"   => \$verbose,    "verbose"       => \$verbose,
+         "w=s" => \$warning,   "warning=s"     => \$warning,
+         "c=s" => \$critical,  "critical=s"    => \$critical,
+        "u=s" => \$unknown,    "unknown=s"     => \$unknown,
+        "p=s" => \$pattern,    "pattern=s"     => \$pattern,
+        "S:s" => \$service,    "service:s"     => \$service,
+        "s=s" => \$status,     "status=s"      => \$status,
+        "d=s" => \$dir,        "dir=s"         => \$dir,
+        "D=s" => \$details,    "details=s"     => \$details,
+        "H:s" => \$host,       "host:s"        => \$host,
+         "f=s" => \$freshness,  "freshness=s"   => \$freshness,
+                               "servhost=s"    => \$servhost,
+        "a:s" => \$ack,        "ack:s"         => \$ack,
+        "dt:s"=> \$dt,         "downtime:s"    => \$dt,
+        "hd:s"=> \$hdown,      "hostdown:s"    => \$hdown,
+                               "ok"            => \$ok);
+
+#Constants:
+my $OK       = 0;
+my $WARNING  = 1;
+my $CRITICAL = 2;
+my $UNKNOWN  = 3;
+
+my $crit="CRITICAL";
+my $warn="WARNING";
+my $unk="UNKNOWN";
+my $down="DOWN";
+my $unreach="UNREACHABLE";
+
+# Print out Help information
+if ($help) {
+  printVersion();
+  printHelp();
+  exitcheck($UNKNOWN);
+}
+
+# Print out version information
+if ($version) {
+  printVersion();
+  exitcheck($UNKNOWN);
+}
+
+# Check for status log or directory argument or print usage
+if (!$status) {
+  if (!$dir) {
+    print "Usage: $0 -s <status file> | -d <Nagios log dir>\n";
+    print "Use the --help option for full list of arguments\n";
+    exitcheck($UNKNOWN);
+  }
+  elsif ($dir =~ m#[^/]/$#) {
+    $status = $dir . "status.log";
+  }
+  else {
+    $status = $dir . "/status.log";
+  }
+}
+
+if (defined $host) {
+  if (!$host) {
+    $host="[^\\s]*";
+  }
+}
+
+if (!$host && !$servhost) {
+  $servhost="[^\\s]*";
+}
+
+if (!$host && !$service) {
+  $service="[^\\s]*";
+}
+
+if (defined $ack) {
+  if (!$ack) {
+    $ack="ok";
+  }
+  elsif (!($ack =~ "ok|critical|warning|unknown|down|unreachable")) {
+    print "Invalid value for ack\n";
+    exitcheck($UNKNOWN);
+  }
+}
+
+if (defined $dt) {
+  if (!$dt) {
+    $dt="ok";
+  }
+  elsif (!($dt =~ "ok|critical|warning|unknown|down|unreachable")) {
+    print "Invalid value for dt\n";
+    exitcheck($UNKNOWN);
+  }
+}
+
+if (defined $hdown) {
+  if (!$hdown) {
+    $hdown="ok";
+  }
+  elsif (!($hdown =~ "ok|critical|warning|unknown|down|unreachable")) {
+    print "Invalid value for hostdown\n";
+    exitcheck($UNKNOWN);
+  }
+}
+
+my $much_details = 0;
+
+my $ServiceNotOK = "CRITICAL|WARNING|UNKNOWN";
+my $HostNotOK   = "DOWN|UNREACHABLE";
+
+my %numprob = ("WARNING",0,"CRITICAL",0,"UNKNOWN",0,"DOWN",0,"UNREACHABLE",0);
+
+my $CritOnly = 0;
+my $WarnOnly = 0;
+my $UnkOnly  = 0;
+
+my @wlev;
+my @clev;
+my @ulev;
+my %warnlevel = ("WARNING",0,"CRITICAL",0,"UNKNOWN",0);
+my %critlevel = ("WARNING",0,"CRITICAL",0,"UNKNOWN",0);
+my %unklevel = ("WARNING",0,"CRITICAL",0,"UNKNOWN",0);
+my %hostlevel = ("DOWN",0,"UNREACHABLE",0);
+
+# Store Hosts in downtime
+my @hostdowntime;
+my $numdowntime = 0;
+
+# Store Hosts in a Down/Unreachable state
+my @hostdown;
+my $numdown = 0;
+
+# Hash for storing state-change to OK times for hosts:
+my %hostoktimes;
+
+# Number of matches in parsing
+my $nummatch = 0;
+
+if ($warning) {
+  if ($warning =~ /,/) {
+    @wlev = split /,/,$warning;
+    $warnlevel{"WARNING"} = $wlev[0];
+    $warnlevel{"CRITICAL"} = $wlev[1];
+    if ($wlev[2] ) {
+      $warnlevel{"UNKNOWN"} = $wlev[2];
+    }
+  }
+  else {
+    $WarnOnly = $warning;
+  }
+}
+else {
+  $WarnOnly = 1;
+}
+
+if ($critical) {
+  if ($critical =~ /,/) {
+    @clev = split /,/,$critical;
+    $critlevel{"WARNING"} = $clev[0];
+    $critlevel{"CRITICAL"} = $clev[1];
+    if ($clev[2] ) {
+      $critlevel{"UNKNOWN"} = $clev[2];
+    }
+  }
+  else {
+    $CritOnly = $critical;
+  }
+}
+else {
+  $CritOnly = 1;
+}
+  
+if ($unknown) {
+  if ($unknown =~ /,/) {
+    @ulev = split /,/,$unknown;
+    $unklevel{"WARNING"} = $ulev[0];
+    $unklevel{"CRITICAL"} = $ulev[1];
+    if ($ulev[2] ) {
+      $unklevel{"UNKNOWN"} = $ulev[2];
+    }
+  }
+  else {
+    $UnkOnly = $unknown;
+  }
+}
+else {
+  $UnkOnly = 1;
+}
+
+
+if (!$freshness) {
+  $freshness = 30 * 60;
+}
+else {
+  $freshness = $freshness * 60;
+}
+
+my %ct = ("CRITICAL",0,"WARNING",0,"UNKNOWN",0,"DOWN",0,"UNREACHABLE",0);
+my %much_ct = ("CRITICAL",0,"WARNING",0,"UNKNOWN",0,"DOWN",0,"UNREACHABLE",0);
+
+my %output = ("CRITICAL","","WARNING","","UNKNOWN","","DOWN","","UNREACHABLE","");
+my %much_output = ("CRITICAL","","WARNING","","UNKNOWN","","DOWN","","UNREACHABLE","");
+
+if ($details) {
+  if ($details =~ /,/) {
+    my @tempv = split /,/,$details;
+    $much_details = $tempv[0];
+    $details = $tempv[1]; 
+  }
+}
+
+open("sta","$status") || die "Cannot open status file $status!";
+
+$curr_time = time;
+$file_time = stat($status)->mtime;
+
+if ($curr_time - $file_time > $freshness) {
+  printf "State CRITICAL - Status file is stale!!!\n";
+  exitcheck($CRITICAL);
+}
+
+while(<sta>) {
+  chomp;
+  if (/^[^\s]+[\s]+HOST;/) {
+    @hdata = split /;/,$_;
+    
+# If you care about matching hosts (not services):
+    if ($host && $hdata[1] =~ /$host/) {
+      $nummatch++;
+      if ( $hdata[2] =~ /$HostNotOK/ ) {
+        addproblem($_,$hdata[2]);
+      }
+    }
+
+# If you are matching services, gather host information:
+    else {
+      if ( $hdata[2] =~ /$HostNotOK/ ) {
+       $hostdown[$numdown] = $hdata[1];
+       $numdown++;
+      }
+      else {
+       $hostoktimes{$hdata[1]} = $hdata[4];
+      }
+      if ( $hdata[17] ne "0" ) {
+       $hostdowntime[$numdowntime] = $hdata[1];
+       $numdowntime++;
+      }
+    }
+  }
+  elsif (!$host && /^[^\s]+[\s]+SERVICE;/) {
+    @servdata = split /;/,$_;
+    if ( ( $pattern                     && ($_ =~ /$pattern/)) ||
+        (($servdata[1] =~ /$servhost/) && ($servdata[2] =~ /$service/)) ){
+      $nummatch++;
+      if (($servdata[5] eq "HARD") && ($servdata[3] =~ /$ServiceNotOK/)) {
+        addproblem($_,$servdata[3]);
+      }
+    }
+  }
+}
+
+close("sta");
+
+if ($nummatch==0) {
+  print "Nothing Matches your criteria!\n";
+  exitcheck($UNKNOWN);
+}
+
+# Count the number of problems (for reference):
+if ($host) {
+  $total = $numprob{"DOWN"} + $numprob{"UNREACHABLE"};
+} 
+else {
+  $total = $numprob{"WARNING"} + $numprob{"CRITICAL"} +  $numprob{"UNKNOWN"};
+}
+
+my $numok = $nummatch - $total;
+
+# If this is a host state check:
+if ($host) {
+  if ($numprob{"DOWN"}>0 || $numprob{"UNREACHABLE"}>0 ) {
+    if  ($details && ($total <= $details)) {
+      print "State CRITICAL - $total Host Problems: $output{$down} $output{$unreach}\n";
+      exitcheck($CRITICAL);
+    }
+    else {
+      print "State CRITICAL - $numprob{$down} Hosts Down, $numprob{$unreach} Hosts Unreachable\n";
+      exitcheck($CRITICAL);
+    }
+  }
+  else {
+    print "State OK - $numok Hosts Up, $total Problems\n";
+    exitcheck($OK);
+  }
+}
+
+#If you only defined a Critical level in terms of # of criticals...
+elsif ($CritOnly && ($numprob{"CRITICAL"} >= $CritOnly)) {
+  countAndPrint($crit,$numprob{$crit},0);
+  exitcheck($CRITICAL);
+}    
+
+#Critical in terms on # criticals and # warnings...
+elsif (!$CritOnly && ($numprob{"WARNING"}  >= $critlevel{"WARNING"}  || 
+                     $numprob{"CRITICAL"} >= $critlevel{"CRITICAL"} ||
+                     $numprob{"UNKNOWN"}  >= $critlevel{"UNKNOWN"} )) {
+  countAndPrint($crit,$total,1);
+  exitcheck($CRITICAL);
+}
+
+#Warning in terms of # warnings only...
+elsif ($WarnOnly && ($numprob{"WARNING"} >= $WarnOnly)) {
+  countAndPrint($warn,$numprob{$warn},0);
+  exitcheck($WARNING);
+}
+
+#Warning in terms of # warnings and # criticals...
+elsif (!$WarnOnly && ($numprob{"WARNING"}  >= $warnlevel{"WARNING"} || 
+                     $numprob{"CRITICAL"} >= $warnlevel{"CRITICAL"} ||
+                     $numprob{"UNKNOWN"}  >= $warnlevel{"UNKNOWN"})) {
+  countAndPrint($warn,$total,1);
+  exitcheck($WARNING);
+}
+
+#Unknown in terms on # unknown only...
+elsif ( $UnkOnly && ($numprob{"UNKNOWN"}>=$UnkOnly) ) {
+  countAndPrint($unk,$numprob{$unk},0);
+  exitcheck($UNKNOWN);
+}
+
+#Unknown in terms of # warning, critical, and unknown...
+elsif (!$UnkOnly && ($numprob{"WARNING"}  >= $unklevel{"WARNING"} ||
+                     $numprob{"CRITICAL"} >= $unklevel{"CRITICAL"} ||
+                     $numprob{"UNKNOWN"}  >= $unklevel{"UNKNOWN"})) {
+  countAndPrint($unk,$total,1);
+  exitcheck($UNKNOWN);
+}
+
+# Everything is OK!
+else {
+  print "State OK -  $numok OK, $total problems\n";
+  exitcheck($OK);
+}
+
+
+
+############################
+# Subroutines
+############################
+
+# Return the proper exit code for Critical, Warning, Unknown, or OK
+sub exitcheck {
+  if ($ok) {
+    exit 0;
+  }
+  else {
+    exit $_[0];
+  }
+} 
+
+# Decide what to print for services:
+sub countAndPrint {
+  my $state = $_[0];
+  my $count = $_[1];
+  my $alltypes = $_[2];
+  my $output = "State $state - ";
+
+  if ($details) {
+    if ($count<=$much_details) {
+      if ($alltypes) {
+        $output .= "$count problems: $much_output{$crit} $much_output{$warn} $much_output{$unk}";
+      }
+      else {
+        $output .= "$count \L$state\E: $much_output{$state}";
+      }
+    }
+    elsif ($count<=$details) {
+      if ($alltypes) {
+        $output .= "$count problems: $output{$crit} $output{$warn} $output{$unk}";
+      }
+      else {
+        $output .= "$count \L$state\E: $output{$state}";
+      }
+    }
+    else {
+      if ($alltypes) {
+        $output .= "$numprob{$crit} critical, $numprob{$warn} warning, $numprob{$unk} unknown";
+      }
+      else {
+        $output .= "$count \L$state\E"; 
+      }
+    }
+  }
+  else {
+    $output .= "$count problems";
+  }
+
+  print "$output\n";
+}
+  
+
+# Add-in the problem found in the status log
+sub addproblem {
+
+  $test = 1;
+  $type = $_[1];
+  my $diffout = "";
+
+  my @values = split /;/,$_[0];
+
+  if (!$host) {
+    my $namehold = $values[1];
+    if ($ack && ($values[13] eq "1")) {
+      if ($ack =~ "ok") {
+        $test = 0;
+      }
+      else {
+        $type = "\U$ack";
+      }
+    }
+    elsif ($hdown && grep /$namehold/, @hostdown) {
+      if ($hdown =~ "ok") {
+        $test = 0;
+      }
+      else {
+        $type = "\U$hdown";
+       $diffout = "$values[1] is down";
+      }
+    }
+    elsif ($dt && (($values[27] ne "0") || (grep /$namehold/, @hostdowntime))){
+      if ($dt =~ "ok") {
+        $test = 0;
+      }
+      else {
+        $type = "\U$dt";
+      }
+    }
+    elsif (exists $hostoktimes{$namehold}) {
+      # If the state change time of the host is more recent than the last
+      # service check, must wait until the next service check runs!
+      if ($hostoktimes{$namehold} > $values[6]) {
+       $test = 0;
+      }
+    }
+  }
+  else {
+    if ($ack && $values[5]) { 
+      if ($ack =~ "ok") {
+        $test = 0;
+      }
+      else {
+        $type = "\U$ack";
+      }
+    }
+    elsif ($dt && ($values[17] ne "0")) {
+      if ($dt =~ "ok") {
+        $test = 0;
+      }
+      else {
+        $type = "\U$dt";
+      }
+    }
+  }
+
+  if ($details && $test) {
+    if (!$host) {
+      if ($diffout) {
+        $much_output{$type} .= " $diffout;";
+       $output{$type} .= "$diffout;";
+       $much_ct{$type}++;
+       $ct{$type}++;
+      }
+      else {
+        if ($much_details && $much_ct{$type}<$much_details) {
+          $much_output{$type} .= " $values[2] on $values[1] $values[31];";
+          $much_ct{$type}++;
+        }
+        if ($ct{$type} < $details) {
+          $output{$type} .= " $values[2] on $values[1];";
+          $ct{$type}++;
+        }
+      }
+    }  
+    else {
+        $much_output{$type} .= " $values[1] $_[1] $values[20],";
+       $much_ct{type}++;
+        $output{$type} .= " $values[1] HOST $_[1],";
+       $ct{$type}++;
+    }
+  }
+  if ($test) {
+    $numprob{$type}++;
+  }
+}
+
+################################
+#
+# Version and Help Information
+#
+################################
+
+sub printVersion {
+  printf <<EndVersion;
+$0 (nagios-plugins) 1.3
+The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute
+copies of the plugins under the terms of the GNU General Public License.
+For more information about these matters, see the file named COPYING.
+EndVersion
+}
+
+sub printHelp {
+  printf <<EOF;
+
+This plugin parses through the Nagios status log and will return a 
+Critical, Warning, or Unknown state depending on the number of 
+Critical, Warning, and/or Unknown services found in the log
+(or Down/Unreachable hosts when matching against hosts)  
+
+Usage: $0 -s <Status File> | -d <Nagios Log Directory> 
+       [-w #[,#][,#]] [-c #[,#][,#]] [-u #[,#][,#]]
+        [--service=<RegEx> | --servhost=<RegEx> | --pattern=<RegEx> |
+        --host            | --host=<RegEx>]
+        [--ack[=string]]  [--dt[=string]]  [--hostdown[=string]]
+        [-D #[,#]]  [--ok]  [-f <Log freshness in # minutes>]
+       $0 --help
+       $0 --version
+NOTE: One of -s and -d must be specified
+
+Options:
+ -s, --status=FILE_NAME
+   Location and name of status log (e.g. /usr/local/nagios/var/status.log)
+ -d, --dir=DIRECTORY_NAME
+   Directory that contains the nagios logs (e.g. /usr/local/nagios/var/)
+ -w, --warning=INTEGER[,INTEGER][,INTEGER]
+   #:     Number of warnings to result in a WARNING state
+          OR
+   #,#:   Warning,Criticals to result in a WARNING state
+         OR
+   #,#,#: Warning,Critical,Unknown to result in a WARNING state 
+   Default: -w=1
+ -c, --critical=INTEGER[,INTEGER][,INTEGER]
+   #:     Number of criticals to result in a CRITICAL state
+          OR
+   #,#:   Warning,Criticals to result in a CRITICAL state
+          OR
+   #,#,#: Warning,Critical,Unknown to result in a CRITICAL state
+   Default: -c=1
+ -u, --unknown=INTEGER[,INTEGER][,INTEGER]
+   #:     Number of unknowns to result in a UNKNOWN state
+          OR
+   #,#:   Warning,Criticals to result in a UNKNOWN state
+          OR
+   #,#,#: Warning,Critical,Unknown to result in a UNKNOWN state
+   Default: -u=1
+ -r, --service[=REGEX]
+   Only match services [that match the RegEx]
+   (--service is default setting if no other matching arguments provided)
+ --servhost=REGEX
+   Only match services whose host match the RegEx
+ -p, --pattern=REGEX
+   Only parse for this regular expression (services only, not hosts)
+ --host[=REGEX]
+   Report on the state of hosts (whose name matches the RegEx if provided)
+ -a, --ack[=ok|warning|critical|unknown|down|unreachable]
+   Handle Acknowledged problems [--ack defaults to ok]
+ --dt, --downtime[=ok|warning|critical|unknown|down|unreachable]
+   Handle problems in scheduled downtime [--dt defaults to ok]
+ --hd, --hostdown[=ok|warning|critical|unknown|down|unreachable]
+   Handle services whose Host is down [--hd defaults to ok]
+ -D, --details=INTEGER[,INTEGER]
+   Amount of verbosity to output
+   If # problems: 
+    <= 1st integer, return full details (each plugin's output) 
+    <= 2nd integer, return some details (list each service host pair)
+    >  2nd integer, return the # of problems
+ -f, --freshness=INTEGER
+   Number of minutes old the log can be to make sure Nagios is running
+   (Default = 30 minutes)
+ --ok
+   Return an OK exit code, regardless of number of problems found
+ -h, --help
+   Print detailed help screen
+ -V, --version
+   Print version information 
+
+For service checking (use --service and/or --servhost): 
+1.  The values of warning, critical, and unknown default to 1, i.e.
+$0 will return CRITICAL if there is at least 1 critical service, 
+WARNING if there is at least 1 warning service, and UNKNOWN if there is
+at least one unknown service.
+
+2.  If a service's host is DOWN or UNREACHABLE, $0 will use the 
+value of --hostdown to determine how to treat the service.  Without that
+argument, $0 will count the service as OK.
+
+3.  If a service's host is OK, but the last host-state change occurred more 
+recently than the last service check, $0 will ignore that service
+(want to wait until the service has been checked after a host has recovered
+or you may get service alert for services that still need to be checked)
+
+4.  If the --dt, --ack, or --hd tags are used, $0 will use the value
+of the arguments to determine how to handle services in downtime, acknowledged,
+or with down hosts (default=OK). For service checks, --dt will also check
+if the service's host is in a downtime.
+
+For host checking (use --host):
+1.  Using the --host argument, $0 will look for DOWN and UNREACHABLE
+hosts.  If any are found, $0 will return a CRITICAL.  You can provide
+an REGEX for --host to only check hosts with matching host names. 
+
+2.  If the --dt or --ack tags are used, $0 will use the value of the
+--dt/--ack arguments to determine the state of the host (default is OK)
+
+EOF
+}
diff --git a/contrib/check_wins.pl b/contrib/check_wins.pl
new file mode 100755 (executable)
index 0000000..58a597a
--- /dev/null
@@ -0,0 +1,248 @@
+#!/usr/bin/perl -w
+
+# $Id$
+
+# $Log$
+# Revision 1.1  2003/02/09 14:16:28  sghosh
+# more contribs
+#
+
+use strict ;
+
+use Getopt::Long ;
+use vars qw($opt_H $opt_D $opt_W $opt_T $debug @my_dcs);
+
+use lib '/usr/local/netsaint/libexec/' ;
+use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
+
+my $PROGNAME = 'check_wins' ;
+
+use constant SAMBA_DEBUG_LVL   => 2 ;
+use constant MY_DCS            => ('dc1','dc2') ;
+# use constant MY_DCS          => qw(ipa01 ipa02 ipa03) ;
+
+my $NMBLOOKUP_PATH             = '/usr/bin/nmblookup' ;
+my $NMBLOOKUP                  = sub { return `$NMBLOOKUP_PATH $_[2] -R -U $_[0] $_[1]` } ;
+my $NMBLOOKUP_CMD              = $NMBLOOKUP_PATH  . ' -R -U' ;
+
+sub print_help ();
+sub print_usage ();
+sub help ();
+sub version ();
+
+delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
+
+$SIG{"ALRM"} = sub { die "Alarm clock restart" } ;
+
+Getopt::Long::Configure('bundling', 'no_ignore_case');
+GetOptions
+        ("V|version"     => \&version,
+         "h|help"        => \&help,
+         "d|debug"       => \$debug,
+        "C|controllers:s" => \@my_dcs,
+         "T|timeout:i"  => \$opt_T,
+         "W|wins=s"     => \$opt_W,
+         "D|domain=s"    => \$opt_D);
+
+
+($opt_D) || usage("MS Domain name not specified\n");
+my $domain = $1 if $opt_D =~ m#(\w+)# ;                # NetBIOS names allow __any__ characters (more than \w)
+($domain) || usage("Invalid MS D name: $opt_D\n");
+
+($opt_W) || usage("WINS hostname or address not specified\n");
+my $wins = $1 if $opt_W =~ m#((?:^\w+$)|(?:\d+(?:\.\d+){3,3}$))# ;
+($wins) || usage("Invalid WINS hostname or address: $opt_W\n");
+
+usage("You must provide the names of your domain controllers by updating MY_DCS in the text or use -C dc_name1 -C dc_name2 ..\n")
+  unless (@my_dcs or MY_DCS) ;
+
+@my_dcs = MY_DCS       unless defined $my_dcs[0] ;
+$TIMEOUT = $opt_T      if defined $opt_T ;
+
+my ($netbios_name, @dcs_of_domain, @dc_addresses) ;
+my (@addr_dcs_of_domain, @found_dcs, %address2dc) ;
+my (@dc_query) ;
+
+# tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipa01
+# Sending queries to 10.0.100.29
+# 10.0.100.16 ipa01<00>
+
+eval {
+  alarm($TIMEOUT) ;
+  @dc_query = $debug ? map { $NMBLOOKUP->($wins, "$_#20", '-d ' . SAMBA_DEBUG_LVL) } @my_dcs :
+                      map { ( $NMBLOOKUP->($wins, "$_#20", '') )[1] } @my_dcs ;
+  alarm(0) ;
+} ;
+
+if ($@ and $@ =~ /Alarm clock restart/) {
+  print qq(Failed. Timeout while waiting for response from  (one of) "$NMBLOOKUP_CMD $wins @my_dcs"\n) ;
+  exit $ERRORS{"CRITICAL"} ;
+}
+
+if ($@ and $@ !~ /Alarm clock restart/) {
+  print qq(Failed. "$@" in response to "NMBLOOKUP_CMD $wins @my_dcs"\n) ;
+  exit $ERRORS{"UNKNOWN"} ;
+}
+
+chomp @dc_query ;
+if ( scalar grep(/name_query failed/, @dc_query) ) {
+  print qq(Failed. WINS "$wins" failed to resolve), scalar @my_dcs > 1 ? ' at least one of ' : ' ', qq("@my_dcs", the domain controller(s) of "$domain". Got "@dc_query"\n) ;
+  exit $ERRORS{"CRITICAL"} ;
+}
+
+# the results of looking up the DCs (by their name) in the WINS 
+
+# 10.0.100.16 ipa01<20>
+# 10.0.100.1 ipa02<20>
+# 10.0.100.104 ipa03<20>
+
+@dc_addresses = () ;
+foreach (@dc_query) {
+  next unless /^(\S+)\s+(\S+?)<\S+?>$/ ;
+  $address2dc{$1} = $2 ;
+  push @dc_addresses, $1 ;
+}
+
+$netbios_name = "$domain#1C"  ;
+
+eval {
+  alarm($TIMEOUT) ;
+  @dcs_of_domain = $NMBLOOKUP->($wins, $netbios_name, defined $debug ? '-d ' . SAMBA_DEBUG_LVL : '') ;
+  alarm(0) ;
+
+} ;
+
+if ($@ and $@ =~ /Alarm clock restart/) {
+  print qq(Failed. Timeout while waiting for response from "$NMBLOOKUP_CMD $wins $netbios_name"\n) ;
+  exit $ERRORS{"CRITICAL"} ;
+} 
+
+if ($@ and $@ !~ /Alarm clock restart/) {
+  print qq(Failed. "$@" in response to "$NMBLOOKUP_CMD $wins $netbios_name"\n) ;
+  exit $ERRORS{"UNKNOWN"} ;
+}
+
+shift @dcs_of_domain ;
+chomp @dcs_of_domain ;
+@addr_dcs_of_domain = map /^(\S+)/, @dcs_of_domain ;
+
+# tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipaustralia#1c
+# Sending queries to 10.0.100.29
+# 10.0.100.114 ipaustralia<1c>
+# 168.168.102.129 ipaustralia<1c>
+# 192.168.101.221 ipaustralia<1c>
+# 10.0.100.61 ipaustralia<1c>
+# 192.168.108.129 ipaustralia<1c>
+# 192.168.102.128 ipaustralia<1c>
+# 10.0.4.126 ipaustralia<1c>
+# 192.168.106.214 ipaustralia<1c>
+# 10.0.3.165 ipaustralia<1c>
+# 192.168.105.214 ipaustralia<1c>
+# 10.0.6.145 ipaustralia<1c>
+# 192.168.104.128 ipaustralia<1c>
+# 10.0.4.59 ipaustralia<1c>
+# 10.9.99.99 ipaustralia<1c>
+# 10.99.99.99 ipaustralia<1c>
+# 10.9.99.254 ipaustralia<1c>
+# 10.0.3.15 ipaustralia<1c>
+# 192.168.102.129 ipaustralia<1c>
+# 192.168.103.129 ipaustralia<1c>
+# 192.168.105.129 ipaustralia<1c>
+# 192.168.106.129 ipaustralia<1c>
+# 192.168.101.129 ipaustralia<1c>
+# 192.168.104.129 ipaustralia<1c>
+# 10.0.3.123 ipaustralia<1c>
+# 10.0.100.67 ipaustralia<1c>
+# tsitc> 
+
+my %x ;
+@found_dcs = grep { ! $x{$_}++ } @address2dc{ grep exists $address2dc{$_}, @addr_dcs_of_domain} ;
+# @found_dcs = grep { defined $_} @address2dc{ grep exists $address2dc{$_}, @addr_dcs_of_domain} ;
+                                                               # Gotcha.
+                                                               # 'exists' is necessary to prevent autovivificatiton
+                                                               # of keys in %address2dc
+
+if ( &set_eq( \@found_dcs, [ values %address2dc ] ) ) {
+  print $debug ? qq(Ok. WINS named "$wins" resolved addresses of "@my_dcs" as "@dc_query" and controllers of domain "$domain" as "@dcs_of_domain"\n) :
+                qq(Ok. Found controllers named "@my_dcs" in response to "$domain#1C" name query from WINS named "$wins".\n) ;
+  exit $ERRORS{"OK"} ;
+} elsif ( scalar @found_dcs == 0 ) {
+  print qq(Failed. Found __no__ controllers named "@my_dcs" in response to "$domain#1C" query from WINS named "$wins". Got "@dcs_of_domain"\n) ;
+  exit $ERRORS{"CRITICAL"} ;
+} elsif ( scalar @found_dcs < scalar keys %address2dc ) {
+  print qq(Warning. Not all domain controllers found in response to "$domain#1C" query from WINS named "$wins". Expected "@my_dcs", got "@found_dcs"\n) ;
+  exit $ERRORS{"WARNING"} ;
+}
+
+sub set_eq {
+
+  return 0 unless scalar @{$_[0]} == scalar @{$_[1]} ;
+  foreach my $a ( @{$_[0]} ) {
+    return 0 unless scalar grep { $a eq $_ } @{$_[1]} ;
+  } 
+  return 1 ;
+
+}
+
+
+sub print_usage () {
+       print "Usage: $PROGNAME -W <wins> -D <domain>\n";
+}
+
+sub print_help () {
+       print_revision($PROGNAME,'$Revision$ ');
+       print "Copyright (c) 2001 Karl DeBisschop/S Hopcroft
+
+Perl Check WINS plugin for NetSaint.
+
+Returns OK if the addresses of domain controllers are found in the list of domain controllers returned in the WINS response to a 'domain controllers query' 
+
+Why would you want to do this ?
+
+MS File server clients insist on connecting to file servers using NetBIOS names.
+If they __don't__ resolve NetBIOS names with a WINS (NBNS) then they'll either fail to logon and  connect to shares or they will
+broadcast requsts for names.
+Both problems are eliminated by a healthy WINS.
+Also, you may have a MS domain spanning a  number of WAN connected sites, with domain controllers far away from powerful local
+domain controllers.
+In this case, you want your local clients to have their logon requests validated by the local controllers.
+
+The plugin works by
+  asking the WINS to resolve the addresses of the domain controllers (supplied by -C or from the constant MY_DCS)
+  asking the WINS to return the list of addresses of the domain controllers able to validate requests for the domain
+   whose name is given by -D
+  returning Ok         if all controller addresses are in that list (of addresses of domain controllers) or
+  returning WARNING    if not all the controller addresses are in the list or
+  returning CRITICAL   if there is no reply from the WINS or the list contains none of the contoller addresses
+
+";
+       print_usage();
+       print '
+-W, --wins=STRING
+   Hostname or address of the WINS (Either Samba/nmbd or MS product)
+-D, --domain=STRING
+   MS Domain name to find the Domain controllers of.
+-C, --controllers:STRING
+   Optional __name(s)__ of domain controller that __must__ be found in the response to a domain controller name query.
+   If not defined, then use the constant value MY_DCS. You must use either -C or make sure that MY_DCS contains the names 
+   of __your__ domain controllers.
+-T, --timeout:INTEGER
+-d, --debug
+   Debugging output.
+-h, --help
+   This stuff.
+
+';
+       support();
+}
+
+sub version () {
+       print_revision($PROGNAME,'$Revision$ ');
+       exit $ERRORS{'OK'};
+}
+
+sub help () {
+       print_help();
+       exit $ERRORS{'OK'};
+}
+
diff --git a/contrib/sched_downtime.pl b/contrib/sched_downtime.pl
new file mode 100644 (file)
index 0000000..b46b482
--- /dev/null
@@ -0,0 +1,47 @@
+#! /usr/bin/perl -w
+#
+# Marko Riedel, EDV Neue Arbeit gGmbH, mriedel@neuearbeit.de 
+#
+#
+#
+#
+use POSIX qw(strtol);
+
+my $command_file = '/usr/local/nagios/var/rw/nagios.cmd';
+
+my $hour = (60*60);
+my $next_day = (24*60*60);
+
+my $downtimes = 
+  [
+   { 
+    host => 'somehost',
+    service => 'SERVICE',
+    times => [ ["00:00", 9], ["18:00", 6] ]
+   }
+  ];
+
+foreach my $entry (@$downtimes) {
+  my ($secstart, $secend, $cmd, $current);
+
+  $current = `/bin/date +"%s"`;
+  chomp $current;
+
+  foreach my $tperiod (@{ $entry->{times} }){
+    $secstart = strtol(`/bin/date -d "$tperiod->[0]" +"%s"`);
+    $secend   = $secstart+$tperiod->[1]*$hour;
+
+    $secstart += $next_day;
+    $secend   += $next_day;
+
+    $cmd  = "[$current] SCHEDULE_SVC_DOWNTIME;";
+    $cmd .= "$entry->{host};$entry->{service};";
+    $cmd .= "$secstart;$secend;";
+    $cmd .= "1;0;$0;automatically scheduled;\n";
+
+    print STDERR $cmd;
+
+    system "echo \"$cmd\" >> $command_file";
+  }
+}  
+