File check_temp_raritan of Package monitoring-plugins-temp_raritan
#!/usr/bin/perl -w
# nagios: -epn
#
# check_temp_raritan - nagios plugin
#
# Copyright (C) 2015, SUSE Linux GmbH
# Author: Lars Vogdt
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of the Novell nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
use warnings;
use strict;
use Carp;
use Config::IniFiles;
use English qw( -no_match_vars );
use Getopt::Long;
use Net::SNMP;
use Pod::Usage;
#######################################################################
## Init Area
#######################################################################
$ENV{'PATH'} = '/bin:/usr/bin:/sbin:/usr/sbin:';
$ENV{'BASH_ENV'} = '';
$ENV{'ENV'} = '';
our $conf={
VERSION => '0.2.0',
PROGNAME => 'check_temp_raritan',
community => 'public',
debug => 0,
hostname => 'localhost',
timeout => 120,
logfile => '/var/log/check_temp_raritan.log',
loglevel => 1,
};
our $ERRORS={
'OK' => 0,
'WARNING' => 1,
'CRITICAL' => 2,
'UNKNOWN' => 3,
'DEPENDENT' => 4,
};
our %nagios_result=(
output => 'OK',
perfdata => '',
error => 0,
);
our @config_options=qw(
ip
community
logfile
loglevel
);
our @needed=qw(
ip
community
);
our $temp_sensor_count = '.1.3.6.1.4.1.13742.4.2.1.0';
our $tempSensorLabel = '.1.3.6.1.4.1.13742.4.2.2.1.2';
our $temperature = '.1.3.6.1.4.1.13742.4.2.2.1.3';
our $tempLowerWarning = '.1.3.6.1.4.1.13742.4.2.2.1.4';
our $tempUpperWarning = '.1.3.6.1.4.1.13742.4.2.2.1.5';
our $tempLowerCritical = '.1.3.6.1.4.1.13742.4.2.2.1.6';
our $tempUpperCritical = '.1.3.6.1.4.1.13742.4.2.2.1.7';
my $print_help=0;
#######################################################################
## Function Area
#######################################################################
sub logfile {
my ($action,$config_ref)=@_;
if (!defined($config_ref->{'loglevel'}) || $config_ref->{'loglevel'} eq ""){
$config_ref->{'loglevel'}=0;
}
if (("$action" eq "open" ) || ("$action" eq "new" )) {
open (my $fh, ">>$config_ref->{'logfile'}") or croak "Couldn't open ".$config_ref->{'logfile'}." !\n";
flock($fh,2) or croak "Can't get lock for $config_ref->{'logfile'} !\n";
return $fh;
} else {
if (defined($config_ref->{'logfile_fh'})){
close $config_ref->{'logfile_fh'} or croak("Could not close filehandle $config_ref->{'logfile_fh'}\n");
}
}
}
sub LOG {
my ($message,$level,$config_ref)=@_;
my $time = localtime(time);
my $fh=$config_ref->{'logfile_fh'};
if ($level <= $config_ref->{'loglevel'}){
print $fh "$time [".$config_ref->{'PROGNAME'}."] : $message\n" or croak("Could not write to logfile\n");
}
print STDERR "DEBUG: $message\n" if ($config_ref->{'debug'});
}
sub check_community($){
my ($string)=@_;
my $stringQuestion = "N";
if ("$string" eq ""){
printf("The Communitystring is empty. Are you sure?\n [y/N]]:");
$stringQuestion = <STDIN>;
chop($stringQuestion);
if ($stringQuestion ne "y" && $stringQuestion ne "Y"){
die("Communitystring is empty. Abort..\n")
}
}
return scalar "$stringQuestion";
}
sub check_ini_section($$$){
my ($iniref,$name,$needed_ref)=@_;
foreach my $needed (@$needed_ref){
if (!defined($iniref->val("$name","$needed"))){
return "$needed";
}
}
return 0
}
sub set_errorcode($$){
my ($status,$result)=@_;
if ( $result->{'error'} < $status){
return $status;
}
else {
return $result->{'error'};
}
}
sub cleanup_and_exit($$){
my ($conf,$exitcode)=@_;
logfile('close',$conf);
exit $exitcode;
}
sub check_raritan($){
my ($conf)=@_;
my $error;
my %session;
($session{'snmp'}, $error)=Net::SNMP->session(
-hostname => $conf->{'hostname'},
-community => $conf->{'community'},
);
if (!defined $session{'snmp'}) {
LOG("ERROR opening SNMP session to $conf->{'hostname'}: $error",1,$conf);
$session{'snmp'}->close();
next;
}
# how many sensors should we query?
my $result=$session{'snmp'}->get_request( -varbindlist => ["$temp_sensor_count" ]);
if (!defined $result) {
LOG("ERROR: no result for temp sensor count: $session{'snmp'}->error()",1,$conf);
$session{'snmp'}->close();
next;
}
my $count=$result->{"$temp_sensor_count"};
# get temperatures
for (my $x=1; $x <= $count; $x++){
# get label
my $result=$session{'snmp'}->get_request( -varbindlist => ["$tempSensorLabel.$x"] );
$session{$x}{'label'}=$result->{"$tempSensorLabel.$x"};
# get current temperature
$result=$session{'snmp'}->get_request( -varbindlist => ["$temperature.$x"]);
$session{$x}{'temp'}=$result->{"$temperature.$x"};
$session{$x}{'real_temp'}=$session{$x}{'temp'}/10;
# get lower warning level
$result=$session{'snmp'}->get_request( -varbindlist => ["$tempLowerWarning.$x"]);
$session{$x}{'lowerWarning'}=$result->{"$tempLowerWarning.$x"};
# get upper warning level
$result=$session{'snmp'}->get_request( -varbindlist => ["$tempUpperWarning.$x"]);
$session{$x}{'upperWarning'}=$result->{"$tempUpperWarning.$x"};
# get lower critical level
$result=$session{'snmp'}->get_request( -varbindlist => ["$tempLowerCritical.$x"]);
$session{$x}{'lowerCritical'}=$result->{"$tempLowerCritical.$x"};
# get upper critical level
$result=$session{'snmp'}->get_request( -varbindlist => ["$tempUpperCritical.$x"]);
$session{$x}{'upperCritical'}=$result->{"$tempUpperCritical.$x"};
#
# prepare output
#
$nagios_result{'perfdata'}="'".$session{$x}{'label'}."'=".$session{$x}{'real_temp'}.
";".$session{$x}{'lowerWarning'}.":".$session{$x}{'upperWarning'}.
";".$session{$x}{'lowerCritical'}.":".$session{$x}{'upperCritical'}.";";
$nagios_result{'output'}="OK: ".$session{$x}{'real_temp'}.
" degrees on '".$session{$x}{'label'}.
"' (".$conf->{'hostname'}.") is inside the tolerance";
if ($session{$x}{'real_temp'} > $session{$x}{'upperWarning'}){
$nagios_result{'output'}="WARNING: ".$session{$x}{'real_temp'}.
" degrees on '".$session{$x}{'label'}.
"' (".$conf->{'hostname'}.") is above warning level (".
$session{$x}{'upperWarning'}.")";
$nagios_result{'error'}=set_errorcode($ERRORS->{'WARNING'},\%nagios_result);
}
if ($session{$x}{'real_temp'} < $session{$x}{'lowerWarning'}){
$nagios_result{'output'}="WARNING: ".$session{$x}{'real_temp'}.
" degrees on '".$session{$x}{'label'}.
"' (".$conf->{'hostname'}.") is below warning level (".
$session{$x}{'lowerWarning'}.")";
$nagios_result{'error'}=set_errorcode($ERRORS->{'WARNING'},\%nagios_result);
}
if ($session{$x}{'real_temp'} > $session{$x}{'upperCritical'}){
$nagios_result{'output'}="CRITICAL: ".$session{$x}{'real_temp'}.
" degrees on '".$session{$x}{'label'}.
"' (".$conf->{'hostname'}.") is above critical level (".
$session{$x}{'upperCritical'}.")";
$nagios_result{'error'}=set_errorcode($ERRORS->{'CRITICAL'},\%nagios_result);
}
if ($session{$x}{'real_temp'} < $session{$x}{'lowerCritical'}){
$nagios_result{'output'}="CRITICAL: ".$session{$x}{'real_temp'}.
" degrees on '".$session{$x}{'label'}.
"' (".$conf->{'hostname'}.") exceeds ciritcal level (".
$session{$x}{'lowerCritical'}.")";
$nagios_result{'error'}=set_errorcode($ERRORS->{'CRITICAL'},\%nagios_result);
}
}
if ($conf->{'debug'}){
print STDERR "Session: \n".Data::Dumper->Dump([\%session])."\n";
}
$session{'snmp'}->close();
return %nagios_result;
}
#######################################################################
## Main Area
#######################################################################
Getopt::Long::Configure('bundling');
GetOptions( "h|help" => \$print_help,
"c|config=s" => \$conf->{'config'},
"d|debug" => \$conf->{'debug'},
"logfile=s" => \$conf->{'logfile'},
"loglevel=i" => \$conf->{'loglevel'},
"H|host=s" => \$conf->{'hostname'},
"C|community=s" => \$conf->{'community'},
"t|timeout=i" => \$conf->{'timeout'},
) or pod2usage(2);
pod2usage( -exitstatus => 0,
-verbose => 1, # 2 to print full pod
) if $print_help;
# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
print "UNKNOWN -timeout reached (".$conf->{'timeout'}." sec)\n";
exit 3;
};
alarm($conf->{'timeout'});
# use an existing config file, if exists
if (defined($conf->{'config'}) && -r $conf->{'config'}){
my $ini = new Config::IniFiles( -file => "$conf->{'config'}",
-default => "global",
-allowcontinue => 1);
if( ! $ini ){
croak("Couldn't open $conf->{'config'} : $!\n");
}
$conf->{'logfile'}=$ini->val('global','logfile') if $ini->val('global','logfile');
$conf->{'loglevel'}=$ini->val('global','loglevel') if $ini->val('global','loglevel');
my $logfile_ref=logfile('open',$conf);
$conf->{'logfile_fh'}=$logfile_ref;
if ($conf->{'debug'}){
use Data::Dumper;
print STDERR "Config:\n".Data::Dumper->Dump([$conf])."\n";
print STDERR "Ini:\n".Data::Dumper->Dump([$ini])."\n";
}
foreach my $section ( $ini->Sections() ){
next if ( $section eq "global" );
my $res=check_ini_section($ini,$section,\@needed);
if ($res){
LOG("Needed element $res not found in $section from $conf->{'config'} - skipping",1,$conf);
next;
}
$conf->{'hostname'}=$ini->val($section, 'ip');
$conf->{'community'}=$ini->val($section, 'community');
%nagios_result=check_raritan($conf);
print $nagios_result{'output'}." |".$nagios_result{'perfdata'}."\n";
LOG("$nagios_result{'output'} |$nagios_result{'perfdata'}",2,$conf);
}
} else {
%nagios_result=check_raritan($conf);
print $nagios_result{'output'}." |".$nagios_result{'perfdata'}."\n";
LOG("$nagios_result{'output'} |$nagios_result{'perfdata'}",2,$conf);
}
LOG("Exit code of last run: $nagios_result{'error'}",2,$conf);
cleanup_and_exit($conf,$nagios_result{'error'});
__END__
=head1 Get temperatures from Raritan Powerswitches via SNMP
SNMP commandline interface for getting temperature information from the sensors of Raritan power switches.
=head1 SYNOPSIS
./check_temp_raritan <OPTIONS>
Options:
-c <file> | --config <file>
-H <host> | --host <host>
-C <community> | --community <community>
=head1 OPTIONS
=over 8
=item B<--config> F<file>
Use configfile F<file> instead of commandline args.
The content of the file should be as follows:
=over 8
[global]
logfile=/var/log/check_temp_raritan.log
loglevel=1
[hostname]
ip=hostname.example.com
community=public
=back
=item B<--host> F<host>
Name of the host to query.
=item B<--community> F<community>
SNMP community string (default: public).
=item B<--logfile> F<file>
Use logfile F<file> instead of the default logfile configured in config.
=back
=head1 DESCRIPTION
Raritan power switches can be equipped with external temperature sensors. This script tries to
get the sensor information via SNMP.
Choose between using a configuration file (together with option -c) or commandline arguments
(options -C and -H).
=head1 AUTHORS
=over 8
=item Lars Vogdt <lars@linux-schulserver.de>
=back
=cut