#!/usr/bin/perl -w # # check_snmp_mssql - nagios plugin # # Kaltashkin Eugene # inspiration by Douglas E. Warner - check_snmp_gauge # # Douglas E. Warner # inspiration by Christoph Kron - check_ifstatus.pl # # 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. # # use strict; use Net::SNMP; use Getopt::Long; #use File::Basename; &Getopt::Long::config('auto_abbrev'); my $version = "0.0.2"; my $status; my $needhelp = ''; my $init = ''; my $compare = ''; my $TIMEOUT = 30; my $tmppath = '/tmp'; my %ERRORS = ( 'OK' , '0', 'WARNING', '1', 'CRITICAL', '2', 'UNKNOWN' , '3', ); # The state of the database. Valid states are defined as follows: # Active(0,1), Single User(2), DBO Only(3), Read Only(4), Offline(5), # Suspect(6), Loading(7), and Publishing(8). # States from MSSQL-MIB my %dbStat = ( '0','OK', '1','Active', '2','Single User', '3','DBO use Only', '4','Read Only', '5','Offline', '6','Suspect', '7','Loading', '8','Publishing', ); # default return value is UNKNOWN my $state = "UNKNOWN"; # time this script was run my $runtime = time(); # responses from script my $answer = ""; my $error; # external variable declarations my $hostname; my $community = "public"; my $port = 161; my $snmpTable = ".1.3.6.1.4.1.311.1.4.1.1.5"; # snmp related variables my $session; my $response; my $snmpkey; my $key; my $dbID; my $dbName = ''; my $dbNamelc = ''; my $keyType; my %dbNamesTmp; my %dbStatus; my %dbStatusTmp; # the usage of this program (duh) sub usage { printf("== check_snmp_mssql v%s ==\n", $version); printf(" Perl SNMP Check MSSQL plugin for Nagios\n"); printf(" Kaltashkin Eugene \n"); printf(" checks MSSQL databases status\n"); printf("\n"); printf("Usage: \n"); printf(" check_snmp_mssql (-C|--snmpcommunity) \n"); printf(" [-p|--port] (-H|--hostname) \n"); printf(" [-d|--dbname] [-i|--init] [-c|--compare]\n"); printf("\n\n"); exit $ERRORS{"UNKNOWN"}; } # for sorting things numerically sub numerically { $a <=> $b } # end numerically # get Statuses the user wants from host sub getStatusList { # get the value(s) for the oid given ($session, $error) = Net::SNMP->session( -hostname => $hostname, -community => $community, -port => $port ); if (!defined($session)) { exitout ( $state = "UNKNOWN", $answer = $error ); } if (!defined($response = $session->get_table($snmpTable))) { $answer = $session->error; $session->close; $state = "WARNING"; print "$state: $answer,$community,$snmpTable"; exit $ERRORS{$state}; } foreach $snmpkey (sort keys %{$response}) { $snmpkey =~ /.*\.(\d+)\.(\d+)\.(\d+)$/; $keyType = $1; $dbID = $2; $key = $3; $dbNamesTmp{$dbID} = lc($response->{$snmpkey}) if ($keyType == 2); $dbStatusTmp{$dbID} = $response->{$snmpkey} if ($keyType == 3); } foreach $dbID (sort numerically keys %dbNamesTmp) { my $dbNameTmp = $dbNamesTmp{$dbID}; my $dbStatTmp = $dbStatusTmp{$dbID}; $dbStatus{$dbNameTmp} = $dbStatTmp; } undef %dbNamesTmp; undef %dbStatusTmp; $session->close; } # end getStatusList # Just in case of problems, let's not hang NetSaint $SIG{'ALRM'} = sub { print ("ERROR: No snmp response from $hostname (alarm)\n"); exit $ERRORS{"UNKNOWN"}; }; alarm($TIMEOUT); if (scalar(@ARGV) == 0) { usage(); } # end if no options, give usage Getopt::Long::Configure("no_ignore_case"); $status = GetOptions("h|help" => \$needhelp, "C|snmpcommunity=s" => \$community, "p|port=i" => \$port, "H|hostname=s" => \$hostname, "d|dbname=s" => \$dbName, "i|init" => \$init, "c|compare" => \$compare ); if ($status == 0 || $needhelp) { print "Usage"; &usage(); } # check temporary path if (!($tmppath)) { exitout ( $state = "UNKNOWN", $answer = "Please define temporary path in script\n" ); } if (!-d $tmppath) { exitout ( $state = "CRITICAL", $answer = "Directory $tmppath not accessible\n" ); } # end check path # begin check for hostname if (!defined($hostname)) { exitout ( $state = "UNKNOWN", $answer = "Hostname must be specified\n" ); } # end check for hostname getStatusList(); if ($init) { $tmppath .= '/' if ($tmppath !~ /\/$/); my $fname = $tmppath.'dblist_'.$hostname; open OUT,">$fname" or exitout ( $state = "CRITICAL", $answer = "Create file $!\n" ); foreach $dbID ( sort keys %dbStatus ) { print OUT $dbID,"\n"; } close OUT; exitout ( $state = "OK", $answer = "DB List initialized succesfully\n" ); } if ($compare) { $tmppath .= '/' if ($tmppath !~ /\/$/); my $fname = $tmppath.'dblist_'.$hostname; # check filename exists if(!-f $fname) { exitout ( $state = "CRITICAL", $answer = "Database list file not found, please run script with --init option\n" ); } open OUT,"<$fname" or exitout ( $state = "CRITICAL", $answer = "Open file $!\n" ); my %dblst; # pushing file content into hash for compare foreach $dbID () { chomp $dbID;$dblst{$dbID} = 1; } close OUT; # check exist keys in two hashes, if found delete keys foreach $dbID ( keys %dbStatus ) { if (exists $dbStatus{$dbID} && exists $dblst{$dbID}) { delete $dbStatus{$dbID}; delete $dblst{$dbID}; } } # after compare hashes have differences my $lenold = scalar keys %dblst; # databases deleted my $lennew = scalar keys %dbStatus; # databases created if ($lenold > 0) { my $tmp = join ",",keys %dblst; exitout ( $state = "CRITICAL", $answer = "Database: $tmp has been deleted\n" ); } if ($lennew > 0) { my $tmp = join ",",keys %dbStatus; exitout ( $state = "WARNING", $answer = "Found new Database: $tmp\n" ); } exitout ( $state = "OK", $answer = "No difference found\n" ); } if ($dbName) { $dbNamelc = lc($dbName); if(!exists $dbStatus{$dbNamelc}) { exitout ( $state = "UNKNOWN", $answer = "Status of Database $dbName unknown or Database not exist\n" ); } else { if($dbStatus{$dbNamelc} > 1) { exitout ( $state = "CRITICAL", $answer = $dbName." ".$dbStat{$dbStatus{$dbNamelc}}."\n" ); } else { exitout ( $state = "OK", $answer = $dbName." ".$dbStat{$dbStatus{$dbNamelc}}."\n" ); } } } $state = "OK"; foreach $dbID (sort keys %dbStatus) { if ($dbStatus{$dbID} > 1) { $state = "CRITICAL"; $answer .= $dbID." ".$dbStat{$dbStatus{$dbID}}.","; } } # end foreach $key # Truncate last comma $answer =~ s/\,$//; # setup final message $answer = "ALL Databases OK" if(length($answer) < 2); $answer .= "\n"; print ("$state: $answer"); exit $ERRORS{$state}; sub exitout { print "$state: $answer"; exit $ERRORS{$state}; }