#
# $Id$
#
-# Copyright (C) 2010 Trond H. Amundsen
+# Copyright (C) 2008-2011 Trond H. Amundsen
#
# 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
# Version and similar info
$NAME = 'check_openmanage';
-$VERSION = '3.6.2-beta2';
+$VERSION = '3.7.2';
$AUTHOR = 'Trond H. Amundsen';
$CONTACT = 't.h.amundsen@usit.uio.no';
GENERAL OPTIONS:
- -p, --perfdata Output performance data [no]
- -t, --timeout Plugin timeout in seconds [30]
- -c, --critical Customise temperature critical limits
- -w, --warning Customise temperature warning limits
- -d, --debug Debug output, reports everything
- -h, --help Display this help text
- -V, --version Display version info
+ -f, --config Specify configuration file
+ -p, --perfdata Output performance data [default=no]
+ -t, --timeout Plugin timeout in seconds [default=30]
+ -c, --critical Custom temperature critical limits
+ -w, --warning Custom temperature warning limits
+ -F, --fahrenheit Use Fahrenheit as temperature unit
+ -d, --debug Debug output, reports everything
+ -h, --help Display this help text
+ -V, --version Display version info
SNMP OPTIONS:
- -H, --hostname Hostname or IP (required for SNMP)
- -C, --community SNMP community string [public]
- -P, --protocol SNMP protocol version [2]
- --port SNMP port number [161]
- -6, --ipv6 Use IPv6 instead of IPv4 [no]
- --tcp Use TCP instead of UDP [no]
+ -H, --hostname Hostname or IP (required for SNMP)
+ -C, --community SNMP community string [default=public]
+ -P, --protocol SNMP protocol version [default=2]
+ --port SNMP port number [default=161]
+ -6, --ipv6 Use IPv6 instead of IPv4 [default=no]
+ --tcp Use TCP instead of UDP [default=no]
OUTPUT OPTIONS:
- -i, --info Prefix any alerts with the service tag
- -e, --extinfo Append system info to alerts
- -s, --state Prefix alerts with alert state
- -S, --short-state Prefix alerts with alert state (abbreviated)
- -o, --okinfo Verbosity when check result is OK
- -I, --htmlinfo HTML output with clickable links
+ -i, --info Prefix any alerts with the service tag
+ -e, --extinfo Append system info to alerts
+ -s, --state Prefix alerts with alert state
+ -S, --short-state Prefix alerts with alert state abbreviated
+ -o, --okinfo Verbosity when check result is OK
+ -B, --show-blacklist Show blacklistings in OK output
+ -I, --htmlinfo HTML output with clickable links
CHECK CONTROL AND BLACKLISTING:
- -a, --all Check everything, even log content
- -b, --blacklist Blacklist missing and/or failed components
- --only Only check a certain component or alert type
- --check Fine-tune which components are checked
- --no-storage Don't check storage (alias for "--check storage=0")
+ -a, --all Check everything, even log content
+ -b, --blacklist Blacklist missing and/or failed components
+ --only Only check a certain component or alert type
+ --check Fine-tune which components are checked
+ --no-storage Don't check storage
For more information and advanced options, see the manual page or URL:
http://folk.uio.no/trondham/software/check_openmanage.html
# Version and license text
$LICENSE = <<"END_LICENSE";
$NAME $VERSION
-Copyright (C) 2010 $AUTHOR
+Copyright (C) 2008-2011 $AUTHOR
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
'check' => [], # check control
'critical' => [], # temperature critical limits
'warning' => [], # temperature warning limits
+ 'tempunit' => 'C', # temperature unit
+ 'fahrenheit' => 0, # Use fahrenheit
+ 'configfile' => undef, # configuration file
'timeout' => 30, # default timeout is 30 seconds
'debug' => 0, # debugging / verbose output
'help' => 0, # display help output
'perfdata' => undef, # output performance data
+ 'legacy_perfdata' => 0, # legacy performance data output
'info' => 0, # display servicetag
'extinfo' => 0, # display extra info
'htmlinfo' => undef, # html tags in output
'state' => 0, # display alert type
'short-state' => 0, # display alert type (short)
'okinfo' => 0, # default "ok" output level
+ 'show_blacklist' => 0, # show blacklisted components
'linebreak' => undef, # specify linebreak
'version' => 0, # plugin version info
'all' => 0, # check everything
'privkey' => undef, # SMNP v3
'privprotocol' => undef, # SMNP v3
'use_get_table' => 0, # hack for SNMPv3 on Windows with net-snmp
+ 'hide_servicetag' => 0, # hidden servicetag
);
# Get options
'check=s' => \@{ $opt{check} },
'c|critical=s' => \@{ $opt{critical} },
'w|warning=s' => \@{ $opt{warning} },
+ 'tempunit=s' => \$opt{tempunit},
+ 'F|fahrenheit' => \$opt{fahrenheit},
+ 'f|configfile=s' => \$opt{configfile},
't|timeout=i' => \$opt{timeout},
'd|debug' => \$opt{debug},
'h|help' => \$opt{help},
'V|version' => \$opt{version},
'p|perfdata:s' => \$opt{perfdata},
+ 'legacy-perfdata' => \$opt{legacy_perfdata},
'i|info' => \$opt{info},
'e|extinfo' => \$opt{extinfo},
'I|htmlinfo:s' => \$opt{htmlinfo},
's|state' => \$opt{state},
'S|short-state' => \$opt{shortstate},
'o|ok-info=i' => \$opt{okinfo},
+ 'B|show-blacklist' => \$opt{show_blacklist},
'linebreak=s' => \$opt{linebreak},
'a|all' => \$opt{all},
'only=s' => \$opt{only},
'privkey=s' => \$opt{privkey},
'privprotocol=s' => \$opt{privprotocol},
'use-get_table' => \$opt{use_get_table},
+ 'hide-servicetag' => \$opt{hide_servicetag},
) or do { print $USAGE; exit $E_UNKNOWN };
# If user requested help
if ($opt{help}) {
print $USAGE, $HELP;
- exit $E_OK;
+ exit $E_UNKNOWN;
}
# If user requested version info
if ($opt{version}) {
print $LICENSE;
- exit $E_OK;
-}
-
-# Setting timeout
-$SIG{ALRM} = sub {
- print "PLUGIN TIMEOUT: $NAME timed out after $opt{timeout} seconds\n";
exit $E_UNKNOWN;
-};
-alarm $opt{timeout};
-
-# If we're using SNMP
-$snmp = defined $opt{hostname} ? 1 : 0;
-
-# SNMP session variables
-$snmp_session = undef;
-$snmp_error = undef;
+}
-# The omreport command
-$omreport = undef;
+# Initialize blacklist
+%blacklist = ();
# Check flags, override available with the --check option
%check = ( 'storage' => 1, # check storage subsystem
'esmhealth' => 1, # check the ESM log overall health
);
+# Messages
+@report_storage = (); # messages with associated nagios level (storage)
+@report_chassis = (); # messages with associated nagios level (chassis)
+@report_other = (); # messages with associated nagios level (other)
+
+# Read config file
+parse_configfile() if defined $opt{configfile};
+
+# Setting timeout
+$SIG{ALRM} = sub {
+ print "PLUGIN TIMEOUT: $NAME timed out after $opt{timeout} seconds\n";
+ exit $E_UNKNOWN;
+};
+alarm $opt{timeout};
+
+# If we're using SNMP
+$snmp = defined $opt{hostname} ? 1 : 0;
+
+# SNMP session variables
+$snmp_session = undef;
+$snmp_error = undef;
+
+# The omreport command
+$omreport = undef;
+
# Default line break
$linebreak = isatty(*STDOUT) ? "\n" : '<br/>';
@enclosures = (); # enclosures
%snmp_enclosure = (); # enclosures
-# Messages
-@report_storage = (); # messages with associated nagios level (storage)
-@report_chassis = (); # messages with associated nagios level (chassis)
-@report_other = (); # messages with associated nagios level (other)
-
# Counters for everything
%count
= (
adjust_checks() if defined $opt{check};
# Blacklisted components
-%blacklist = defined $opt{blacklist} ? %{ get_blacklist() } : ();
+set_blacklist($opt{blacklist}) if defined $opt{blacklist};
# If blacklisting is in effect, don't check global health status
if (scalar keys %blacklist > 0) {
check_omreport_options();
}
+# Temperature unit
+if ($opt{fahrenheit}) {
+ $opt{tempunit} = 'F';
+}
+
+# Check tempunit syntax
+if ($opt{tempunit} !~ m{\A C|F|K|R \z}xms) {
+ print "ERROR: Unknown temperature unit '$opt{tempunit}'\n";
+ exit $E_UNKNOWN;
+}
#---------------------------------------------------------------------
# Helper functions
#---------------------------------------------------------------------
+# Make a regex from a glob pattern. Shamelessly stolen from Perl
+# Cookbook chapter 6.9
+sub glob2regex {
+ my $globstr = shift;
+ my %patmap
+ = ( '*' => '.*',
+ '?' => '.',
+ '[' => '[',
+ ']' => ']',
+ );
+ $globstr =~ s{(.)} { $patmap{$1} || "\Q$1" }ge;
+ return '\A' . $globstr . '\z';
+}
+
+#
+# Read config file
+#
+sub parse_configfile {
+ our $tiny = undef;
+
+ # Regexp for boolean values
+ our $off = qr{\A (0|off|false) \s* \z}ixms;
+ our $on = qr{\A (1|on|true) \s* \z}ixms;
+
+ # Mapping between command line options and the corresponding
+ # config file options
+ our %opt2config
+ = ( 'info' => 'output_servicetag',
+ 'extinfo' => 'output_sysinfo',
+ 'postmsg' => 'output_post_message',
+ 'state' => 'output_servicestate',
+ 'shortstate' => 'output_servicestate_abbr',
+ 'show_blacklist' => 'output_blacklist',
+ 'hide_servicetag' => 'output_hide_servicetag',
+ 'htmlinfo' => 'output_html',
+ 'okinfo' => 'output_ok_verbosity',
+ 'protocol' => 'snmp_version',
+ 'community' => 'snmp_community',
+ 'port' => 'snmp_port',
+ 'ipv6' => 'snmp_use_ipv6',
+ 'tcp' => 'snmp_use_tcp',
+ 'warning' => 'temp_threshold_warning',
+ 'critical' => 'temp_threshold_critical',
+ 'all' => 'check_everything',
+ 'perfdata' => 'performance_data',
+ 'tempunit' => 'temperature_unit',
+ 'timeout' => 'timeout',
+ 'blacklist' => 'blacklist',
+ 'legacy_perfdata' => 'legacy_performance_data',
+ );
+
+ # Load the perl module
+ if ( eval { require Config::Tiny; 1 } ) {
+ $tiny = Config::Tiny->new();
+ }
+ else {
+ print "ERROR: Required perl module 'Config::Tiny' not found\n";
+ exit $E_UNKNOWN;
+ }
+
+ # Read the config file
+ $tiny = Config::Tiny->read($opt{configfile})
+ or do { report('other', (sprintf q{Couldn't read configuration file: %s}, Config::Tiny->errstr()), $E_UNKNOWN);
+ return; };
+
+ # Syntax check
+ foreach my $section (keys %{ $tiny }) {
+ KEYWORD:
+ foreach my $keyword (keys %{ $tiny->{$section} }) {
+ next KEYWORD if $keyword eq 'check_everything';
+ if ($keyword =~ m{\A check_(.+)}xms) {
+ my $c = $1;
+ foreach my $cl (keys %check) {
+ next KEYWORD if $c eq $cl;
+ }
+ }
+ else {
+ LEGAL:
+ foreach my $legal (keys %opt2config) {
+ next KEYWORD if $keyword eq $opt2config{$legal};
+ }
+ }
+ if ($section eq '_') {
+ report('other', qq{CONFIG ERROR: In the global section: Unknown statement "$keyword"}, $E_UNKNOWN);
+ }
+ else {
+ report('other', qq{CONFIG ERROR: Unknown statement "$keyword" in section "$section"}, $E_UNKNOWN);
+ }
+ }
+ }
+
+ # Adjust checks according to statements in the configuration file
+ sub configfile_adjust_checks {
+ my $keyword = shift;
+ CHECK_CONFIG:
+ foreach my $key (keys %check) {
+ my $copt = join '_', 'check', $key;
+ next CHECK_CONFIG if !defined $tiny->{$keyword}->{$copt} or $tiny->{$keyword}->{$copt} eq q{};
+ if ($tiny->{$keyword}->{$copt} =~ m{$on}ixms) {
+ $check{$key} = 1;
+ }
+ elsif ($tiny->{$keyword}->{$copt} =~ m{$off}ixms) {
+ $check{$key} = 0;
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for '$copt' must be boolean (True/False)", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set blacklist according to statements in the configuration file
+ sub configfile_set_blacklist {
+ my $keyword = shift;
+ if (defined $tiny->{$keyword}->{blacklist} and $tiny->{$keyword}->{blacklist} ne q{}) {
+ # set_blacklist() takes an array ref
+ set_blacklist([$tiny->{$keyword}->{blacklist}]);
+ }
+ return;
+ }
+
+ # Set timeout according to statements in the configuration file
+ sub configfile_set_timeout {
+ my $keyword = shift;
+ if (defined $tiny->{$keyword}->{timeout} and $tiny->{$keyword}->{timeout} ne q{}) {
+ if ($tiny->{$keyword}->{timeout} =~ m{\A \d+ \z}xms) { # integer
+ $opt{timeout} = $tiny->{$keyword}->{timeout};
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for 'timeout' must be a positive integer", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set a boolean option
+ sub configfile_set_boolean {
+ my ($keyword, $bool) = @_;
+ my $cbool = $opt2config{$bool};
+ if (defined $tiny->{$keyword}->{$cbool} and $tiny->{$keyword}->{$cbool} ne q{}) {
+ if ($tiny->{$keyword}->{$cbool} =~ m{$on}ixms) {
+ $opt{$bool} = 1;
+ }
+ elsif ($tiny->{$keyword}->{$cbool} =~ m{$off}ixms) {
+ $opt{$bool} = 0;
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for '$cbool' must be boolean (True/False)", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set htmlinfo option from config file
+ sub configfile_set_htmlinfo {
+ my $keyword = shift;
+ my $conf = $opt2config{htmlinfo};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ if ($tiny->{$keyword}->{$conf} =~ m{$on}ixms) {
+ $opt{htmlinfo} = 1;
+ }
+ elsif ($tiny->{$keyword}->{$conf} =~ m{$off}ixms) {
+ $opt{htmlinfo} = undef;
+ }
+ else {
+ $opt{htmlinfo} = $tiny->{$keyword}->{$conf};
+ }
+ }
+ return;
+ }
+
+ # Set OK output verbosity
+ sub configfile_set_ok_verbosity {
+ my $keyword = shift;
+ my $conf = $opt2config{okinfo};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ if ($tiny->{$keyword}->{$conf} =~ m{\A \d+ \z}xms) {
+ $opt{okinfo} = $tiny->{$keyword}->{$conf};
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for '$conf' must be a positive integer", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set SNMP protocol version from config file
+ sub configfile_set_snmp_version {
+ my $keyword = shift;
+ my $conf = $opt2config{protocol};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ if ($tiny->{$keyword}->{$conf} =~ m{\A 1|2|3 \z}xms) {
+ $opt{protocol} = $tiny->{$keyword}->{$conf};
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for '$conf' must be '1', '2' or '3'", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set SNMP community name from config file
+ sub configfile_set_snmp_community {
+ my $keyword = shift;
+ my $conf = $opt2config{community};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ $opt{community} = $tiny->{$keyword}->{$conf};
+ }
+ return;
+ }
+
+ # Set SNMP port number from config file
+ sub configfile_set_snmp_port {
+ my $keyword = shift;
+ my $conf = $opt2config{port};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ if ($tiny->{$keyword}->{$conf} =~ m{\A \d+ \z}xms) { # integer
+ $opt{port} = $tiny->{$keyword}->{$conf};
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for '$conf' must be a positive integer", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set temperature threshold from config file
+ sub configfile_set_temp_threshold {
+ my $keyword = shift;
+ my $level = shift;
+ my $conf = $opt2config{$level};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ $opt{$level} = [$tiny->{$keyword}->{$conf}]; # array ref
+ }
+ return;
+ }
+
+ # Set perfdata from config file
+ sub configfile_set_perfdata {
+ my $keyword = shift;
+ my $conf = $opt2config{perfdata};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ if ($tiny->{$keyword}->{$conf} =~ m{$on}ixms) {
+ $opt{perfdata} = 1;
+ }
+ elsif ($tiny->{$keyword}->{$conf} =~ m{$off}ixms) {
+ $opt{perfdata} = undef;
+ }
+ elsif ($tiny->{$keyword}->{$conf} =~ m{\A minimal|multiline \z}xms) {
+ $opt{perfdata} = $tiny->{$keyword}->{$conf};
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for '$conf' must be either boolean, 'minimal' or 'multiline'", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set temp unit from config file
+ sub configfile_set_tempunit {
+ my $keyword = shift;
+ my $conf = $opt2config{tempunit};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ if ($tiny->{$keyword}->{$conf} =~ m{\A C|F|K|R \z}ixms) {
+ $opt{tempunit} = $tiny->{$keyword}->{$conf};
+ }
+ else {
+ report('other', "CONFIG ERROR: Rvalue for '$conf' must one of C/F/K/R", $E_UNKNOWN);
+ }
+ }
+ return;
+ }
+
+ # Set postmsg string from config file
+ sub configfile_set_postmsg {
+ my $keyword = shift;
+ my $conf = $opt2config{postmsg};
+ if (defined $tiny->{$keyword}->{$conf} and $tiny->{$keyword}->{$conf} ne q{}) {
+ $opt{postmsg} = $tiny->{$keyword}->{$conf}; # array ref
+ }
+ return;
+ }
+
+ # Sections in the config file to check for statements
+ my @sections = ();
+
+ # First: Populate the sections array with the global section
+ @sections = ('_');
+
+ # Second: Populate the sections array with host glob pattern (but
+ # not exact match)
+ PATTERN:
+ foreach my $glob (sort keys %{ $tiny }) {
+ next PATTERN if $glob eq '_'; # global section
+ next PATTERN if $glob eq $opt{hostname}; # exact match
+ my $regex = glob2regex($glob); # make regexp
+ if ($opt{hostname} =~ m{$regex}) {
+ push @sections, $glob;
+ }
+ }
+
+ # Third: Populate the sections array with exact hostname
+ if (defined $tiny->{$opt{hostname}}) {
+ push @sections, $opt{hostname};
+ }
+
+ # Loop through the sections array and get options
+ foreach my $sect (@sections) {
+ configfile_adjust_checks($sect);
+ configfile_set_blacklist($sect);
+ configfile_set_timeout($sect);
+ configfile_set_htmlinfo($sect);
+ configfile_set_ok_verbosity($sect);
+ configfile_set_boolean($sect, 'all');
+ configfile_set_boolean($sect, 'info');
+ configfile_set_boolean($sect, 'extinfo');
+ configfile_set_boolean($sect, 'state');
+ configfile_set_boolean($sect, 'shortstate');
+ configfile_set_boolean($sect, 'show_blacklist');
+ configfile_set_boolean($sect, 'ipv6');
+ configfile_set_boolean($sect, 'tcp');
+ configfile_set_boolean($sect, 'legacy_perfdata');
+ configfile_set_boolean($sect, 'hide_servicetag');
+ configfile_set_snmp_version($sect);
+ configfile_set_snmp_community($sect);
+ configfile_set_snmp_port($sect);
+ configfile_set_temp_threshold($sect, 'warning');
+ configfile_set_temp_threshold($sect, 'critical');
+ configfile_set_perfdata($sect);
+ configfile_set_tempunit($sect);
+ configfile_set_postmsg($sect);
+ }
+
+ return;
+}
+
#
# Store a message in one of the message arrays
#
return push @{ $type2array{$type} }, [ $msg, $exval, $id ];
}
-
#
# Run command, put resulting output lines in an array and return a
# pointer to that array
# Detecting blade via SNMP
#
sub snmp_detect_blade {
- my $DellBaseBoardType = '1.3.6.1.4.1.674.10892.1.300.80.1.7.1.1';
- my $result = $snmp_session->get_request(-varbindlist => [$DellBaseBoardType]);
+ # In some setups, the IDs for the blade and interconnect
+ # board are mixed up, so we need to check both.
+ my $DellBaseBoardType1 = '1.3.6.1.4.1.674.10892.1.300.80.1.7.1.1';
+ my $DellBaseBoardType2 = '1.3.6.1.4.1.674.10892.1.300.80.1.7.1.2';
+ my $result1 = $snmp_session->get_request(-varbindlist => [$DellBaseBoardType1]);
+ my $result2 = $snmp_session->get_request(-varbindlist => [$DellBaseBoardType2]);
# Identify blade. Older models (4th and 5th gen models) and/or old
# OMSA (4.x) don't have this OID. If we get "noSuchInstance" or
# similar, we assume that this isn't a blade
- if (exists $result->{$DellBaseBoardType} && $result->{$DellBaseBoardType} eq '3') {
+ if (exists $result1->{$DellBaseBoardType1} && $result1->{$DellBaseBoardType1} eq '3') {
+ $blade = 1;
+ return;
+ }
+ if (exists $result2->{$DellBaseBoardType2} && $result2->{$DellBaseBoardType2} eq '3') {
$blade = 1;
+ return;
}
return;
}
# Read the blacklist option and return a hash containing the
# blacklisted components
#
-sub get_blacklist {
+sub set_blacklist {
+ my $foo = shift;
my @bl = ();
- my %blacklist = ();
- if (scalar @{ $opt{blacklist} } >= 0) {
- foreach my $black (@{ $opt{blacklist} }) {
+ if (scalar @{ $foo } >= 0) {
+ foreach my $black (@{ $foo }) {
my $tmp = q{};
if (-f $black) {
open my $BL, '<', $black
next if $c !~ m/=/xms;
my ($key, $val) = split /=/xms, $c;
my @vals = split /,/xms, $val;
- $blacklist{$key} = \@vals;
+ push @{ $blacklist{$key} }, @vals;
}
}
- return \%blacklist;
+ return;
}
#
# adjust the check hash
if ($opt{only} eq 'chassis') {
- map { $check{$_} = 1 } qw(memory fans power temp cpu voltage
+ map { $check{$_} = 1 } qw(memory fans power temp cpu voltage sdcard
batteries amperage intrusion esmhealth);
}
else {
| No\sbattery\sprobes\sfound\son\sthis\ssystem # No battery probes
| Invalid\scommand:\spwrmonitoring # Old hardware
| Hardware\sor\sfeature\snot\spresent\. # SD cards
- | Invalid\scommand:\sremovableflashmedia # SD cards with old OMSA
+ | Invalid\scommand:\sremovableflashmedia # SD cards with old OMSA
+ | Error\sCorrection; # Memory stuff. Not really an error (new in OMSA 6.4)
# | Current\sprobes\snot\sfound # OMSA + RHEL5.4 bug
# | No\scontrollers\sfound # No RAID controller
}xms;
# Workaround for Openmanage BUG introduced in OMSA 5.5.0
$rawtext =~ s{\n;}{;}gxms if $command eq 'storage controller';
+ # Workaround for logical connectors where there are extra
+ # information that isn't possible to parse consistently. Remove
+ # everything after and including "Path Health"
+ if ($command =~ m{\A storage\sconnector}xms) {
+ $rawtext =~ s{Path\sHealth.*}{}xms;
+ }
+
# Report if no controllers found
if ($command eq 'storage controller' and $rawtext =~ m{No\scontrollers\sfound}xms) {
report('storage', 'Storage Error! No controllers found', $E_UNKNOWN);
# This helper function returns the corresponding value of a hash key,
# but takes into account that the key may not exist
sub get_hashval {
- my $key = shift || return undef;
+ my $key = shift || return;
my $hash = shift;
- return exists $hash->{$key} ? $hash->{$key} : "Undefined value $key";
+ return defined $hash->{$key} ? $hash->{$key} : "Undefined value $key";
}
+# Find component status from hash
+sub get_snmp_status {
+ my $key = shift || return 'Unknown';
+ return exists $snmp_status{$key} ? $snmp_status{$key} : 'Unknown';
+}
+
+# Find component status from hash
+sub get_snmp_probestatus {
+ my $key = shift || return 'Unknown';
+ return exists $snmp_probestatus{$key} ? $snmp_probestatus{$key} : 'Unknown';
+}
+
+# Check that a hash entry is defined and not an empty string. Return a
+# chosen string (parameter) if these conditions are not met
+sub get_nonempty_string {
+ my $key = shift; # key to check
+ my $hash = shift; # hash where the key belongs
+ my $alt = shift; # alternate return value
+ if (defined $hash->{$key} and $hash->{$key} ne q{}) {
+ return $hash->{$key};
+ }
+ return $alt;
+}
+
+# Converts from Celsius to something else
+sub temp_from_celsius {
+ my $x = shift;
+ my $to = shift;
+
+ if ($to eq 'F') {
+ return sprintf '%.1f', ($x * 9/5 + 32);
+ }
+ elsif ($to eq 'K') {
+ return sprintf '%.1f', ($x + 273.15);
+ }
+ elsif ($to eq 'R') {
+ return sprintf '%.1f', ($x * 9/5 + 32 + 459.67);
+ }
+ return $x;
+}
#---------------------------------------------------------------------
printf "SNMP ERROR [global]: %s\n", $snmp_error;
exit $E_UNKNOWN;
}
- $health = $status2nagios{$snmp_status{$result->{$systemStateGlobalSystemStatus}}};
+ $health = $status2nagios{get_snmp_status($result->{$systemStateGlobalSystemStatus})};
}
else {
#
# STORAGE: Check controllers
#-----------------------------------------
sub check_controllers {
- return if blacklisted('ctrl', 'all');
-
my $nexus = undef;
my $name = undef;
my $state = undef;
CTRL:
foreach my $out (@output) {
if ($snmp) {
- $name = $out->{controllerName};
- $state = get_hashval($out->{controllerState}, \%ctrl_state);
- $status = $snmp_status{$out->{controllerComponentStatus}};
- $minfw = exists $out->{controllerMinFWVersion}
- ? $out->{controllerMinFWVersion} : undef;
- $mindr = exists $out->{controllerMinDriverVersion}
- ? $out->{controllerMinDriverVersion} : undef;
- $firmware = exists $out->{controllerFWVersion}
- ? $out->{controllerFWVersion} : 'N/A';
- $driver = exists $out->{controllerDriverVersion}
- ? $out->{controllerDriverVersion} : 'N/A';
- $minstdr = exists $out->{'controllerMinRequiredStorportVer'}
- ? $out->{controllerMinRequiredStorportVer} : undef;
- $stdr = exists $out->{controllerStorportDriverVersion}
- ? $out->{controllerStorportDriverVersion} : undef;
- $nexus = convert_nexus($out->{controllerNexusID});
+ $name = $out->{controllerName} || 'Unknown controller';
+ $state = get_hashval($out->{controllerState}, \%ctrl_state) || 'Unknown state';
+ $status = get_snmp_status($out->{controllerComponentStatus});
+ $minfw = $out->{controllerMinFWVersion} || undef;
+ $mindr = $out->{controllerMinDriverVersion} || undef;
+ $firmware = $out->{controllerFWVersion} || 'N/A';
+ $driver = $out->{controllerDriverVersion} || 'N/A';
+ $minstdr = $out->{'controllerMinRequiredStorportVer'} || undef;
+ $stdr = $out->{controllerStorportDriverVersion} || undef;
+ $nexus = convert_nexus(($out->{controllerNexusID} || 9999));
}
else {
- $nexus = $out->{ID};
- $name = $out->{Name};
- $state = $out->{State};
- $status = $out->{Status};
+ $nexus = get_nonempty_string('ID', $out, '9999');
+ $name = get_nonempty_string('Name', $out, 'Unknown controller');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
$minfw = $out->{'Minimum Required Firmware Version'} ne 'Not Applicable'
? $out->{'Minimum Required Firmware Version'} : undef;
$mindr = $out->{'Minimum Required Driver Version'} ne 'Not Applicable'
#-----------------------------------------
sub check_physical_disks {
return if $#controllers == -1;
- return if blacklisted('pdisk', 'all');
my $nexus = undef;
my $name = undef;
my $media = undef; # media type (e.g. HDD, SSD)
my $bus = undef; # bus protocol (e.g. SAS, SATA)
my $spare = undef; # spare state (e.g. global hotspare)
+ my $cert = undef; # if drive is certified or not
my @output = ();
if ($snmp) {
'1.3.6.1.4.1.674.10893.1.20.130.4.1.26' => 'arrayDiskNexusID',
'1.3.6.1.4.1.674.10893.1.20.130.4.1.31' => 'arrayDiskSmartAlertIndication',
'1.3.6.1.4.1.674.10893.1.20.130.4.1.35' => 'arrayDiskMediaType',
+ '1.3.6.1.4.1.674.10893.1.20.130.4.1.36' => 'arrayDiskDellCertified',
'1.3.6.1.4.1.674.10893.1.20.130.5.1.7' => 'arrayDiskEnclosureConnectionControllerNumber',
'1.3.6.1.4.1.674.10893.1.20.130.6.1.7' => 'arrayDiskChannelConnectionControllerNumber',
);
PDISK:
foreach my $out (@output) {
if ($snmp) {
- $name = $out->{arrayDiskName};
- $state = get_hashval($out->{arrayDiskState}, \%pdisk_state);
- $status = $snmp_status{$out->{arrayDiskComponentStatus}};
- $fpred = exists $out->{arrayDiskSmartAlertIndication}
+ $name = $out->{arrayDiskName} || 'Unknown disk';
+ $state = get_hashval($out->{arrayDiskState}, \%pdisk_state) || 'Unknown state';
+ $status = get_snmp_status($out->{arrayDiskComponentStatus});
+ $fpred = defined $out->{arrayDiskSmartAlertIndication}
&& $out->{arrayDiskSmartAlertIndication} == 2 ? 1 : 0;
$progr = q{};
- $nexus = convert_nexus($out->{arrayDiskNexusID});
- $vendor = exists $out->{arrayDiskVendor}
- ? $out->{arrayDiskVendor} : 'Unknown Vendor';
- $product = exists $out->{arrayDiskProductID}
- ? $out->{arrayDiskProductID} : 'Unknown Product ID';
- $spare = get_hashval($out->{arrayDiskSpareState}, \%spare_state);
- $bus = exists $out->{arrayDiskBusType}
- ? get_hashval($out->{arrayDiskBusType}, \%bus_type) : undef;
- $media = exists $out->{arrayDiskMediaType}
- ? get_hashval($out->{arrayDiskMediaType}, \%media_type) : undef;
+ $nexus = convert_nexus(($out->{arrayDiskNexusID} || 9999));
+ $vendor = $out->{arrayDiskVendor} || 'Unknown vendor';
+ $product = $out->{arrayDiskProductID} || 'Unknown product ID';
+ $spare = get_hashval($out->{arrayDiskSpareState}, \%spare_state) || q{};
+ $bus = get_hashval($out->{arrayDiskBusType}, \%bus_type);
+ $media = get_hashval($out->{arrayDiskMediaType}, \%media_type);
+ $cert = defined $out->{arrayDiskDellCertified} ? $out->{arrayDiskDellCertified} : 1;
$capacity = exists $out->{arrayDiskLengthInMB}
? $out->{arrayDiskLengthInMB} * 1024**2 : -1;
}
}
else {
- $name = $out->{'Name'};
- $state = $out->{'State'};
- $status = $out->{'Status'};
- $fpred = lc($out->{'Failure Predicted'}) eq 'yes' ? 1 : 0;
- $progr = ' [' . $out->{'Progress'} . ']';
- $ctrl = $out->{'ctrl'};
+ $name = get_nonempty_string('Name', $out, 'Unknown disk');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $fpred = lc(get_nonempty_string('Failure Predicted', $out, q{})) eq 'yes' ? 1 : 0;
+ $progr = ' [' . get_nonempty_string('Progress', $out, q{}) . ']';
$nexus = join q{:}, $out->{ctrl}, $out->{'ID'};
- $vendor = $out->{'Vendor ID'} ne q{} ? $out->{'Vendor ID'} : 'Unknown Vendor';
- $product = $out->{'Product ID'} ne q{} ? $out->{'Product ID'} : 'Unknown Product ID';
- $media = $out->{'Media'};
- $spare = $out->{'Hot Spare'};
- $bus = $out->{'Bus Protocol'};
- $capacity = $out->{'Capacity'};
+ $vendor = get_nonempty_string('Vendor ID', $out, 'Unknown Vendor');
+ $product = get_nonempty_string('Product ID', $out, 'Unknown Product ID');
+ $media = get_nonempty_string('Media', $out, undef);
+ $bus = get_nonempty_string('Bus Protocol', $out, undef);
+ $spare = get_nonempty_string('Hot Spare', $out, q{});
+ $cert = get_nonempty_string('Certified', $out, 1);
+ $ctrl = $out->{ctrl};
+ $capacity = get_nonempty_string('Capacity', $out, q{});
$capacity =~ s{\A .*? \((\d+) \s bytes\) \z}{$1}xms;
if ($capacity eq 'Unavailable') {
$capacity = -1;
}
+ if ($cert eq 'Yes' or $cert eq 'Not Applicable') {
+ $cert = 1;
+ }
+ else {
+ $cert = 0;
+ }
}
- next PDISK if blacklisted('pdisk', $nexus);
$count{pdisk}++;
+ next PDISK if blacklisted('pdisk', $nexus);
$vendor =~ s{\s+\z}{}xms; # remove trailing whitespace
$product =~ s{\s+\z}{}xms; # remove trailing whitespace
$name, $vendor, $product, $capacity, $ctrl, $state, $progr;
report('storage', $msg, $E_WARNING, $nexus);
}
+ # Special case: Uncertified disk
+ elsif ($status eq 'Non-Critical' and !$cert) {
+ if (blacklisted('pdisk_cert', $nexus)) {
+ my $msg = sprintf '%s [%s %s, %s] on ctrl %d is %s, Not Certified',
+ $name, $vendor, $product, $capacity, $ctrl, $state;
+ report('storage', $msg, $E_OK, $nexus);
+ }
+ else {
+ my $msg = sprintf '%s [%s %s, %s] on ctrl %d is Not Certified',
+ $name, $vendor, $product, $capacity, $ctrl;
+ report('storage', $msg, $E_WARNING, $nexus);
+ }
+ }
+ # Special case: Foreign disk
+ elsif ($status eq 'Non-Critical' and $state eq 'Foreign'
+ and blacklisted('pdisk_foreign', $nexus)) {
+ my $msg = sprintf '%s [%s %s, %s] on ctrl %d is %s',
+ $name, $vendor, $product, $capacity, $ctrl, $state;
+ report('storage', $msg, $E_OK, $nexus);
+ }
# Default
elsif ($status ne 'Ok') {
my $msg = sprintf '%s [%s %s, %s] on ctrl %d needs attention: %s',
#-----------------------------------------
sub check_virtual_disks {
return if $#controllers == -1;
- return if blacklisted('vdisk', 'all');
my $name = undef;
my $nexus = undef;
1 => 'Concatenated',
2 => 'RAID-0',
3 => 'RAID-1',
+ 4 => 'UNSUPPORTED:raid-2',
+ 5 => 'UNSUPPORTED:raid-3',
+ 6 => 'UNSUPPORTED:raid-4',
7 => 'RAID-5',
8 => 'RAID-6',
+ 9 => 'UNSUPPORTED:raid-7',
10 => 'RAID-10',
+ 11 => 'UNSUPPORTED:raid-30',
12 => 'RAID-50',
+ 13 => 'UNSUPPORTED:addSpares',
+ 14 => 'UNSUPPORTED:deleteLogical',
+ 15 => 'UNSUPPORTED:transformLogical',
+ 18 => 'UNSUPPORTED:raid-0-plus-1',
19 => 'Concatenated RAID-1',
+ 20 => 'UNSUPPORTED:concatRaid-5',
+ 21 => 'UNSUPPORTED:noRaid',
+ 22 => 'UNSUPPORTED:volume',
+ 23 => 'UNSUPPORTED:raidMorph',
24 => 'RAID-60',
+ 25 => 'CacheCade',
);
# Check virtual disks on each of the controllers
VDISK:
foreach my $out (@output) {
if ($snmp) {
- $dev = $out->{virtualDiskDeviceName};
- $state = get_hashval($out->{virtualDiskState}, \%vdisk_state);
- $layout = get_hashval($out->{virtualDiskLayout}, \%vdisk_layout);
- $status = $snmp_status{$out->{virtualDiskComponentStatus}};
- $size = sprintf '%.2f GB', $out->{virtualDiskLengthInMB} / 1024;
- $progr = q{}; # can't get this from SNMP(?)
- $nexus = convert_nexus($out->{virtualDiskNexusID});
+ $dev = $out->{virtualDiskDeviceName} || 'Unknown device';
+ $state = get_hashval($out->{virtualDiskState}, \%vdisk_state) || 'Unknown state';
+ $layout = get_hashval($out->{virtualDiskLayout}, \%vdisk_layout) || 'Unknown layout';
+ $status = get_snmp_status($out->{virtualDiskComponentStatus});
+ $size = sprintf '%.2f GB', ($out->{virtualDiskLengthInMB} || 0) / 1024;
+ $progr = q{}; # not available via SNMP
+ $nexus = convert_nexus(($out->{virtualDiskNexusID} || 9999));
}
else {
- $dev = $out->{'Device Name'};
- $state = $out->{State};
- $status = $out->{Status};
- $layout = $out->{Layout};
- $size = $out->{Size};
- $progr = ' [' . $out->{Progress} . ']';
+ $dev = get_nonempty_string('Device Name', $out, 'Unknown device');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $layout = get_nonempty_string('Layout', $out, 'Unknown layout');
+ $size = get_nonempty_string('Size', $out, 'Unavailable');
$size =~ s{\A (.*GB).* \z}{$1}xms;
- $nexus = join q{:}, $out->{ctrl}, $out->{ID};
+ $progr = ' [' . get_nonempty_string('Progress', $out, q{}) . ']';
$ctrl = $out->{ctrl};
+ $nexus = join q{:}, $ctrl, get_nonempty_string('ID', $out, '9999');
}
- next VDISK if blacklisted('vdisk', $nexus);
$count{vdisk}++;
+ next VDISK if blacklisted('vdisk', $nexus);
# The device name is undefined sometimes
$dev = q{} if !defined $dev;
#-----------------------------------------
sub check_cache_battery {
return if $#controllers == -1;
- return if blacklisted('bat', 'all');
my $id = undef;
my $nexus = undef;
BATTERY:
foreach my $out (@output) {
if ($snmp) {
- $status = $snmp_status{$out->{batteryComponentStatus}};
- $state = get_hashval($out->{batteryState}, \%bat_state);
- $learn = get_hashval($out->{batteryLearnState}, \%bat_learn_state);
- $pred = get_hashval($out->{batteryPredictedCapacity}, \%bat_pred_cap);
- $ctrl = $out->{batteryConnectionControllerNumber} - 1;
- $nexus = convert_nexus($out->{batteryNexusID});
+ $status = get_snmp_status($out->{batteryComponentStatus});
+ $state = get_hashval($out->{batteryState}, \%bat_state) || 'Unknown state';
+ $learn = get_hashval($out->{batteryLearnState}, \%bat_learn_state) || 'Unknown learn state';
+ $pred = get_hashval($out->{batteryPredictedCapacity}, \%bat_pred_cap) || 'Unknown predicted capacity status';
+ $ctrl = $snmp_controller{$out->{batteryConnectionControllerNumber}};
+ $nexus = convert_nexus(($out->{batteryNexusID} || 9999));
$id = $nexus;
$id =~ s{\A \d+:(\d+) \z}{$1}xms;
}
else {
- $id = $out->{'ID'};
- $state = $out->{'State'};
- $status = $out->{'Status'};
- $learn = $out->{'Learn State'};
- $pred = $out->{'Predicted Capacity Status'};
+ $id = get_nonempty_string('ID', $out, 9999);
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $learn = get_nonempty_string('Learn State', $out, 'Unknown learn state');
+ $pred = get_nonempty_string('Predicted Capacity Status', $out, 'Unknown predicted capacity status');
$ctrl = $out->{'ctrl'};
$nexus = join q{:}, $out->{ctrl}, $id;
}
report('storage', $msg, $E_WARNING, $nexus);
}
# Default
- elsif ($status ne 'Ok') {
- my $msg = sprintf 'Cache Battery %d in controller %d needs attention: %s (%s)',
- $id, $ctrl, $state, $status;
- report('storage', $msg, $status2nagios{$status}, $nexus);
- }
- # Ok
else {
my $msg = sprintf 'Cache Battery %d in controller %d is %s',
$id, $ctrl, $state;
- report('storage', $msg, $E_OK, $nexus);
+ report('storage', $msg, $status2nagios{$status}, $nexus);
}
}
return;
#-----------------------------------------
sub check_connectors {
return if $#controllers == -1;
- return if blacklisted('conn', 'all');
my $nexus = undef;
my $name = undef;
CHANNEL:
foreach my $out (@output) {
if ($snmp) {
- $name = $out->{channelName};
- $status = $snmp_status{$out->{channelComponentStatus}};
- $state = get_hashval($out->{channelState}, \%conn_state);
- $type = get_hashval($out->{channelBusType}, \%conn_bustype);
- $nexus = convert_nexus($out->{channelNexusID});
+ $name = $out->{channelName} || 'Unknown channel';
+ $status = get_snmp_status($out->{channelComponentStatus});
+ $state = get_hashval($out->{channelState}, \%conn_state) || 'Unknown state';
+ $type = get_hashval($out->{channelBusType}, \%conn_bustype) || 'Unknown type';
+ $nexus = convert_nexus(($out->{channelNexusID} || 9999));
$ctrl = $nexus;
$ctrl =~ s{(\d+):\d+}{$1}xms;
- # workaround for ancient OMSA versions
- if (! defined $type) { $type = 'n/a'; }
}
else {
- $name = $out->{'Name'};
- $state = $out->{'State'};
- $status = $out->{'Status'};
- $type = $out->{'Connector Type'};
+ $name = get_nonempty_string('Name', $out, 'Unknown channel');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $type = get_nonempty_string('Connector Type', $out, 'Unknown type');
$ctrl = $out->{ctrl};
$nexus = join q{:}, $out->{ctrl}, $out->{'ID'};
}
# STORAGE: Check enclosures
#-----------------------------------------
sub check_enclosures {
- return if blacklisted('encl', 'all');
-
my $id = undef;
my $nexus = undef;
my $name = undef;
ENCLOSURE:
foreach my $out (@output) {
if ($snmp) {
- $id = $out->{enclosureNumber} - 1;
- $name = $out->{enclosureName};
- $state = get_hashval($out->{enclosureState}, \%encl_state);
- $status = $snmp_status{$out->{enclosureComponentStatus}};
- $firmware = exists $out->{enclosureFirmwareVersion}
- ? $out->{enclosureFirmwareVersion} : 'N/A';
- $nexus = convert_nexus($out->{enclosureNexusID});
+ $id = ($out->{enclosureNumber} || 10000) - 1;
+ $name = $out->{enclosureName} || 'Unknown enclosure';
+ $state = get_hashval($out->{enclosureState}, \%encl_state) || 'Unknown state';
+ $status = get_snmp_status($out->{enclosureComponentStatus});
+ $firmware = $out->{enclosureFirmwareVersion} || 'N/A';
+ $nexus = convert_nexus(($out->{enclosureNexusID} || 9999));
$ctrl = $nexus;
$ctrl =~ s{\A (\d+):.* \z}{$1}xms;
# for the next two, a value of 9999 means feature not available
- $occupied_slots = exists $out->{enclosureOccupiedSlotCount}
+ $occupied_slots = defined $out->{enclosureOccupiedSlotCount}
&& $out->{enclosureOccupiedSlotCount} != 9999
? $out->{enclosureOccupiedSlotCount} : undef;
- $total_slots = exists $out->{enclosureTotalSlots}
+ $total_slots = defined $out->{enclosureTotalSlots}
&& $out->{enclosureTotalSlots} != 9999
? $out->{enclosureTotalSlots} : undef;
}
else {
- $id = $out->{ID};
- $name = $out->{Name};
- $state = $out->{State};
- $status = $out->{Status};
- $firmware = $out->{'Firmware Version'} ne 'Not Applicable'
- ? $out->{'Firmware Version'} : 'N/A';
+ $id = get_nonempty_string('ID', $out, 9999);
+ $name = get_nonempty_string('Name', $out, 'Unknown enclosure');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $firmware = get_nonempty_string('Firmware Version', $out, 'N/A');
+ $firmware =~ s{Not\sApplicable}{N/A}xms;
$nexus = join q{:}, $out->{ctrl}, $id;
$ctrl = $out->{ctrl};
}
#-----------------------------------------
sub check_enclosure_fans {
return if $#controllers == -1;
- return if blacklisted('encl_fan', 'all');
my $nexus = undef;
my $name = undef;
FAN:
foreach my $out (@output) {
if ($snmp) {
- $name = $out->{fanName};
- $state = get_hashval($out->{fanState}, \%fan_state);
- $status = $snmp_status{$out->{fanComponentStatus}};
- $speed = $out->{fanProbeCurrValue};
- $encl_name = $out->{fanConnectionEnclosureName};
+ $name = $out->{fanName} || 'Unknown fan';
+ $state = get_hashval($out->{fanState}, \%fan_state) || 'Unknown state';
+ $status = get_snmp_status($out->{fanComponentStatus});
+ $speed = $out->{fanProbeCurrValue} || 'N/A';
+ $encl_name = $out->{fanConnectionEnclosureName} || 'Unknown enclosure';
$encl_id = $snmp_enclosure{$out->{fanConnectionEnclosureNumber}}{nexus};
- $nexus = convert_nexus($out->{fanNexusID});
+ $nexus = convert_nexus(($out->{fanNexusID} || 9999));
}
else {
- $name = $out->{'Name'};
- $state = $out->{'State'};
- $status = $out->{'Status'};
- $speed = $out->{'Speed'};
+ $name = get_nonempty_string('Name', $out, 'Unknown fan');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $speed = get_nonempty_string('Speed', $out, 'N/A');
$encl_id = join q{:}, $out->{ctrl}, $out->{'encl_id'};
$encl_name = $out->{encl_name};
- $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, $out->{'ID'};
+ $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, get_nonempty_string('ID', $out, '9999');
}
next FAN if blacklisted('encl_fan', $nexus);
#-----------------------------------------
sub check_enclosure_pwr {
return if $#controllers == -1;
- return if blacklisted('encl_ps', 'all');
my $nexus = undef;
my $name = undef;
PS:
foreach my $out (@output) {
if ($snmp) {
- $name = $out->{powerSupplyName};
- $state = get_hashval($out->{powerSupplyState}, \%ps_state);
- $status = $snmp_status{$out->{powerSupplyComponentStatus}};
+ $name = $out->{powerSupplyName} || 'Unknown PSU';
+ $state = get_hashval($out->{powerSupplyState}, \%ps_state) || 'Unknown state';
+ $status = get_snmp_status($out->{powerSupplyComponentStatus});
$encl_id = $snmp_enclosure{$out->{powerSupplyConnectionEnclosureNumber}}{nexus};
- $encl_name = $out->{powerSupplyConnectionEnclosureName};
- $nexus = convert_nexus($out->{powerSupplyNexusID});
+ $encl_name = $out->{powerSupplyConnectionEnclosureName} || 'Unknown enclosure';
+ $nexus = convert_nexus(($out->{powerSupplyNexusID} || 9999));
}
else {
- $name = $out->{'Name'};
- $state = $out->{'State'};
- $status = $out->{'Status'};
+ $name = get_nonempty_string('Name', $out, 'Unknown PSU');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
$encl_id = join q{:}, $out->{ctrl}, $out->{'encl_id'};
$encl_name = $out->{encl_name};
- $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, $out->{'ID'};
+ $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, get_nonempty_string('ID', $out, '9999');
}
next PS if blacklisted('encl_ps', $nexus);
#-----------------------------------------
sub check_enclosure_temp {
return if $#controllers == -1;
- return if blacklisted('encl_temp', 'all');
my $nexus = undef;
my $name = undef;
TEMP:
foreach my $out (@output) {
if ($snmp) {
- $name = $out->{temperatureProbeName};
- $state = get_hashval($out->{temperatureProbeState}, \%temp_state);
- $status = $snmp_status{$out->{temperatureProbeComponentStatus}};
- $unit = $out->{temperatureProbeUnit};
- $reading = exists $out->{temperatureProbeCurValue}
- ? $out->{temperatureProbeCurValue} : '[N/A]';
- $max_warn = exists $out->{temperatureProbeMaxWarning}
- ? $out->{temperatureProbeMaxWarning} : '[N/A]';
- $max_crit = exists $out->{temperatureProbeMaxCritical}
- ? $out->{temperatureProbeMaxCritical} : '[N/A]';
- $min_warn = exists $out->{temperatureProbeMinWarning}
- ? $out->{temperatureProbeMinWarning} : '[N/A]';
- $min_crit = exists $out->{temperatureProbeMinCritical}
- ? $out->{temperatureProbeMinCritical} : '[N/A]';
+ $name = $out->{temperatureProbeName} || 'Unknown temp probe';
+ $state = get_hashval($out->{temperatureProbeState}, \%temp_state) || 'Unknown state';
+ $status = get_snmp_probestatus($out->{temperatureProbeComponentStatus});
+ $unit = $out->{temperatureProbeUnit} || 'Unknown unit';
+ $reading = $out->{temperatureProbeCurValue} || '[N/A]';
+ $max_warn = $out->{temperatureProbeMaxWarning} || '[N/A]';
+ $max_crit = $out->{temperatureProbeMaxCritical} || '[N/A]';
+ $min_warn = $out->{temperatureProbeMinWarning} || '[N/A]';
+ $min_crit = $out->{temperatureProbeMinCritical} || '[N/A]';
$encl_id = $snmp_enclosure{$out->{temperatureConnectionEnclosureNumber}}{nexus};
- $encl_name = $out->{temperatureConnectionEnclosureName};
- $nexus = convert_nexus($out->{temperatureProbeNexusID});
+ $encl_name = $out->{temperatureConnectionEnclosureName} || 'Unknown enclosure';
+ $nexus = convert_nexus(($out->{temperatureProbeNexusID} || 9999));
}
else {
- $name = $out->{'Name'};
- $state = $out->{'State'};
- $status = $out->{'Status'};
+ $name = get_nonempty_string('Name', $out, 'Unknown temp probe');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
$unit = 'FIXME';
- $reading = $out->{'Reading'};
- $max_warn = $out->{'Maximum Warning Threshold'};
- $max_crit = $out->{'Maximum Failure Threshold'};
- $min_warn = $out->{'Minimum Warning Threshold'};
- $min_crit = $out->{'Minimum Failure Threshold'};
+ $reading = get_nonempty_string('Reading', $out, '[N/A]');
+ $max_warn = get_nonempty_string('Maximum Warning Threshold', $out, '[N/A]');
+ $max_crit = get_nonempty_string('Maximum Failure Threshold', $out, '[N/A]');
+ $min_warn = get_nonempty_string('Minimum Warning Threshold', $out, '[N/A]');
+ $min_crit = get_nonempty_string('Minimum Failure Threshold', $out, '[N/A]');
$encl_id = join q{:}, $out->{ctrl}, $out->{'encl_id'};
$encl_name = $out->{encl_name};
- $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, $out->{'ID'};
+ $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, get_nonempty_string('ID', $out, '9999');
}
next TEMP if blacklisted('encl_temp', $nexus);
$min_warn =~ s{\A \s* (-?\d+) \s* C? \s* \z}{$1}xms or $min_warn = '[N/A]';
$min_crit =~ s{\A \s* (-?\d+) \s* C? \s* \z}{$1}xms or $min_crit = '[N/A]';
+ # Convert temp units
+ if ($opt{tempunit} ne 'C') {
+ $reading = temp_from_celsius($reading, $opt{tempunit});
+ $max_warn = temp_from_celsius($max_warn, $opt{tempunit});
+ $max_crit = temp_from_celsius($max_crit, $opt{tempunit});
+ $min_warn = temp_from_celsius($min_warn, $opt{tempunit});
+ $min_crit = temp_from_celsius($min_crit, $opt{tempunit});
+ }
+
# Inactive temp probes
if ($status eq 'Unknown' and $state eq 'Inactive') {
my $msg = sprintf '%s in enclosure %s [%s] is %s',
report('storage', $msg, $E_OK, $nexus);
}
elsif ($status ne 'Ok' and $max_crit ne '[N/A]' and $reading > $max_crit) {
- my $msg = sprintf '%s in enclosure %s [%s] is critically high at %d C',
- $name, $encl_id, $encl_name, $reading;
+ my $msg = sprintf '%s in enclosure %s [%s] is critically high at %s %s',
+ $name, $encl_id, $encl_name, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $nexus);
}
elsif ($status ne 'Ok' and $max_warn ne '[N/A]' and $reading > $max_warn) {
- my $msg = sprintf '%s in enclosure %s [%s] is too high at %d C',
- $name, $encl_id, $encl_name, $reading;
+ my $msg = sprintf '%s in enclosure %s [%s] is too high at %s %s',
+ $name, $encl_id, $encl_name, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $nexus);
}
elsif ($status ne 'Ok' and $min_crit ne '[N/A]' and $reading < $min_crit) {
- my $msg = sprintf '%s in enclosure %s [%s] is critically low at %d C',
- $name, $encl_id, $encl_name, $reading;
+ my $msg = sprintf '%s in enclosure %s [%s] is critically low at %s %s',
+ $name, $encl_id, $encl_name, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $nexus);
}
elsif ($status ne 'Ok' and $min_warn ne '[N/A]' and $reading < $min_warn) {
- my $msg = sprintf '%s in enclosure %s [%s] is too low at %d C',
- $name, $encl_id, $encl_name, $reading;
+ my $msg = sprintf '%s in enclosure %s [%s] is too low at %s %s',
+ $name, $encl_id, $encl_name, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $nexus);
}
if (defined $reading && $reading =~ m{\A -?\d+ \z}xms) {
# take into account that with certain states the
# reading doesn't exist or is not an integer
- $msg .= sprintf ' at %s C', $reading;
+ $msg .= sprintf ' at %s %s', $reading, $opt{tempunit};
if ($min_warn eq '[N/A]' or $min_crit eq '[N/A]') {
$msg .= sprintf ' (max=%s/%s)', $max_warn, $max_crit;
}
if (defined $reading && $reading ne '[N/A]') {
# take into account that with certain states the
# reading doesn't exist or is not an integer
- $msg .= sprintf ' reads %d C', $reading;
+ $msg .= sprintf ' reads %s %s', $reading, $opt{tempunit};
if ($min_warn eq '[N/A]' or $min_crit eq '[N/A]') {
$msg .= sprintf ' (max=%s/%s)', $max_warn, $max_crit;
}
# Collect performance data
if (defined $opt{perfdata} && $reading ne '[N/A]') {
- $name =~ s{\A Temperature\sProbe\s(\d+) \z}{temp_$1}gxms;
- my $label = "enclosure_${encl_id}_${name}";
- my $mini = $label;
- $mini =~ s{enclosure_(.+?)_temp_(.+?)}{e$1t$2}xms;
+ my $index = $name;
+ $index =~ s{\A Temperature\sProbe\s(\d+) \z}{$1}gxms;
+ my $legacy_name = $name;
+ $legacy_name =~ s{\A Temperature\sProbe\s(\d+) \z}{temp_$1}gxms;
+ my $legacy_label = lc "enclosure_${encl_id}_${legacy_name}";
+ my $legacy_mini = $legacy_label;
+ $legacy_mini =~ s{enclosure_(.+?)_temp_(.+?)}{e$1t$2}xms;
push @perfdata, {
- label => $label,
- mini => $mini,
- value => $reading,
- warn => $max_warn,
- crit => $max_crit,
+ type => 'E',
+ id => $opt{perfdata} eq 'minimal' ? "${encl_id}_t${index}" : "${encl_id}_temp_${index}",
+ unit => $opt{tempunit},
+ label => q{},
+ legacy => $legacy_label,
+ mini => $legacy_mini,
+ value => $reading,
+ warn => $max_warn,
+ crit => $max_crit,
};
}
}
#-----------------------------------------
sub check_enclosure_emms {
return if $#controllers == -1;
- return if blacklisted('encl_emm', 'all');
my $nexus = undef;
my $name = undef;
EMM:
foreach my $out (@output) {
if ($snmp) {
- $name = $out->{enclosureManagementModuleName};
- $state = get_hashval($out->{enclosureManagementModuleState}, \%emms_state);
- $status = $snmp_status{$out->{enclosureManagementModuleComponentStatus}};
+ $name = $out->{enclosureManagementModuleName} || 'Unknown EMM';
+ $state = get_hashval($out->{enclosureManagementModuleState}, \%emms_state) || 'Unknown state';
+ $status = get_snmp_status($out->{enclosureManagementModuleComponentStatus});
$encl_id = $snmp_enclosure{$out->{enclosureManagementModuleConnectionEnclosureNumber}}{nexus};
- $encl_name = $out->{enclosureManagementModuleConnectionEnclosureName};
- $nexus = convert_nexus($out->{enclosureManagementModuleNexusID});
+ $encl_name = $out->{enclosureManagementModuleConnectionEnclosureName} || 'Unknown enclosure';
+ $nexus = convert_nexus(($out->{enclosureManagementModuleNexusID} || 9999));
}
else {
- $name = $out->{'Name'};
- $state = $out->{'State'};
- $status = $out->{'Status'};
+ $name = get_nonempty_string('Name', $out, 'Unknown EMM');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $status = get_nonempty_string('Status', $out, 'Unknown');
$encl_id = join q{:}, $out->{ctrl}, $out->{'encl_id'};
$encl_name = $out->{encl_name};
- $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, $out->{'ID'};
+ $nexus = join q{:}, $out->{ctrl}, $out->{'encl_id'}, get_nonempty_string('ID', $out, '9999');
}
next EMM if blacklisted('encl_emm', $nexus);
# CHASSIS: Check memory modules
#-----------------------------------------
sub check_memory {
- return if blacklisted('dimm', 'all');
-
my $index = undef;
my $status = undef;
my $location = undef;
foreach my $out (@output) {
@failures = (); # Initialize
if ($snmp) {
- $index = $out->{memoryDeviceIndex};
- $status = $snmp_status{$out->{memoryDeviceStatus}};
- $location = $out->{memoryDeviceLocationName};
- $size = sprintf '%d MB', $out->{memoryDeviceSize}/1024;
- $modes = $out->{memoryDeviceFailureModes};
+ $index = ($out->{memoryDeviceIndex} || 10000) - 1;
+ $status = get_snmp_status($out->{memoryDeviceStatus});
+ $location = $out->{memoryDeviceLocationName} || 'Unknown location';
+ $size = sprintf '%d MB', ($out->{memoryDeviceSize} || 0)/1024;
+ $modes = $out->{memoryDeviceFailureModes} || -9999;
if ($modes > 0) {
foreach my $mask (sort keys %failure_mode) {
if (($modes & $mask) != 0) { push @failures, $failure_mode{$mask}; }
}
}
+ elsif ($modes == -9999) {
+ push @failures, q{ERROR: Failure modes not available via SNMP};
+ }
}
else {
- $index = $out->{'Type'} eq '[Not Occupied]' ? undef : $out->{'Index'};
- $status = $out->{'Status'};
- $location = $out->{'Connector Name'};
- $size = $out->{'Size'};
+ my $type = get_nonempty_string('Type', $out, q{});
+ $index = $type eq '[Not Occupied]' ? undef : get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $location = get_nonempty_string('Connector Name', $out, 'Unknown location');
+ $size = get_nonempty_string('Size', $out, 0);
if (defined $size) {
$size =~ s{\s\s}{ }gxms;
}
$msize =~ s{\A (\d+) \s MB}{$1}xms;
$count{mem} += $msize;
- next DIMM if blacklisted('dimm', $index);
-
# Ignore empty memory slots
next DIMM if !defined $index;
+
$count{dimm}++;
+ next DIMM if blacklisted('dimm', $index);
if ($status ne 'Ok') {
my $msg = undef;
# CHASSIS: Check fans
#-----------------------------------------
sub check_fans {
- return if blacklisted('fan', 'all');
-
my $index = undef;
my $status = undef;
my $reading = undef;
FAN:
foreach my $out (@output) {
if ($snmp) {
- $index = $out->{coolingDeviceIndex};
- $status = $snmp_probestatus{$out->{coolingDeviceStatus}};
- $reading = $out->{coolingDeviceReading};
- $location = $out->{coolingDeviceLocationName};
- $max_crit = exists $out->{coolingDeviceUpperCriticalThreshold}
- ? $out->{coolingDeviceUpperCriticalThreshold} : 0;
- $max_warn = exists $out->{coolingDeviceUpperNonCriticalThreshold}
- ? $out->{coolingDeviceUpperNonCriticalThreshold} : 0;
+ $index = ($out->{coolingDeviceIndex} || 10000) - 1;
+ $status = get_snmp_probestatus($out->{coolingDeviceStatus});
+ $reading = $out->{coolingDeviceReading} || 0;
+ $location = $out->{coolingDeviceLocationName} || 'Unknown location';
+ $max_crit = $out->{coolingDeviceUpperCriticalThreshold} || 0;
+ $max_warn = $out->{coolingDeviceUpperNonCriticalThreshold} || 0;
}
else {
- $index = $out->{'Index'};
- $status = $out->{'Status'};
- $reading = $out->{'Reading'};
- $location = $out->{'Probe Name'};
- $max_crit = $out->{'Maximum Failure Threshold'} ne '[N/A]'
- ? $out->{'Maximum Failure Threshold'} : 0;
- $max_warn = $out->{'Maximum Warning Threshold'} ne '[N/A]'
- ? $out->{'Maximum Warning Threshold'} : 0;
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $reading = get_nonempty_string('Reading', $out, 0);
+ $location = get_nonempty_string('Probe Name', $out, 'Unknown location');
+ $max_crit = get_nonempty_string('Maximum Failure Threshold', $out, 0);
+ $max_warn = get_nonempty_string('Maximum Warning Threshold', $out, 0);
+ if ($max_crit eq '[N/A]') { $max_crit = 0; }
+ if ($max_warn eq '[N/A]') { $max_warn = 0; }
$reading =~ s{\A (\d+).* \z}{$1}xms;
$max_warn =~ s{\A (\d+).* \z}{$1}xms;
$max_crit =~ s{\A (\d+).* \z}{$1}xms;
}
- next FAN if blacklisted('fan', $index);
$count{fan}++;
+ next FAN if blacklisted('fan', $index);
- if ($status ne 'Ok') {
- my $msg = sprintf 'Chassis fan %d [%s] needs attention: %s',
- $index, $location, $status;
- my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
- report('chassis', $msg, $err, $index);
- }
- else {
- my $msg = sprintf 'Chassis fan %d [%s]: %s',
- $index, $location, $reading;
- report('chassis', $msg, $E_OK, $index);
- }
+ # Default
+ my $msg = sprintf 'Chassis fan %d [%s] reading: %s RPM',
+ $index, $location, $reading;
+ my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
+ report('chassis', $msg, $err, $index);
# Collect performance data
if (defined $opt{perfdata}) {
- my $pname = lc $location;
+ my $pname = $location;
$pname =~ s{\s}{_}gxms;
$pname =~ s{proc_}{cpu#}xms;
+ my $legacy_pname = $pname;
+ $pname =~ s{_rpm\z}{}ixms;
push @perfdata, {
- label => "fan_${index}_${pname}",
- mini => "f$index",
- value => $reading,
- warn => $max_warn,
- crit => $max_crit,
+ type => 'F',
+ id => $index,
+ unit => 'rpm',
+ label => $pname,
+ legacy => lc "fan_${index}_${legacy_pname}",
+ mini => "f$index",
+ value => $reading,
+ warn => $max_warn,
+ crit => $max_crit,
};
}
}
# CHASSIS: Check power supplies
#-----------------------------------------
sub check_powersupplies {
- return if blacklisted('ps', 'all');
-
my $index = undef;
my $status = undef;
my $type = undef;
if ($snmp) {
@states = (); # contains states for the PS
- $index = $out->{powerSupplyIndex} - 1;
- $status = $snmp_status{$out->{powerSupplyStatus}};
- $type = get_hashval($out->{powerSupplyType}, \%ps_type);
- $err_type = defined $out->{powerSupplyConfigurationErrorType}
- ? $ps_config_error_type{$out->{powerSupplyConfigurationErrorType}} : undef;
+ $index = ($out->{powerSupplyIndex} || 10000) - 1;
+ $status = get_snmp_status($out->{powerSupplyStatus});
+ $type = get_hashval($out->{powerSupplyType}, \%ps_type) || 'Unknown type';
+ $err_type = get_hashval($out->{powerSupplyConfigurationErrorType}, \%ps_config_error_type);
# get the combined state from the StatusReading OID
+ my $raw_state = $out->{powerSupplySensorState} || 0;
foreach my $mask (sort keys %ps_state) {
- if (($out->{powerSupplySensorState} & $mask) != 0) {
+ if (($raw_state & $mask) != 0) {
push @states, $ps_state{$mask};
}
}
$state = join q{, }, @states;
}
else {
- $index = $out->{'Index'};
- $status = $out->{'Status'};
- $type = $out->{'Type'};
- $state = $out->{'Online Status'};
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $type = get_nonempty_string('Type', $out, 'Unknown type');
+ $state = get_nonempty_string('Online Status', $out, 'Unknown state');
}
- next PS if blacklisted('ps', $index);
$count{power}++;
+ next PS if blacklisted('ps', $index);
if ($status ne 'Ok') {
my $msg = sprintf 'Power Supply %d [%s] needs attention: %s',
# CHASSIS: Check temperatures
#-----------------------------------------
sub check_temperatures {
- return if blacklisted('temp', 'all');
-
my $index = undef;
my $status = undef;
my $reading = undef;
TEMP:
foreach my $out (@output) {
if ($snmp) {
- $index = $out->{temperatureProbeIndex} - 1;
- $status = $snmp_probestatus{$out->{temperatureProbeStatus}};
- $location = $out->{temperatureProbeLocationName};
- $reading = exists $out->{temperatureProbeReading}
- ? $out->{temperatureProbeReading} / 10 : '[N/A]';
- $max_crit = exists $out->{temperatureProbeUpperCriticalThreshold}
- ? $out->{temperatureProbeUpperCriticalThreshold} / 10 : '[N/A]';
- $max_warn = exists $out->{temperatureProbeUpperNonCriticalThreshold}
- ? $out->{temperatureProbeUpperNonCriticalThreshold} / 10 : '[N/A]';
- $min_crit = exists $out->{temperatureProbeLowerCriticalThreshold}
- ? $out->{temperatureProbeLowerCriticalThreshold} / 10 : '[N/A]';
- $min_warn = exists $out->{temperatureProbeLowerNonCriticalThreshold}
- ? $out->{temperatureProbeLowerNonCriticalThreshold} / 10 : '[N/A]';
+ $index = ($out->{temperatureProbeIndex} || 10000) - 1;
+ $status = get_snmp_probestatus($out->{temperatureProbeStatus});
+ $location = $out->{temperatureProbeLocationName} || 'Unknown location';
$type = get_hashval($out->{temperatureProbeType}, \%probe_type);
- $discrete = exists $out->{temperatureProbeDiscreteReading}
- ? $out->{temperatureProbeDiscreteReading} : '[N/A]';
+ $reading = $out->{temperatureProbeReading} || '[N/A]';
+ $max_crit = $out->{temperatureProbeUpperCriticalThreshold} || '[N/A]';
+ $max_warn = $out->{temperatureProbeUpperNonCriticalThreshold} || '[N/A]';
+ $min_crit = $out->{temperatureProbeLowerCriticalThreshold} || '[N/A]';
+ $min_warn = $out->{temperatureProbeLowerNonCriticalThreshold} || '[N/A]';
+ $discrete = $out->{temperatureProbeDiscreteReading} || '[N/A]';
+
+ # If numeric values, i.e. not discrete
+ $reading /= 10 if $reading =~ m{\A \d+ \z}xms;
+ $max_crit /= 10 if $max_crit =~ m{\A \d+ \z}xms;
+ $max_warn /= 10 if $max_warn =~ m{\A \d+ \z}xms;
+ $min_crit /= 10 if $min_crit =~ m{\A \d+ \z}xms;
+ $min_warn /= 10 if $min_warn =~ m{\A \d+ \z}xms;
+
# workaround for bad temp probes
if ($type eq 'AmbientESM' and $reading !~ m{\A \d+(\.\d+)? \z}xms) {
$type = 'Discrete';
}
}
else {
- $index = $out->{'Index'};
- $status = $out->{'Status'};
- $reading = $out->{'Reading'}; $reading =~ s{\.0\s+C}{}xms;
- $location = $out->{'Probe Name'};
- $max_crit = $out->{'Maximum Failure Threshold'}; $max_crit =~ s{\.0\s+C}{}xms;
- $max_warn = $out->{'Maximum Warning Threshold'}; $max_warn =~ s{\.0\s+C}{}xms;
- $min_crit = $out->{'Minimum Failure Threshold'}; $min_crit =~ s{\.0\s+C}{}xms;
- $min_warn = $out->{'Minimum Warning Threshold'}; $min_warn =~ s{\.0\s+C}{}xms;
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $location = get_nonempty_string('Probe Name', $out, 'Unknown location');
+ $reading = get_nonempty_string('Reading', $out, '[N/A]');
+ $max_crit = get_nonempty_string('Maximum Failure Threshold', $out, '[N/A]');
+ $max_warn = get_nonempty_string('Maximum Warning Threshold', $out, '[N/A]');
+ $min_crit = get_nonempty_string('Minimum Failure Threshold', $out, '[N/A]');
+ $min_warn = get_nonempty_string('Minimum Warning Threshold', $out, '[N/A]');
+
+ # Cleaning the temp readings
+ $reading =~ s{\.0\s+C}{}xms;
+ $max_crit =~ s{\.0\s+C}{}xms;
+ $max_warn =~ s{\.0\s+C}{}xms;
+ $min_crit =~ s{\.0\s+C}{}xms;
+ $min_warn =~ s{\.0\s+C}{}xms;
+
$type = $reading =~ m{\A\d+\z}xms ? 'AmbientESM' : 'Discrete';
$discrete = $reading;
}
- next TEMP if blacklisted('temp', $index);
$count{temp}++;
+ next TEMP if blacklisted('temp', $index);
+
+ # Convert temp units
+ if ($opt{tempunit} ne 'C') {
+ $reading = temp_from_celsius($reading, $opt{tempunit});
+ $max_warn = temp_from_celsius($max_warn, $opt{tempunit});
+ $max_crit = temp_from_celsius($max_crit, $opt{tempunit});
+ $min_warn = temp_from_celsius($min_warn, $opt{tempunit});
+ $min_crit = temp_from_celsius($min_crit, $opt{tempunit});
+ }
if ($type eq 'Discrete') {
my $msg = sprintf 'Temperature probe %d [%s] is %s',
# First check according to custom thresholds
if (exists $crit_threshold{$index}{max} and $reading > $crit_threshold{$index}{max}) {
# Custom critical MAX
- my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom max=%d)',
- $index, $location, $reading, $crit_threshold{$index}{max};
+ my $msg = sprintf 'Temperature Probe %d [%s] reads %s %s (custom max=%s)',
+ $index, $location, $reading, $opt{tempunit}, $crit_threshold{$index}{max};
report('chassis', $msg, $E_CRITICAL, $index);
}
elsif (exists $warn_threshold{$index}{max} and $reading > $warn_threshold{$index}{max}) {
# Custom warning MAX
- my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom max=%d)',
- $index, $location, $reading, $warn_threshold{$index}{max};
+ my $msg = sprintf 'Temperature Probe %d [%s] reads %s %s (custom max=%s)',
+ $index, $location, $reading, $opt{tempunit}, $warn_threshold{$index}{max};
report('chassis', $msg, $E_WARNING, $index);
}
elsif (exists $crit_threshold{$index}{min} and $reading < $crit_threshold{$index}{min}) {
# Custom critical MIN
- my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom min=%d)',
- $index, $location, $reading, $crit_threshold{$index}{min};
+ my $msg = sprintf 'Temperature Probe %d [%s] reads %s %s (custom min=%s)',
+ $index, $location, $reading, $opt{tempunit}, $crit_threshold{$index}{min};
report('chassis', $msg, $E_CRITICAL, $index);
}
elsif (exists $warn_threshold{$index}{min} and $reading < $warn_threshold{$index}{min}) {
# Custom warning MIN
- my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom min=%d)',
- $index, $location, $reading, $warn_threshold{$index}{min};
+ my $msg = sprintf 'Temperature Probe %d [%s] reads %s %s (custom min=%s)',
+ $index, $location, $reading, $opt{tempunit}, $warn_threshold{$index}{min};
report('chassis', $msg, $E_WARNING, $index);
}
elsif ($status ne 'Ok' and $max_crit ne '[N/A]' and $reading > $max_crit) {
- my $msg = sprintf 'Temperature Probe %d [%s] is critically high at %d C',
- $index, $location, $reading;
+ my $msg = sprintf 'Temperature Probe %d [%s] is critically high at %s %s',
+ $index, $location, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $index);
}
elsif ($status ne 'Ok' and $max_warn ne '[N/A]' and $reading > $max_warn) {
- my $msg = sprintf 'Temperature Probe %d [%s] is too high at %d C',
- $index, $location, $reading;
+ my $msg = sprintf 'Temperature Probe %d [%s] is too high at %s %s',
+ $index, $location, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $index);
}
elsif ($status ne 'Ok' and $min_crit ne '[N/A]' and $reading < $min_crit) {
- my $msg = sprintf 'Temperature Probe %d [%s] is critically low at %d C',
- $index, $location, $reading;
+ my $msg = sprintf 'Temperature Probe %d [%s] is critically low at %s %s',
+ $index, $location, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $index);
}
elsif ($status ne 'Ok' and $min_warn ne '[N/A]' and $reading < $min_warn) {
- my $msg = sprintf 'Temperature Probe %d [%s] is too low at %d C',
- $index, $location, $reading;
+ my $msg = sprintf 'Temperature Probe %d [%s] is too low at %s %s',
+ $index, $location, $reading, $opt{tempunit};
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $index);
}
# Ok
else {
- my $msg = sprintf 'Temperature Probe %d [%s] reads %d C',
- $index, $location, $reading;
+ my $msg = sprintf 'Temperature Probe %d [%s] reads %s %s',
+ $index, $location, $reading, $opt{tempunit};
if ($min_warn eq '[N/A]' and $min_crit eq '[N/A]') {
$msg .= sprintf ' (max=%s/%s)', $max_warn, $max_crit;
}
# Collect performance data
if (defined $opt{perfdata}) {
- my $pname = lc $location;
+ my $pname = $location;
$pname =~ s{\s}{_}gxms;
- $pname =~ s{_temp\z}{}xms;
+ $pname =~ s{_temp\z}{}ixms;
$pname =~ s{proc_}{cpu#}xms;
push @perfdata, {
- label => "temp_${index}_${pname}",
- mini => "t$index",
- value => $reading,
- warn => $max_warn,
- crit => $max_crit,
+ type => 'T',
+ id => $index,
+ unit => $opt{tempunit},
+ label => $pname,
+ legacy => lc "temp_${index}_${pname}",
+ mini => "t$index",
+ value => $reading,
+ warn => $max_warn,
+ crit => $max_crit,
};
}
}
# CHASSIS: Check processors
#-----------------------------------------
sub check_processors {
- return if blacklisted('cpu', 'all');
-
my $index = undef;
my $status = undef;
my $state = undef;
foreach my $out (@output) {
if ($snmp) {
$index = exists $out->{processorDeviceStatusIndex}
- ? $out->{processorDeviceStatusIndex} - 1
- : $out->{processorDeviceIndex} - 1;
+ ? ($out->{processorDeviceStatusIndex} || 10000) - 1
+ : ($out->{processorDeviceIndex} || 10000) - 1;
$status = exists $out->{processorDeviceStatusStatus}
- ? $snmp_status{$out->{processorDeviceStatusStatus}}
- : $snmp_status{$out->{processorDeviceStatus}};
- if (exists $out->{processorDeviceStatusReading}) {
+ ? get_snmp_status($out->{processorDeviceStatusStatus})
+ : get_snmp_status($out->{processorDeviceStatus});
+ if (defined $out->{processorDeviceStatusReading}) {
my @states = (); # contains states for the CPU
# get the combined state from the StatusReading OID
$state = join q{, }, @states;
}
else {
- $state = get_hashval($out->{processorDeviceStatusState}, \%cpu_state);
+ $state = get_hashval($out->{processorDeviceStatusState}, \%cpu_state) || 'Unknown state';
}
- $man = $out->{processorDeviceManufacturerName};
- $family = (exists $out->{processorDeviceFamily}
- and exists $cpu_family{$out->{processorDeviceFamily}})
+ $man = $out->{processorDeviceManufacturerName} || undef;
+ $family = (defined $out->{processorDeviceFamily}
+ and defined $cpu_family{$out->{processorDeviceFamily}})
? $cpu_family{$out->{processorDeviceFamily}} : undef;
- $speed = $out->{processorDeviceCurrentSpeed};
- $brand = $out->{processorDeviceBrandName};
+ $speed = $out->{processorDeviceCurrentSpeed} || undef;
+ $brand = $out->{processorDeviceBrandName} || undef;
}
else {
- $index = $out->{'Index'};
- $status = $out->{'Status'};
- $state = $out->{'State'};
- $brand = exists $out->{'Processor Brand'} ? $out->{'Processor Brand'} : undef;
- $family = exists $out->{'Processor Family'} ? $out->{'Processor Family'} : undef;
- $man = exists $out->{'Processor Manufacturer'} ? $out->{'Processor Manufacturer'} : undef;
- $speed = exists $out->{'Current Speed'} ? $out->{'Current Speed'} : undef;
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $brand = get_nonempty_string('Processor Brand', $out, undef);
+ $family = get_nonempty_string('Processor Family', $out, undef);
+ $man = get_nonempty_string('Processor Manufacturer', $out, undef);
+ $speed = get_nonempty_string('Current Speed', $out, undef);
}
- next CPU if blacklisted('cpu', $index);
-
# Ignore unoccupied CPU slots (omreport)
next CPU if (defined $out->{'Processor Manufacturer'}
and $out->{'Processor Manufacturer'} eq '[Not Occupied]')
or (defined $out->{'Processor Brand'} and $out->{'Processor Brand'} eq '[Not Occupied]');
# Ignore unoccupied CPU slots (snmp)
- if ($snmp and exists $out->{processorDeviceStatusReading}
+ if ($snmp and defined $out->{processorDeviceStatusReading}
and $out->{processorDeviceStatusReading} == 0) {
next CPU;
}
$count{cpu}++;
+ next CPU if blacklisted('cpu', $index);
if (defined $brand) {
$brand =~ s{\s\s+}{ }gxms;
# CHASSIS: Check voltage probes
#-----------------------------------------
sub check_volts {
- return if blacklisted('volt', 'all');
-
my $index = undef;
my $status = undef;
my $reading = undef;
my $location = undef;
+ my $max_crit = undef;
+ my $max_warn = undef;
my @output = ();
if ($snmp) {
VOLT:
foreach my $out (@output) {
if ($snmp) {
- $index = $out->{voltageProbeIndex} - 1;
- $status = $snmp_probestatus{$out->{voltageProbeStatus}};
- $reading = exists $out->{voltageProbeReading}
+ $index = ($out->{voltageProbeIndex} || 10000) - 1;
+ $status = get_snmp_probestatus($out->{voltageProbeStatus});
+ $reading = defined $out->{voltageProbeReading}
? sprintf('%.3f V', $out->{voltageProbeReading}/1000)
- : get_hashval($out->{voltageProbeDiscreteReading}, \%volt_discrete_reading);
- $location = $out->{voltageProbeLocationName};
+ : (get_hashval($out->{voltageProbeDiscreteReading}, \%volt_discrete_reading) || 'Unknown reading');
+ $location = $out->{voltageProbeLocationName} || 'Unknown location';
+ $max_crit = $out->{voltageProbeUpperCriticalThreshold} || 0;
+ $max_warn = $out->{voltageProbeUpperNonCriticalThreshold} || 0;
}
else {
- $index = $out->{'Index'};
- $status = $out->{'Status'};
- $reading = $out->{'Reading'};
- $location = $out->{'Probe Name'};
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $reading = get_nonempty_string('Reading', $out, 'Unknown reading');
+ $location = get_nonempty_string('Probe Name', $out, 'Unknown location');
+ $max_crit = get_nonempty_string('Maximum Failure Threshold', $out, 0);
+ $max_warn = get_nonempty_string('Maximum Warning Threshold', $out, 0);
+
+ $max_crit = 0 if $max_crit eq '[N/A]';
+ $max_warn = 0 if $max_warn eq '[N/A]';
}
- next VOLT if blacklisted('volt', $index);
$count{volt}++;
+ next VOLT if blacklisted('volt', $index);
my $msg = sprintf 'Voltage sensor %d [%s] is %s',
$index, $location, $reading;
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $index);
+
+ # Collect performance data
+ if (defined $opt{perfdata} and !$opt{legacy_perfdata}) {
+ $reading =~ s{\s+V\z}{}xms; # remove unit
+ $reading =~ s{\.000\z}{}xms; # if integer
+ next VOLT if $reading !~ m{\A \d+(\.\d+)? \z}xms; # discrete reading (not number)
+ my $label = join q{_}, $location;
+ $label =~ s{\s}{_}gxms;
+ push @perfdata, {
+ type => 'V',
+ id => $index,
+ unit => 'V',
+ label => $label,
+ value => $reading,
+ warn => 0,
+ crit => 0,
+ };
+ }
}
return;
}
# CHASSIS: Check batteries
#-----------------------------------------
sub check_batteries {
- return if blacklisted('bp', 'all');
-
my $index = undef;
my $status = undef;
my $reading = undef;
BATTERY:
foreach my $out (@output) {
if ($snmp) {
- $index = $out->{batteryIndex} - 1;
- $status = $snmp_status{$out->{batteryStatus}};
- $reading = get_hashval($out->{batteryReading}, \%bat_reading);
- $location = $out->{batteryLocationName};
+ $index = ($out->{batteryIndex} || 10000) - 1;
+ $status = get_snmp_status($out->{batteryStatus});
+ $reading = get_hashval($out->{batteryReading}, \%bat_reading) || 'Unknown reading';
+ $location = $out->{batteryLocationName} || 'Unknown location';
}
else {
- $index = $out->{'Index'};
- $status = $out->{'Status'};
- $reading = $out->{'Reading'};
- $location = $out->{'Probe Name'};
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $reading = get_nonempty_string('Reading', $out, 'Unknown reading');
+ $location = get_nonempty_string('Probe Name', $out, 'Unknown location');
}
- next BATTERY if blacklisted('bp', $index);
$count{bat}++;
+ next BATTERY if blacklisted('bp', $index);
my $msg = sprintf 'Battery probe %d [%s] is %s',
$index, $location, $reading;
# CHASSIS: Check amperage probes (power monitoring)
#-----------------------------------------
sub check_pwrmonitoring {
- return if blacklisted('amp', 'all');
-
my $index = undef;
my $status = undef;
my $reading = undef;
AMP:
foreach my $out (@output) {
if ($snmp) {
- $index = $out->{amperageProbeIndex} - 1;
- $status = $snmp_status{$out->{amperageProbeStatus}};
+ $index = ($out->{amperageProbeIndex} || 10000) - 1;
+ $status = get_snmp_probestatus($out->{amperageProbeStatus});
$type = get_hashval($out->{amperageProbeType}, \%amp_type);
$reading = $type eq 'amperageProbeTypeIsDiscrete'
? get_hashval($out->{amperageProbeDiscreteReading}, \%amp_discrete)
- : $out->{amperageProbeReading};
- $location = $out->{amperageProbeLocationName};
- $max_crit = exists $out->{amperageProbeUpperCriticalThreshold}
- ? $out->{amperageProbeUpperCriticalThreshold} : 0;
- $max_warn = exists $out->{amperageProbeUpperNonCriticalThreshold}
- ? $out->{amperageProbeUpperNonCriticalThreshold} : 0;
+ : ($out->{amperageProbeReading} || 0);
+ $location = $out->{amperageProbeLocationName} || 'Unknown location';
+ $max_crit = $out->{amperageProbeUpperCriticalThreshold} || 0;
+ $max_warn = $out->{amperageProbeUpperNonCriticalThreshold} || 0;
$unit = exists $amp_unit{$amp_type{$out->{amperageProbeType}}}
? $amp_unit{$amp_type{$out->{amperageProbeType}}} : 'mA';
- # workaround for broken probes
- if (!defined $reading) {
- $type = 'amperageProbeTypeIsDiscrete';
- $reading = '[N/A]';
- $unit = q{};
- }
-
# calculate proper values and set unit for ampere probes
if ($unit eq 'hA' and $type ne 'amperageProbeTypeIsDiscrete') {
$reading /= 10;
$max_warn /= 10;
$unit = 'A';
}
+ if ($unit eq 'mA' and $type ne 'amperageProbeTypeIsDiscrete') {
+ $reading /= 1000;
+ $max_crit /= 1000;
+ $max_warn /= 1000;
+ $unit = 'A';
+ }
}
else {
- $index = $out->{'Index'};
- next AMP if (!defined $index || $index !~ m/^\d+$/x);
- $status = $out->{'Status'};
- $reading = $out->{'Reading'};
- $location = $out->{'Probe Name'};
- $max_crit = $out->{'Failure Threshold'} ne '[N/A]'
- ? $out->{'Failure Threshold'} : 0;
- $max_warn = $out->{'Warning Threshold'} ne '[N/A]'
- ? $out->{'Warning Threshold'} : 0;
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $reading = get_nonempty_string('Reading', $out, 'Unknown reading');
+ $location = get_nonempty_string('Probe Name', $out, 'Unknown location');
+ $max_crit = get_nonempty_string('Failure Threshold', $out, 0);
+ $max_warn = get_nonempty_string('Warning Threshold', $out, 0);
+
+ $max_crit = 0 if $max_crit eq '[N/A]';
+ $max_warn = 0 if $max_warn eq '[N/A]';
+
$reading =~ s{\A (\d+.*?)\s+([a-zA-Z]+) \s*\z}{$1}xms;
- $unit = $2;
+ $unit = $2 || 'unknown';
$max_warn =~ s{\A (\d+.*?)\s+[a-zA-Z]+ \s*\z}{$1}xms;
$max_crit =~ s{\A (\d+.*?)\s+[a-zA-Z]+ \s*\z}{$1}xms;
}
- next AMP if blacklisted('amp', $index);
next AMP if $index !~ m{\A \d+ \z}xms;
# Special case: Probe is present but unknown. This happens via
# disabled due to non-redundant and/or non-instrumented power
# supplies.
# E.g. R410 with newer BMC firmware and 1 power supply
- if ($snmp && $status eq 'Unknown' && $reading eq '[N/A]') {
+ if ($snmp && $status eq 'Unknown' && $reading == 0) {
next AMP;
}
$count{amp}++;
+ next AMP if blacklisted('amp', $index);
# Special case: Discrete reading
if (defined $type and $type eq 'amperageProbeTypeIsDiscrete') {
my $msg = sprintf 'Amperage probe %d [%s] is %s',
$index, $location, $reading;
- report('chassis', $msg, $status2nagios{$status}, $index);
+ my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
+ report('chassis', $msg, $err, $index);
}
# Default
else {
my $msg = sprintf 'Amperage probe %d [%s] reads %s %s',
$index, $location, $reading, $unit;
- report('chassis', $msg, $status2nagios{$status}, $index);
+ my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
+ report('chassis', $msg, $err, $index);
}
# Collect performance data
if (defined $opt{perfdata}) {
next AMP if $reading !~ m{\A \d+(\.\d+)? \z}xms; # discrete reading (not number)
- my $label = join q{_}, 'pwr_mon', $index, lc $location;
+ my $label = join q{_}, $location;
$label =~ s{\s}{_}gxms;
push @perfdata, {
- label => $label,
- mini => "p${index}" . lc $unit,
- value => $reading,
- warn => $max_warn,
- crit => $max_crit,
+ type => $unit,
+ id => $index,
+ unit => $unit,
+ label => $label,
+ legacy => (join q{_}, 'pwr_mon', $index, lc $label),
+ mini => "p${index}" . lc $unit,
+ value => $reading,
+ warn => $max_warn,
+ crit => $max_crit,
};
}
}
# find used indexes
foreach (@perfdata) {
- if ($_->{label} =~ m/\A pwr_mon_(\d+)/xms) {
+ if ($_->{label} =~ m/\A [WA](\d+)/xms) {
$used{$1} = 1;
}
}
AMP2:
foreach my $line (@{ run_command("$omreport $omopt_chassis pwrmonitoring -fmt ssv") }) {
chop $line;
- if ($line eq 'Location;Reading') {
+ if ($line eq 'Location;Reading' or $line eq 'Amperage') {
$found = 1;
next AMP2;
}
$found = 0;
next AMP2;
}
- if ($found and $line =~ m/\A ([^;]+?) ; (\d*\.\d+) \s [AW] \z/xms) {
- my $aname = lc $1;
- my $aval = $2;
+ if ($found and $line =~ m/\A ([^;]+?) ; (\d*\.\d+) \s ([AW]) \z/xms) {
+ my $aname = $1;
+ my $aval = $2;
+ my $aunit = $3;
$aname =~ s{\s}{_}gxms;
# don't use an existing index
while (exists $used{$index}) { ++$index; }
push @perfdata, {
- label => "pwr_mon_${index}_${aname}",
- mini => "p${index}a",
- value => $aval,
- warn => 0,
- crit => 0,
+ type => $aunit,
+ id => $index,
+ unit => $aunit,
+ label => $aname,
+ legacy => "pwr_mon_${index}_${aname}",
+ mini => "p${index}a",
+ value => $aval,
+ warn => 0,
+ crit => 0,
};
++$index;
}
# CHASSIS: Check intrusion
#-----------------------------------------
sub check_intrusion {
- return if blacklisted('intr', 'all');
-
my $index = undef;
my $status = undef;
my $reading = undef;
INTRUSION:
foreach my $out (@output) {
if ($snmp) {
- $index = $out->{intrusionIndex} - 1;
- $status = $snmp_status{$out->{intrusionStatus}};
- $reading = get_hashval($out->{intrusionReading}, \%int_reading);
+ $index = ($out->{intrusionIndex} || 10000) - 1;
+ $status = get_snmp_status($out->{intrusionStatus});
+ $reading = get_hashval($out->{intrusionReading}, \%int_reading) || 'Unknown reading';
}
else {
- $index = $out->{'Index'};
- $status = $out->{'Status'};
- $reading = $out->{'State'};
+ $index = get_nonempty_string('Index', $out, 9999);
+ $status = get_nonempty_string('Status', $out, 'Unknown');
+ $reading = get_nonempty_string('State', $out, 'Unknown reading');
}
- next INTRUSION if blacklisted('intr', $index);
$count{intr}++;
+ next INTRUSION if blacklisted('intr', $index);
if ($status ne 'Ok') {
my $msg = sprintf 'Chassis intrusion %d detected: %s',
# CHASSIS: Check SD Card Device
#-----------------------------------------
sub check_sdcard {
- return if blacklisted('sdcard', 'all');
-
my $index = undef;
my $status = undef;
my $state = undef;
SDCARD:
foreach my $out (@output) {
if ($snmp) {
- $index = $out->{sdCardDeviceIndex} - 1;
- $status = $snmp_status{$out->{sdCardDeviceStatus}};
+ $index = ($out->{sdCardDeviceIndex} || 10000) - 1;
+ $status = get_snmp_status($out->{sdCardDeviceStatus});
- if (exists $out->{sdCardDeviceCardState}) {
+ if (defined $out->{sdCardDeviceCardState}) {
my @states = (); # contains states SD card
# get the combined state from the Device Status OID
}
}
- $location = $out->{sdCardDeviceLocationName};
- $capacity = sprintf '%s MB', $out->{sdCardDeviceCardStorageSize};
+ $location = $out->{sdCardDeviceLocationName} || 'Unknown location';
+ $capacity = sprintf '%s MB', ($out->{sdCardDeviceCardStorageSize} || 'Unknown size');
}
else {
$index = $c++;
- $status = defined $out->{'Status'} ? $out->{'Status'} : 'Ok';
- $state = $out->{'State'};
- $location = $out->{'Connector Name'};
- $capacity = $out->{'Storage Size'} ne '[Not Available]'
- ? $out->{'Storage Size'} : 'Unknown Size';
+ $status = get_nonempty_string('Status', $out, 'Ok');
+ $state = get_nonempty_string('State', $out, 'Unknown state');
+ $location = get_nonempty_string('Connector Name', $out, 'Unknown location');
+ $capacity = get_nonempty_string('Storage Size', $out, 'Unknown size');
+
+ $capacity =~ s{\[Not Available\]}{Unknown Size};
}
- next SDCARD if blacklisted('sd', $index);
$count{sd}++ if $state ne 'Absent';
+ next SDCARD if blacklisted('sd', $index);
if ($status ne 'Ok') {
my $msg = sprintf 'SD Card %d needs attention: %s',
$snmp_session->error;
report('other', $msg, $E_UNKNOWN);
}
- $health = $snmp_status{$result->{$systemStateEventLogStatus}};
+ $health = get_snmp_status($result->{$systemStateEventLogStatus});
}
else {
foreach (@{ run_command("$omreport $omopt_system esmlog -fmt ssv") }) {
$sysinfo{model} = $val;
}
if ($key eq 'Chassis Service Tag' or $key eq 'Service Tag') {
- $sysinfo{serial} = $val;
+ $sysinfo{serial} = $opt{hide_servicetag} ? 'XXXXXXX' : $val;
}
if ($key eq 'System Revision') {
$sysinfo{rev} = q{ } . $val;
$sysinfo{model} =~ s{\s+\z}{}xms; # remove trailing whitespace
}
elsif (exists $chassis_oid{$oid} and $chassis_oid{$oid} eq 'chassisServiceTagName') {
- $sysinfo{serial} = $result->{$oid};
+ $sysinfo{serial} = $opt{hide_servicetag} ? 'XXXXXXX' : $result->{$oid};
}
elsif (exists $chassis_oid{$oid} and $chassis_oid{$oid} eq 'chassisSystemRevisionName') {
$sysinfo{rev} = q{ } . $result->{$oid};
14 => 'secondaryBackPlane', # Secondary Backplane for ESM 2 systems
15 => 'secondaryBackPlaneESM3And4', # Secondary Backplane for ESM 3 and 4 systems
16 => 'rac', # Remote Access Controller
- 17 => 'imc' # Integrated Management Controller
+ 17 => 'iDRAC', # Integrated Dell Remote Access Controller
+ 19 => 'unifiedServerConfigurator', # Unified Server Configurator
+ 20 => 'lifecycleController', # Lifecycle Controller
);
$sysinfo{'bmc'} = 1;
$sysinfo{'bmc_fw'} = $out->{firmwareVersionName};
}
- elsif ($fw_type{$out->{firmwareType}} =~ m{\A rac|imc \z}xms) {
+ elsif ($fw_type{$out->{firmwareType}} =~ m{\A rac|iDRAC \z}xms) {
my $name = $out->{firmwareTypeName}; $name =~ s/\s//gxms;
$sysinfo{'rac'} = 1;
$sysinfo{'rac_name'} = $name;
print " ServiceTag: $sysinfo{serial}";
print q{ } x (25 - length $sysinfo{serial}), "Plugin version: $VERSION\n";
print " BIOS/date: $sysinfo{bios} $sysinfo{biosdate}";
- print q{ } x (25 - length "$sysinfo{bios} $sysinfo{biosdate}"), "Operation mode: $mode\n";
+ print q{ } x (25 - length "$sysinfo{bios} $sysinfo{biosdate}"), "Checking mode: $mode\n";
if ($#report_storage >= 0) {
print "-----------------------------------------------------------------------------\n";
print " Storage Components \n";
# Prefix with service tag if specified with option '-i|--info'
if ($opt{info}) {
- if (defined $opt{htmlinfo}) {
- $msg = '[<a href="' . warranty_url($sysinfo{serial})
+ if (defined $opt{htmlinfo} and !$opt{hide_servicetag}) {
+ $msg = '[<a target="_blank" href="' . warranty_url($sysinfo{serial})
. "\">$sysinfo{serial}</a>] " . $msg;
}
else {
);
print $okmsg{$opt{only}};
+
+ # show blacklisted components
+ if ($opt{show_blacklist} and %blacklist) {
+ my @blstr = ();
+ foreach (keys %blacklist) {
+ push @blstr, "$_=" . join ',', @{ $blacklist{$_} };
+ }
+ print $linebreak;
+ print "----- BLACKLISTED: " . join '/', @blstr;
+ }
}
elsif ($exit_code == $E_OK && !$opt{debug}) {
- if (defined $opt{htmlinfo}) {
- printf q{OK - System: '<a href="%s">%s%s</a>', SN: '<a href="%s">%s</a>'},
+ if (defined $opt{htmlinfo} and !$opt{hide_servicetag}) {
+ printf q{OK - System: '<a target="_blank" href="%s">%s%s</a>', SN: '<a target="_blank" href="%s">%s</a>'},
documentation_url($sysinfo{model}), $sysinfo{model}, $sysinfo{rev},
warranty_url($sysinfo{serial}), $sysinfo{serial};
}
+ if (defined $opt{htmlinfo} and $opt{hide_servicetag}) {
+ printf q{OK - System: '<a target="_blank" href="%s">%s%s</a>', SN: '%s'},
+ documentation_url($sysinfo{model}), $sysinfo{model}, $sysinfo{rev},
+ $sysinfo{serial};
+ }
else {
printf q{OK - System: '%s%s', SN: '%s'},
$sysinfo{model}, $sysinfo{rev}, $sysinfo{serial};
print ', not checking storage';
}
+ # show blacklisted components
+ if ($opt{show_blacklist} and %blacklist) {
+ my @blstr = ();
+ foreach (keys %blacklist) {
+ push @blstr, "$_=" . join ',', @{ $blacklist{$_} };
+ }
+ print $linebreak;
+ print "----- BLACKLISTED: " . join '/', @blstr;
+ }
+
if ($opt{okinfo} >= 1) {
print $linebreak;
printf q{----- BIOS='%s %s'}, $sysinfo{bios}, $sysinfo{biosdate};
else {
if ($opt{extinfo}) {
print $linebreak;
- if (defined $opt{htmlinfo}) {
- printf '------ SYSTEM: <a href="%s">%s%s</a>, SN: <a href="%s">%s</a>',
+ if (defined $opt{htmlinfo} && !$opt{hide_servicetag}) {
+ printf '------ SYSTEM: <a target="_blank" href="%s">%s%s</a>, SN: <a target="_blank" href="%s">%s</a>',
documentation_url($sysinfo{model}), $sysinfo{model}, $sysinfo{rev},
warranty_url($sysinfo{serial}), $sysinfo{serial};
}
+ elsif (defined $opt{htmlinfo} && $opt{hide_servicetag}) {
+ printf '------ SYSTEM: <a target="_blank" href="%s">%s%s</a>, SN: %s',
+ documentation_url($sysinfo{model}), $sysinfo{model}, $sysinfo{rev},
+ $sysinfo{serial};
+ }
else {
printf '------ SYSTEM: %s%s, SN: %s',
$sysinfo{model}, $sysinfo{rev}, $sysinfo{serial};
# Sort routine for performance data
sub perfsort {
+ my %order = ( 'T' => 0, 'W' => 1, 'A' => 2, 'V' => 3, 'F' => 4, 'E' => 5, );
+
+ # sort in this order:
+ # 1. the type according to the hash "order" above
+ # 2. the id (index) numerically
+ # 3. the id (index) alphabetically
+ # 4. the label
+ return $order{$a->{type}} cmp $order{$b->{type}} ||
+ ($a->{id} =~ m{\A\d+\z}xms and $a->{id} <=> $b->{id}) ||
+ ($a->{id} !~ m{\A\d+\z}xms and $a->{id} cmp $b->{id}) ||
+ $a->{label} cmp $b->{label};
+ }
+
+ # LEGACY sort routine for performance data
+ sub perfsort_legacy {
my %order = ( fan => 0, pwr => 1, tem => 2, enc => 3, );
- return ($order{(substr $a->{label}, 0, 3)} cmp $order{(substr $b->{label}, 0, 3)}) ||
- $a->{label} cmp $b->{label};
+ return ($order{(substr $a->{legacy}, 0, 3)} cmp $order{(substr $b->{legacy}, 0, 3)}) ||
+ $a->{legacy} cmp $b->{legacy};
}
# Print performance data sorted
- my $type = $opt{perfdata} eq 'minimal' ? 'mini' : 'label';
- print join $lb, map { "$_->{$type}=$_->{value};$_->{warn};$_->{crit}" } sort perfsort @perfdata;
+ if ($opt{legacy_perfdata}) {
+ my $type = $opt{perfdata} eq 'minimal' ? 'mini' : 'legacy';
+ print join $lb, map { "$_->{$type}=$_->{value};$_->{warn};$_->{crit}" } sort perfsort_legacy @perfdata;
+ }
+ else {
+ if ($opt{perfdata} eq 'minimal') {
+ print join $lb, map { "$_->{type}$_->{id}=$_->{value}$_->{unit};$_->{warn};$_->{crit}" } sort perfsort @perfdata;
+ }
+ else {
+ print join $lb, map { "$_->{type}$_->{id}_$_->{label}=$_->{value}$_->{unit};$_->{warn};$_->{crit}" } sort perfsort @perfdata;
+ }
+ }
}
-# Print a linebreak at the end
-print "\n" if !$opt{debug};
+# Wrapping up and finishing
+if ($opt{debug}) {
+ # Exit with value 3 (unknown) if debug
+ exit $E_UNKNOWN;
+}
+else {
+ # Print a linebreak at the end if we have a TTY
+ isatty(*STDOUT) && print "\n";
-# Exit with proper exit code
-exit $exit_code;
+ # Exit with proper exit code
+ exit $exit_code;
+}