# Version and similar info
$NAME = 'check_openmanage';
-$VERSION = '3.7.0-beta1';
+$VERSION = '3.7.2';
$AUTHOR = 'Trond H. Amundsen';
$CONTACT = 't.h.amundsen@usit.uio.no';
GENERAL OPTIONS:
- -f, --configfile Configuration file
+ -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
'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
'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},
'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
exit $E_UNKNOWN;
}
-# 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
= (
'rac_fw' => 'N/A', # RAC firmware
);
-# Initialize blacklist
-%blacklist = ();
-
-# Read config file
-parse_configfile() if defined $opt{configfile};
-
# Adjust which checks to perform
adjust_checks() if defined $opt{check};
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
# Read config file
#
sub parse_configfile {
- my $tiny = undef;
+ 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: Perl module 'Config::Tiny' not found\n";
+ 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', "Couldn't read configuration file '$opt{configfile}': $!", $E_UNKNOWN);
+ 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 ($obj, $keyword) = @_;
- my $off = qr{\A (0|off|false) \s* \z}xms;
- my $on = qr{\A (1|on|true) \s* \z}xms;
+ my $keyword = shift;
CHECK_CONFIG:
foreach my $key (keys %check) {
my $copt = join '_', 'check', $key;
- next CHECK_CONFIG if !defined $obj->{$keyword}->{$copt} or $obj->{$keyword}->{$copt} eq q{};
- if ($obj->{$keyword}->{$copt} =~ m{$on}xms) {
+ 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 ($obj->{$keyword}->{$copt} =~ m{$off}xms) {
+ 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 ($obj, $keyword) = @_;
- if (defined $obj->{$keyword}->{blacklist} and $obj->{$keyword}->{blacklist} ne q{}) {
+ my $keyword = shift;
+ if (defined $tiny->{$keyword}->{blacklist} and $tiny->{$keyword}->{blacklist} ne q{}) {
# set_blacklist() takes an array ref
- set_blacklist([$obj->{$keyword}->{blacklist}]);
+ set_blacklist([$tiny->{$keyword}->{blacklist}]);
}
return;
}
- # Get global configuration options
- configfile_adjust_checks($tiny, '_');
- configfile_set_blacklist($tiny, '_');
+ # 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;
+ }
- # Get host options (exact or regexp)
- if (defined $tiny->{$opt{hostname}}) {
- configfile_adjust_checks($tiny, $opt{hostname});
- configfile_set_blacklist($tiny, $opt{hostname});
+ # 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;
}
- else {
- SECTION:
- foreach my $section (keys %{ $tiny }) {
- next SECTION if $section eq '_'; # global section
- my $regex = glob2regex($section); # make regexp
- if ($opt{hostname} =~ m{$regex}) {
- configfile_adjust_checks($tiny, $section);
- configfile_set_blacklist($tiny, $section);
- last SECTION;
+
+ # 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;
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;
}
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;
+}
+
#---------------------------------------------------------------------
# Check functions
$spare = get_hashval($out->{arrayDiskSpareState}, \%spare_state) || q{};
$bus = get_hashval($out->{arrayDiskBusType}, \%bus_type);
$media = get_hashval($out->{arrayDiskMediaType}, \%media_type);
- $cert = $out->{arrayDiskDellCertified} || 1;
+ $cert = defined $out->{arrayDiskDellCertified} ? $out->{arrayDiskDellCertified} : 1;
$capacity = exists $out->{arrayDiskLengthInMB}
? $out->{arrayDiskLengthInMB} * 1024**2 : -1;
}
# Special case: Uncertified disk
elsif ($status eq 'Non-Critical' and !$cert) {
- my $msg = sprintf '%s [%s %s, %s] on ctrl %d is Not Certified',
- $name, $vendor, $product, $capacity, $ctrl;
- report('storage', $msg, $E_WARNING, $nexus);
+ 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') {
$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 = ($out->{batteryConnectionControllerNumber} || 10000) - 1;
+ $ctrl = $snmp_controller{$out->{batteryConnectionControllerNumber}};
$nexus = convert_nexus(($out->{batteryNexusID} || 9999));
$id = $nexus;
$id =~ s{\A \d+:(\d+) \z}{$1}xms;
$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;
}
if (defined $opt{perfdata} && $reading ne '[N/A]') {
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, {
- type => 'E',
- id => $opt{perfdata} eq 'minimal' ? "${encl_id}_t${index}" : "${encl_id}_temp_${index}",
- unit => 'C',
- label => q{},
- 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,
};
}
}
my $pname = $location;
$pname =~ s{\s}{_}gxms;
$pname =~ s{proc_}{cpu#}xms;
+ my $legacy_pname = $pname;
$pname =~ s{_rpm\z}{}ixms;
push @perfdata, {
- type => 'F',
- id => $index,
- unit => 'rpm',
- label => $pname,
- 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,
};
}
}
$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',
$index, $location, $discrete;
# 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;
}
if (defined $opt{perfdata}) {
my $pname = $location;
$pname =~ s{\s}{_}gxms;
- $pname =~ s{_temp\z}{}xms;
+ $pname =~ s{_temp\z}{}ixms;
$pname =~ s{proc_}{cpu#}xms;
push @perfdata, {
- type => 'T',
- id => $index,
- unit => 'C',
- label => $pname,
- 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,
};
}
}
report('chassis', $msg, $err, $index);
# Collect performance data
- if (defined $opt{perfdata}) {
+ 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,
+ type => 'V',
+ id => $index,
+ unit => 'V',
+ label => $label,
+ value => $reading,
+ warn => 0,
+ crit => 0,
};
}
}
$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 = get_nonempty_string('Index', $out, 9999);
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
my $label = join q{_}, $location;
$label =~ s{\s}{_}gxms;
push @perfdata, {
- type => $unit,
- id => $index,
- unit => $unit,
- label => $label,
- 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,
};
}
}
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;
}
while (exists $used{$index}) { ++$index; }
push @perfdata, {
- type => $aunit,
- id => $index,
- unit => $aunit,
- label => $aname,
- 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;
}
$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};
# 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 {
}
}
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};
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};
$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->{legacy}, 0, 3)} cmp $order{(substr $b->{legacy}, 0, 3)}) ||
+ $a->{legacy} cmp $b->{legacy};
+ }
+
# Print performance data sorted
- if ($opt{perfdata} eq 'minimal') {
- print join $lb, map { "$_->{type}$_->{id}=$_->{value}$_->{unit};$_->{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 {
- print join $lb, map { "$_->{type}$_->{id}_$_->{label}=$_->{value}$_->{unit};$_->{warn};$_->{crit}" } sort perfsort @perfdata;
+ 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;
+ }
}
}