#
# $Id$
#
-# Copyright (C) 2009 Trond H. Amundsen
+# Copyright (C) 2010 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
$snmp_session $snmp_error $omreport $globalstatus $global
$linebreak $omopt_chassis $omopt_system $blade
$exit_code $snmp
- %check %opt %perfdata %reverse_exitcode %status2nagios
+ %check %opt %reverse_exitcode %status2nagios
%snmp_status %snmp_probestatus %probestatus2nagios %sysinfo
%blacklist %nagios_alert_count %count
- @controllers @enclosures
+ @perl_warnings @controllers @enclosures @perfdata
@report_storage @report_chassis @report_other
);
# Initialization and global variables
#---------------------------------------------------------------------
-# If we don't have a TTY, the plugin is probably run by Nagios. In
-# that case, redirect all output to STDERR to STDOUT. Nagios ignores
-# output to STDERR.
-if (! isatty(*STDOUT)) {
- open STDERR, '>&', 'STDOUT'
- or do { print "ERROR: Couldn't redirect STDERR to STDOUT\n"; exit 2; }
-}
+# Collect perl warnings in an array
+$SIG{__WARN__} = sub { push @perl_warnings, [@_]; };
# Version and similar info
$NAME = 'check_openmanage';
-$VERSION = '3.5.0-beta14';
+$VERSION = '3.5.7-beta19';
$AUTHOR = 'Trond H. Amundsen';
$CONTACT = 't.h.amundsen@usit.uio.no';
SNMP OPTIONS:
- -H, --hostname Hostname or IP of the server (needed for SNMP)
+ -H, --hostname Hostname or IP (required for SNMP)
-C, --community SNMP community string
-P, --protocol SNMP protocol version
--port SNMP port number
-i, --info Prefix any alerts with the service tag
-e, --extinfo Append system info to alerts
-s, --state Prefix alerts with alert state
- --short-state Prefix alerts with alert state (abbreviated)
+ -S, --short-state Prefix alerts with alert state (abbreviated)
-o, --okinfo Verbosity when check result is OK
- --htmlinfo HTML output with clickable links
+ -I, --htmlinfo HTML output with clickable links
CHECK CONTROL AND BLACKLISTING:
# Version and license text
$LICENSE = <<"END_LICENSE";
$NAME $VERSION
-Copyright (C) 2009 $AUTHOR
+Copyright (C) 2010 $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.
END_LICENSE
# Options with default values
-%opt = ( 'blacklist' => [],
- 'check' => [],
- 'critical' => [],
- 'warning' => [],
- 'timeout' => 30, # default timeout is 30 seconds
- 'debug' => 0,
- 'help' => 0,
- 'perfdata' => undef,
- 'info' => 0,
- 'extinfo' => 0,
- 'htmlinfo' => undef,
- 'postmsg' => undef,
- 'state' => 0,
- 'short-state' => 0,
- 'okinfo' => 0, # default "ok" output level
- 'linebreak' => undef,
- 'version' => 0,
- 'all' => 0,
- 'only' => undef,
- 'omreport' => undef,
- 'port' => 161, # default SNMP port
- 'hostname' => undef,
- 'community' => 'public', # SMNP v1 or v2c
- 'protocol' => 2,
- 'username' => undef, # SMNP v3
- 'authpassword' => undef, # SMNP v3
- 'authkey' => undef, # SMNP v3
- 'authprotocol' => undef, # SMNP v3
- 'privpassword' => undef, # SMNP v3
- 'privkey' => undef, # SMNP v3
- 'privprotocol' => undef, # SMNP v3
+%opt = ( 'blacklist' => [], # blacklisting
+ 'check' => [], # check control
+ 'critical' => [], # temperature critical limits
+ 'warning' => [], # temperature warning limits
+ 'timeout' => 30, # default timeout is 30 seconds
+ 'debug' => 0, # debugging / verbose output
+ 'help' => 0, # display help output
+ 'perfdata' => undef, # output performance data
+ 'info' => 0, # display servicetag
+ 'extinfo' => 0, # display extra info
+ 'htmlinfo' => undef, # html tags in output
+ 'postmsg' => undef, # post message
+ 'state' => 0, # display alert type
+ 'short-state' => 0, # display alert type (short)
+ 'okinfo' => 0, # default "ok" output level
+ 'linebreak' => undef, # specify linebreak
+ 'version' => 0, # plugin version info
+ 'all' => 0, # check everything
+ 'only' => undef, # only one component
+ 'omreport' => undef, # omreport path
+ 'port' => 161, # default SNMP port
+ 'hostname' => undef, # hostname or IP
+ 'community' => 'public', # SMNP v1 or v2c
+ 'protocol' => 2, # default SNMP protocol 2c
+ 'username' => undef, # SMNP v3
+ 'authpassword' => undef, # SMNP v3
+ 'authkey' => undef, # SMNP v3
+ 'authprotocol' => undef, # SMNP v3
+ 'privpassword' => undef, # SMNP v3
+ 'privkey' => undef, # SMNP v3
+ 'privprotocol' => undef, # SMNP v3
+ 'use_get_table' => 0, # hack for SNMPv3 on Windows with net-snmp
);
# Get options
'p|perfdata:s' => \$opt{perfdata},
'i|info' => \$opt{info},
'e|extinfo' => \$opt{extinfo},
- 'htmlinfo:s' => \$opt{htmlinfo},
+ 'I|htmlinfo:s' => \$opt{htmlinfo},
'postmsg=s' => \$opt{postmsg},
's|state' => \$opt{state},
- 'short-state' => \$opt{shortstate},
+ 'S|short-state' => \$opt{shortstate},
'o|ok-info=i' => \$opt{okinfo},
- 'l|linebreak=s' => \$opt{linebreak},
+ 'linebreak=s' => \$opt{linebreak},
'a|all' => \$opt{all},
'only=s' => \$opt{only},
'omreport=s' => \$opt{omreport},
'privpassword=s' => \$opt{privpassword},
'privkey=s' => \$opt{privkey},
'privprotocol=s' => \$opt{privprotocol},
+ 'use-get_table' => \$opt{use_get_table},
) or do { print $USAGE; exit $E_UNKNOWN };
# If user requested help
);
# Performance data
-%perfdata = ();
+@perfdata = ();
# Global health status
$global = 1; # default is to check global status
}
}
else {
- print "You need perl module Net::SNMP to run $NAME in SNMP mode\n";
+ print "ERROR: You need perl module Net::SNMP to run $NAME in SNMP mode\n";
exit $E_UNKNOWN;
}
return;
# 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 ($result->{$DellBaseBoardType} eq '3') {
+ if (exists $result->{$DellBaseBoardType} && $result->{$DellBaseBoardType} eq '3') {
$blade = 1;
}
return;
sub find_omreport {
# If user has specified path to omreport
if (defined $opt{omreport} and -x $opt{omreport}) {
- $omreport = $opt{omreport};
+ $omreport = qq{"$opt{omreport}"};
return;
}
my @omreport_paths
= (
'/usr/bin/omreport', # default on Linux
+ '/opt/dell/srvadmin/bin/omreport', # default on Linux with OMSA 6.2.0
'/opt/dell/srvadmin/oma/bin/omreport.sh', # alternate on Linux
'/opt/dell/srvadmin/oma/bin/omreport', # alternate on Linux
'C:\Program Files (x86)\Dell\SysMgt\oma\bin\omreport.exe', # default on Windows x64
OMREPORT_PATH:
foreach my $bin (@omreport_paths) {
if (-x $bin) {
- $omreport = $bin;
+ $omreport = qq{"$bin"};
last OMREPORT_PATH;
}
}
print qq{ERROR: Wrong simultaneous usage of the "--only" and "--check" options\n};
exit $E_UNKNOWN;
}
- if (! exists $check{$opt{only}} and $opt{only} ne 'chassis') {
+ if (! exists $check{$opt{only}} && $opt{only} ne 'chassis') {
print qq{ERROR: "$opt{only}" is not a known keyword for the "--only" option\n};
exit $E_UNKNOWN;
}
| No\scontrollers\sfound # No RAID controller
| No\sbattery\sprobes\sfound\son\sthis\ssystem # No battery probes
| Invalid\scommand:\spwrmonitoring # Older OMSAs lack this command(?)
+# | Current\sprobes\snot\sfound # OMSA + RHEL5.4 bug
}xms;
# Errors that are OK on blade servers
return [] if !defined $rawtext;
# Workaround for Openmanage BUG introduced in OMSA 5.5.0
- $rawtext =~ s/\n;/;/gxms if $command eq 'storage controller';
+ $rawtext =~ s{\n;}{;}gxms if $command eq 'storage controller';
+
+ # Openmanage sometimes puts a linebreak between "Error" and the
+ # actual error text
+ $rawtext =~ s{^Error\s*\n}{Error: }xms;
# Parse output, store in array
- for ((split /\n/xms, $rawtext)) {
- if (m/\A Error/xms) {
+ for ((split m{\n}xms, $rawtext)) {
+ if (m{\AError}xms) {
next if m{$ok_errors}xms;
next if ($blade and m{$ok_blade_errors}xms);
report('other', "Problem running 'omreport $command': $_", $E_UNKNOWN);
next if !m/(.*?;){2}/xms; # ignore lines with less than 3 fields
my @vals = split /;/xms;
- if ($vals[0] =~ m/\A (Index|ID|Severity) \z/xms) {
+ if ($vals[0] =~ m/\A (Index|ID|Severity|Processor|Current\sSpeed) \z/xms) {
@keys = @vals;
}
else {
if (defined $blacklist{$name}) {
foreach my $comp (@{ $blacklist{$name} }) {
- if (defined $id and $comp eq $id) {
+ if (defined $id and ($comp eq $id or uc($comp) eq 'ALL')) {
$ret = 1;
}
}
# Gets the output from SNMP result according to the OIDs checked
sub get_snmp_output {
my ($result,$oidref) = @_;
+ my @temp = ();
my @output = ();
foreach my $oid (keys %{ $result }) {
- my @dummy = split /\./xms, $oid;
- my $id = pop @dummy;
- --$id;
- my $foo = join q{.}, @dummy;
- if (exists $oidref->{$foo}) {
- $output[$id]{$oidref->{$foo}} = $result->{$oid};
+ my $short = $oid;
+ $short =~ s{\s}{}gxms; # remove whitespace
+ $short =~ s{\A (.+) \. (\d+) \z}{$1}xms; # remove last number
+ my $id = $2;
+ if (exists $oidref->{$short}) {
+ $temp[$id]{$oidref->{$short}} = $result->{$oid};
}
}
+
+ # Remove any empty indexes
+ foreach my $out (@temp) {
+ if (defined $out) {
+ push @output, $out;
+ }
+ }
+
return \@output;
}
}
+# 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 $hash = shift;
+ return exists $hash->{$key} ? $hash->{$key} : "Undefined value $key";
+}
+
+
#---------------------------------------------------------------------
# Check functions
# STORAGE: Check controllers
#-----------------------------------------
sub check_controllers {
+ return if blacklisted('ctrl', 'all');
+
my $id = undef;
my $nexus = undef;
my $name = undef;
my $mindr = undef;
my $firmware = undef;
my $driver = undef;
+ my $minstdr = undef; # Minimum required Storport driver version
+ my $stdr = undef; # Storport driver version
my @output = ();
if ($snmp) {
'1.3.6.1.4.1.674.10893.1.20.130.1.1.41' => 'controllerDriverVersion',
'1.3.6.1.4.1.674.10893.1.20.130.1.1.44' => 'controllerMinFWVersion',
'1.3.6.1.4.1.674.10893.1.20.130.1.1.45' => 'controllerMinDriverVersion',
+ '1.3.6.1.4.1.674.10893.1.20.130.1.1.55' => 'controllerStorportDriverVersion',
+ '1.3.6.1.4.1.674.10893.1.20.130.1.1.56' => 'controllerMinRequiredStorportVer',
);
# We use get_table() here for the odd case where a server has
CTRL:
foreach my $out (@output) {
if ($snmp) {
- $id = $out->{'controllerNumber'} - 1;
- $name = $out->{'controllerName'};
- $state = $ctrl_state{$out->{'controllerState'}};
- $status = $snmp_status{$out->{'controllerComponentStatus'}};
- $minfw = exists $out->{'controllerMinFWVersion'}
- ? $out->{'controllerMinFWVersion'} : undef;
- $mindr = exists $out->{'controllerMinDriverVersion'}
- ? $out->{'controllerMinDriverVersion'} : undef;
+ $id = $out->{controllerNumber} - 1;
+ $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});
}
else {
? $out->{'Firmware Version'} : 'N/A';
$driver = $out->{'Driver Version'} ne 'Not Applicable'
? $out->{'Driver Version'} : 'N/A';
+ $minstdr = (exists $out->{'Minimum Required Storport Driver Version'}
+ and $out->{'Minimum Required Storport Driver Version'} ne 'Not Applicable')
+ ? $out->{'Minimum Required Storport Driver Version'} : undef;
+ $stdr = (exists $out->{'Storport Driver Version'}
+ and $out->{'Storport Driver Version'} ne 'Not Applicable')
+ ? $out->{'Storport Driver Version'} : undef;
$nexus = $id;
}
$sysinfo{'controller'}{$id}{'name'} = $name;
$sysinfo{'controller'}{$id}{'driver'} = $driver;
$sysinfo{'controller'}{$id}{'firmware'} = $firmware;
+ $sysinfo{'controller'}{$id}{'storport'} = $stdr;
next CTRL if blacklisted('ctrl', $nexus);
$id, $name, $driver;
report('storage', $msg, $E_WARNING, $nexus);
}
+ # Special case: old storport driver
+ if (!blacklisted('ctrl_stdr', $id) && defined $minstdr) {
+ chomp $stdr;
+ my $msg = sprintf q{Controller %d [%s]: Storport driver '%s' is out of date},
+ $id, $name, $stdr;
+ report('storage', $msg, $E_WARNING, $nexus);
+ }
# Ok
if ($status eq 'Ok' or ($status eq 'Non-Critical'
- and (defined $minfw or defined $mindr))) {
+ and (defined $minfw or defined $mindr or defined $minstdr))) {
my $msg = sprintf 'Controller %d [%s] is %s',
$id, $name, $state;
report('storage', $msg, $E_OK, $nexus);
#-----------------------------------------
sub check_physical_disks {
return if $#controllers == -1;
+ return if blacklisted('pdisk', 'all');
my $id = undef;
my $nexus = undef;
'1.3.6.1.4.1.674.10893.1.20.130.4.1.24' => 'arrayDiskComponentStatus',
'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.5.1.5' => 'arrayDiskEnclosureConnectionEnclosureNumber',
'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',
);
- my $result = $snmp_session->get_entries(-columns => [keys %pdisk_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $arrayDiskTable = '1.3.6.1.4.1.674.10893.1.20.130.4';
+ my $arrayDiskEnclosureConnectionControllerNumber = '1.3.6.1.4.1.674.10893.1.20.130.5.1.7';
+ my $arrayDiskChannelConnectionControllerNumber = '1.3.6.1.4.1.674.10893.1.20.130.6.1.7';
+
+ $result = $snmp_session->get_table(-baseoid => $arrayDiskTable);
+ my $ext1 = $snmp_session->get_table(-baseoid => $arrayDiskEnclosureConnectionControllerNumber);
+ my $ext2 = $snmp_session->get_table(-baseoid => $arrayDiskChannelConnectionControllerNumber);
+
+ if (defined $result) {
+ defined $ext1 && map { $$result{$_} = $$ext1{$_} } keys %{ $ext1 };
+ defined $ext2 && map { $$result{$_} = $$ext2{$_} } keys %{ $ext2 };
+ }
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %pdisk_oid]);
+ }
if (!defined $result) {
printf "SNMP ERROR [storage / pdisk]: %s.\n", $snmp_session->error;
}
else {
foreach my $c (@controllers) {
+ # This blacklists disks with broken firmware, which includes
+ # illegal XML characters that makes openmanage choke on itself
+ next if blacklisted('ctrl_pdisk', $c);
+
push @output, @{ run_omreport("storage pdisk controller=$c") };
map_item('ctrl', $c, \@output);
}
7 => 'Recovering',
11 => 'Removed',
15 => 'Resynching',
+ 22 => 'Replacing', # FIXME: this one is not defined in the OM 6.2.0.1 MIBs
24 => 'Rebuilding',
25 => 'No Media',
26 => 'Formatting',
foreach my $out (@output) {
if ($snmp) {
$name = $out->{arrayDiskName};
- if ($name =~ m{.*\d+:\d+:\d+\z}xms) {
+ if (exists $out->{arrayDiskEnclosureID}) {
$id = join q{:}, ($out->{arrayDiskChannel}, $out->{arrayDiskEnclosureID},
- $out->{arrayDiskTargetID});
+ $out->{arrayDiskTargetID});
}
else {
$id = join q{:}, ($out->{arrayDiskChannel}, $out->{arrayDiskTargetID});
}
- $state = $pdisk_state{$out->{arrayDiskState}};
+ $state = get_hashval($out->{arrayDiskState}, \%pdisk_state);
$status = $snmp_status{$out->{arrayDiskComponentStatus}};
$fpred = $out->{arrayDiskSmartAlertIndication} == 2 ? 1 : 0;
$progr = q{};
- $ctrl = exists $out->{arrayDiskEnclosureConnectionControllerNumber}
- ? $out->{arrayDiskEnclosureConnectionControllerNumber} - 1
- : -1;
$nexus = convert_nexus($out->{arrayDiskNexusID});
$vendor = $out->{arrayDiskVendor};
$product = $out->{arrayDiskProductID};
$capacity = $out->{arrayDiskLengthInMB} * 1024**2;
+ if (exists $out->{arrayDiskEnclosureConnectionControllerNumber}) {
+ $ctrl = $out->{arrayDiskEnclosureConnectionControllerNumber} - 1;
+ }
+ elsif (exists $out->{arrayDiskChannelConnectionControllerNumber}) {
+ $ctrl = $out->{arrayDiskChannelConnectionControllerNumber} - 1;
+ }
+ else {
+ $ctrl = -1;
+ }
}
else {
$id = $out->{'ID'};
? sprintf '%.1fTB', ($capacity / 1000**4)
: sprintf '%.0fGB', ($capacity / 1000**3);
$capacity = '450GB' if $capacity eq '449GB'; # quick fix for 450GB disks
+ $capacity = '300GB' if $capacity eq '299GB'; # quick fix for 300GB disks
$capacity = '146GB' if $capacity eq '147GB'; # quick fix for 146GB disks
- $capacity = '300GB' if $capacity eq '299GB'; # quick fix for 146GB disks
# Capitalize only the first letter of the vendor name
$vendor = (substr $vendor, 0, 1) . lc (substr $vendor, 1, length $vendor);
$vendor =~ s{\(tm\)\z}{}xms;
# Special case: Failure predicted
- if ($status eq 'Non-Critical' and $fpred) {
+ if ($fpred) {
my $msg = sprintf '%s [%s %s, %s] on ctrl %d needs attention: Failure Predicted',
$name, $vendor, $product, $capacity, $ctrl;
- report('storage', $msg, $E_WARNING, $nexus);
- }
- # Special case: Rebuilding
- elsif ($state eq 'Rebuilding') {
- my $msg = sprintf '%s [%s] on ctrl %d is %s%s',
- $name, $capacity, $ctrl, $state, $progr;
+ $msg .= " ($state)" if $state ne 'Predictive failure';
+ report('storage', $msg,
+ ($status2nagios{$status} == $E_CRITICAL ? $E_CRITICAL : $E_WARNING), $nexus);
+ }
+ # Special case: Rebuilding / Replacing
+ elsif ($state =~ m{\A Rebuilding|Replacing \z}xms) {
+ my $msg = sprintf '%s [%s %s, %s] on ctrl %d is %s%s',
+ $name, $vendor, $product, $capacity, $ctrl, $state, $progr;
report('storage', $msg, $E_WARNING, $nexus);
}
# Default
#-----------------------------------------
sub check_virtual_disks {
return if $#controllers == -1;
+ return if blacklisted('vdisk', 'all');
my $id = undef;
my $name = undef;
'1.3.6.1.4.1.674.10893.1.20.140.1.1.20' => 'virtualDiskComponentStatus',
'1.3.6.1.4.1.674.10893.1.20.140.1.1.21' => 'virtualDiskNexusID',
);
- my $result = $snmp_session->get_entries(-columns => [keys %vdisk_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $virtualDiskTable = '1.3.6.1.4.1.674.10893.1.20.140.1';
+ $result = $snmp_session->get_table(-baseoid => $virtualDiskTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %vdisk_oid]);
+ }
# No logical drives is OK
return if !defined $result;
8 => 'RAID-6',
10 => 'RAID-10',
12 => 'RAID-50',
- 19 => 'Concatenated RAID 1',
+ 19 => 'Concatenated RAID-1',
24 => 'RAID-60',
);
if ($snmp) {
$id = $out->{virtualDiskTargetID};
$dev = $out->{virtualDiskDeviceName};
- $state = $vdisk_state{$out->{virtualDiskState}};
+ $state = get_hashval($out->{virtualDiskState}, \%vdisk_state);
+ $layout = get_hashval($out->{virtualDiskLayout}, \%vdisk_layout);
$status = $snmp_status{$out->{virtualDiskComponentStatus}};
- $layout = $vdisk_layout{$out->{virtualDiskLayout}};
$size = sprintf '%.2f GB', $out->{virtualDiskLengthInMB} / 1024;
$progr = q{}; # can't get this from SNMP(?)
$nexus = convert_nexus($out->{virtualDiskNexusID});
next VDISK if blacklisted('vdisk', $nexus);
$count{vdisk}++;
+ # The device name is undefined sometimes
+ $dev = q{} if !defined $dev;
+
# Special case: Regenerating
if ($state eq 'Regenerating') {
my $msg = sprintf q{Logical drive %d '%s' [%s, %s] on ctrl %d is %s%s},
#-----------------------------------------
sub check_cache_battery {
return if $#controllers == -1;
+ return if blacklisted('bat', 'all');
my $id = undef;
my $nexus = undef;
'1.3.6.1.4.1.674.10893.1.20.130.15.1.12' => 'batteryLearnState',
'1.3.6.1.4.1.674.10893.1.20.130.16.1.5' => 'batteryConnectionControllerNumber',
);
- my $result = $snmp_session->get_entries(-columns => [keys %bat_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $batteryTable = '1.3.6.1.4.1.674.10893.1.20.130.15';
+ my $batteryConnectionTable = '1.3.6.1.4.1.674.10893.1.20.130.16';
+
+ $result = $snmp_session->get_table(-baseoid => $batteryTable);
+ my $ext = $snmp_session->get_table(-baseoid => $batteryConnectionTable);
+
+ if (defined $result) {
+ defined $ext && map { $$result{$_} = $$ext{$_} } keys %{ $ext };
+ }
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %bat_oid]);
+ }
# No cache battery is OK
return if !defined $result;
36 => 'Learning',
);
+ # Specifies the learn state activity of the battery
my %bat_learn_state
= (
1 => 'Failed',
16 => 'Idle',
);
+ # This property displays the battery's ability to be charged
my %bat_pred_cap
= (
1 => 'Failed', # The battery cannot be charged and needs to be replaced
BATTERY:
foreach my $out (@output) {
if ($snmp) {
- $state = $bat_state{$out->{batteryState}};
$status = $snmp_status{$out->{batteryComponentStatus}};
- $learn = exists $out->{batteryLearnState}
- ? $bat_learn_state{$out->{batteryLearnState}} : undef;
- $pred = exists $out->{batteryPredictedCapacity}
- ? $bat_pred_cap{$out->{batteryPredictedCapacity}} : undef;
+ $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});
$id = $nexus;
# Special case: Charging
if ($state eq 'Charging') {
- my $msg = sprintf 'Cache battery %d in controller %d is %s (%s) [probably harmless]',
- $id, $ctrl, $state, $pred;
- report('storage', $msg, $E_WARNING, $nexus);
+ if ($pred eq 'Failed') {
+ my $msg = sprintf 'Cache battery %d in controller %d is %s (%s) [replace battery]',
+ $id, $ctrl, $state, $pred;
+ report('storage', $msg, $E_CRITICAL, $nexus);
+ }
+ else {
+ next BATTERY if blacklisted('bat_charge', $nexus);
+ my $msg = sprintf 'Cache battery %d in controller %d is %s (%s) [probably harmless]',
+ $id, $ctrl, $state, $pred;
+ report('storage', $msg, $E_WARNING, $nexus);
+ }
}
# Special case: Learning (battery learns its capacity)
elsif ($state eq 'Learning') {
- my $msg = sprintf 'Cache battery %d in controller %d is %s (%s) [probably harmless]',
- $id, $ctrl, $state, $learn;
- report('storage', $msg, $E_WARNING, $nexus);
+ if ($learn eq 'Failed') {
+ my $msg = sprintf 'Cache battery %d in controller %d is %s (%s)',
+ $id, $ctrl, $state, $learn;
+ report('storage', $msg, $E_CRITICAL, $nexus);
+ }
+ else {
+ next BATTERY if blacklisted('bat_charge', $nexus);
+ my $msg = sprintf 'Cache battery %d in controller %d is %s (%s) [probably harmless]',
+ $id, $ctrl, $state, $learn;
+ report('storage', $msg, $E_WARNING, $nexus);
+ }
}
# Special case: Power Low (first part of recharge cycle)
elsif ($state eq 'Power Low') {
+ next BATTERY if blacklisted('bat_charge', $nexus);
my $msg = sprintf 'Cache battery %d in controller %d is %s [probably harmless]',
$id, $ctrl, $state;
report('storage', $msg, $E_WARNING, $nexus);
}
+ # Special case: Degraded and Non-Critical (usually part of recharge cycle)
+ elsif ($state eq 'Degraded' && $status eq 'Non-Critical') {
+ next BATTERY if blacklisted('bat_charge', $nexus);
+ my $msg = sprintf 'Cache battery %d in controller %d is %s (%s) [probably harmless]',
+ $id, $ctrl, $state, $status;
+ report('storage', $msg, $E_WARNING, $nexus);
+ }
# Default
elsif ($status ne 'Ok') {
my $msg = sprintf 'Cache battery %d in controller %d needs attention: %s (%s)',
#-----------------------------------------
sub check_connectors {
return if $#controllers == -1;
+ return if blacklisted('conn', 'all');
my $id = undef;
my $nexus = undef;
'1.3.6.1.4.1.674.10893.1.20.130.2.1.9' => 'channelNexusID',
'1.3.6.1.4.1.674.10893.1.20.130.2.1.11' => 'channelBusType',
);
- my $result = $snmp_session->get_entries(-columns => [keys %conn_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $channelTable = '1.3.6.1.4.1.674.10893.1.20.130.2';
+ $result = $snmp_session->get_table(-baseoid => $channelTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %conn_oid]);
+ }
if (!defined $result) {
printf "SNMP ERROR [storage / channel]: %s.\n", $snmp_session->error;
if ($snmp) {
$id = $out->{channelNumber} - 1;
$name = $out->{channelName};
- $state = $conn_state{$out->{channelState}};
$status = $snmp_status{$out->{channelComponentStatus}};
- $type = $conn_bustype{$out->{channelBusType}};
+ $state = get_hashval($out->{channelState}, \%conn_state);
+ $type = get_hashval($out->{channelBusType}, \%conn_bustype);
$nexus = convert_nexus($out->{channelNexusID});
$ctrl = $nexus;
$ctrl =~ s{(\d+):\d+}{$1}xms;
# STORAGE: Check enclosures
#-----------------------------------------
sub check_enclosures {
+ return if blacklisted('encl', 'all');
+
my $id = undef;
my $nexus = undef;
my $name = undef;
'1.3.6.1.4.1.674.10893.1.20.130.3.1.25' => 'enclosureNexusID',
'1.3.6.1.4.1.674.10893.1.20.130.3.1.26' => 'enclosureFirmwareVersion',
);
- my $result = $snmp_session->get_entries(-columns => [keys %encl_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $enclosureTable = '1.3.6.1.4.1.674.10893.1.20.130.3';
+ $result = $snmp_session->get_table(-baseoid => $enclosureTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %encl_oid]);
+ }
# No enclosures is OK
return if !defined $result;
ENCLOSURE:
foreach my $out (@output) {
if ($snmp) {
- $id = $out->{'enclosureNumber'} - 1;
- $name = $out->{'enclosureName'};
- $state = $encl_state{$out->{'enclosureState'}};
- $status = $snmp_status{$out->{'enclosureComponentStatus'}};
+ $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});
#-----------------------------------------
sub check_enclosure_fans {
return if $#controllers == -1;
+ return if blacklisted('encl_fan', 'all');
my $id = undef;
my $nexus = undef;
'1.3.6.1.4.1.674.10893.1.20.130.8.1.4' => 'fanConnectionEnclosureName',
'1.3.6.1.4.1.674.10893.1.20.130.8.1.5' => 'fanConnectionEnclosureNumber',
);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $fanTable = '1.3.6.1.4.1.674.10893.1.20.130.7';
+ my $fanConnectionTable = '1.3.6.1.4.1.674.10893.1.20.130.8';
- my $result = $snmp_session->get_entries(-columns => [keys %fan_oid]);
+ $result = $snmp_session->get_table(-baseoid => $fanTable);
+ my $ext = $snmp_session->get_table(-baseoid => $fanConnectionTable);
+
+ if (defined $result) {
+ defined $ext && map { $$result{$_} = $$ext{$_} } keys %{ $ext };
+ }
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %fan_oid]);
+ }
# No enclosure fans is OK
return if !defined $result;
if ($snmp) {
$id = $out->{fanNumber} - 1;
$name = $out->{fanName};
- $state = $fan_state{$out->{fanState}};
+ $state = get_hashval($out->{fanState}, \%fan_state);
$status = $snmp_status{$out->{fanComponentStatus}};
$speed = $out->{fanProbeCurrValue};
$encl_id = $out->{fanConnectionEnclosureNumber} - 1;
#-----------------------------------------
sub check_enclosure_pwr {
return if $#controllers == -1;
+ return if blacklisted('encl_ps', 'all');
my $id = undef;
my $nexus = undef;
'1.3.6.1.4.1.674.10893.1.20.130.10.1.4' => 'powerSupplyConnectionEnclosureName',
'1.3.6.1.4.1.674.10893.1.20.130.10.1.5' => 'powerSupplyConnectionEnclosureNumber',
);
- my $result = $snmp_session->get_entries(-columns => [keys %ps_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $powerSupplyTable = '1.3.6.1.4.1.674.10893.1.20.130.9';
+ my $powerSupplyConnectionTable = '1.3.6.1.4.1.674.10893.1.20.130.10';
+
+ $result = $snmp_session->get_table(-baseoid => $powerSupplyTable);
+ my $ext = $snmp_session->get_table(-baseoid => $powerSupplyConnectionTable);
+
+ if (defined $result) {
+ defined $ext && map { $$result{$_} = $$ext{$_} } keys %{ $ext };
+ }
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %ps_oid]);
+ }
# No enclosure power supplies is OK
return if !defined $result;
if ($snmp) {
$id = $out->{powerSupplyNumber};
$name = $out->{powerSupplyName};
- $state = $ps_state{$out->{powerSupplyState}};
+ $state = get_hashval($out->{powerSupplyState}, \%ps_state);
$status = $snmp_status{$out->{powerSupplyComponentStatus}};
$encl_id = $out->{powerSupplyConnectionEnclosureNumber} - 1;
$encl_name = $out->{powerSupplyConnectionEnclosureName};
#-----------------------------------------
sub check_enclosure_temp {
return if $#controllers == -1;
+ return if blacklisted('encl_temp', 'all');
my $id = undef;
my $nexus = undef;
'1.3.6.1.4.1.674.10893.1.20.130.12.1.4' => 'temperatureConnectionEnclosureName',
'1.3.6.1.4.1.674.10893.1.20.130.12.1.5' => 'temperatureConnectionEnclosureNumber',
);
- my $result = $snmp_session->get_entries(-columns => [keys %temp_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $temperatureProbeTable = '1.3.6.1.4.1.674.10893.1.20.130.11';
+ my $temperatureConnectionTable = '1.3.6.1.4.1.674.10893.1.20.130.12';
+
+ $result = $snmp_session->get_table(-baseoid => $temperatureProbeTable);
+ my $ext = $snmp_session->get_table(-baseoid => $temperatureConnectionTable);
+
+ if (defined $result) {
+ defined $ext && map { $$result{$_} = $$ext{$_} } keys %{ $ext };
+ }
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %temp_oid]);
+ }
# No enclosure temperature probes is OK
return if !defined $result;
if ($snmp) {
$id = $out->{temperatureProbeNumber} - 1;
$name = $out->{temperatureProbeName};
- $state = $temp_state{$out->{temperatureProbeState}};
+ $state = get_hashval($out->{temperatureProbeState}, \%temp_state);
$status = $snmp_status{$out->{temperatureProbeComponentStatus}};
$unit = $out->{temperatureProbeUnit};
$reading = $out->{temperatureProbeCurValue};
# Collect performance data
if (defined $opt{perfdata}) {
$name =~ s{\A Temperature\sProbe\s(\d+) \z}{temp_$1}gxms;
- my $pkey = "enclosure_${encl_id}_${name}";
- my $pval = join q{;}, "${reading}C", $max_warn, $max_crit;
- $perfdata{$pkey} = $pval;
+ my $label = "enclosure_${encl_id}_${name}";
+ my $mini = $label;
+ $mini =~ s{enclosure_(.+?)_temp_(.+?)}{e$1t$2}xms;
+ push @perfdata, {
+ label => $label,
+ mini => $mini,
+ value => $reading,
+ unit => '',
+ warn => $max_warn,
+ crit => $max_crit,
+ };
}
}
return;
#-----------------------------------------
sub check_enclosure_emms {
return if $#controllers == -1;
+ return if blacklisted('encl_emm', 'all');
my $id = undef;
my $nexus = undef;
'1.3.6.1.4.1.674.10893.1.20.130.14.1.4' => 'enclosureManagementModuleConnectionEnclosureName',
'1.3.6.1.4.1.674.10893.1.20.130.14.1.5' => 'enclosureManagementModuleConnectionEnclosureNumber',
);
- my $result = $snmp_session->get_entries(-columns => [keys %emms_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $enclosureManagementModuleTable = '1.3.6.1.4.1.674.10893.1.20.130.13';
+ my $enclosureManagementModuleConnectionTable = '1.3.6.1.4.1.674.10893.1.20.130.14';
+
+ $result = $snmp_session->get_table(-baseoid => $enclosureManagementModuleTable);
+ my $ext = $snmp_session->get_table(-baseoid => $enclosureManagementModuleConnectionTable);
+
+ if (defined $result) {
+ defined $ext && map { $$result{$_} = $$ext{$_} } keys %{ $ext };
+ }
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %emms_oid]);
+ }
# No enclosure EMMs is OK
return if !defined $result;
if ($snmp) {
$id = $out->{enclosureManagementModuleNumber} - 1;
$name = $out->{enclosureManagementModuleName};
- $state = $emms_state{$out->{enclosureManagementModuleState}};
+ $state = get_hashval($out->{enclosureManagementModuleState}, \%emms_state);
$status = $snmp_status{$out->{enclosureManagementModuleComponentStatus}};
$encl_id = $out->{enclosureManagementModuleConnectionEnclosureNumber} - 1;
$encl_name = $out->{enclosureManagementModuleConnectionEnclosureName};
# CHASSIS: Check memory modules
#-----------------------------------------
sub check_memory {
+ return if blacklisted('dimm', 'all');
+
my $index = undef;
my $status = undef;
my $location = undef;
'1.3.6.1.4.1.674.10892.1.1100.50.1.14.1' => 'memoryDeviceSize',
'1.3.6.1.4.1.674.10892.1.1100.50.1.20.1' => 'memoryDeviceFailureModes',
);
- my $result = $snmp_session->get_entries(-columns => [keys %dimm_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $memoryDeviceTable = '1.3.6.1.4.1.674.10892.1.1100.50.1';
+ $result = $snmp_session->get_table(-baseoid => $memoryDeviceTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %dimm_oid]);
+ }
if (!defined $result) {
printf "SNMP ERROR [memory]: %s.\n", $snmp_session->error;
# CHASSIS: Check fans
#-----------------------------------------
sub check_fans {
+ return if blacklisted('fan', 'all');
+
my $index = undef;
my $status = undef;
my $reading = undef;
'1.3.6.1.4.1.674.10892.1.700.12.1.10.1' => 'coolingDeviceUpperCriticalThreshold',
'1.3.6.1.4.1.674.10892.1.700.12.1.11.1' => 'coolingDeviceUpperNonCriticalThreshold',
);
- my $result = $snmp_session->get_entries(-columns => [keys %cool_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $coolingDeviceTable = '1.3.6.1.4.1.674.10892.1.700.12.1';
+ $result = $snmp_session->get_table(-baseoid => $coolingDeviceTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %cool_oid]);
+ }
if ($blade && !defined $result) {
return 0;
$pname =~ s{\s}{_}gxms;
$pname =~ s{proc_}{cpu#}xms;
my $pkey = join q{_}, 'fan', $index, $pname;
- my $pval = join q{;}, "${reading}RPM", $max_warn, $max_crit;
- $perfdata{$pkey} = $pval;
+ push @perfdata, {
+ label => $pkey,
+ mini => "f$index",
+ value => $reading,
+ unit => '',
+ warn => $max_warn,
+ crit => $max_crit,
+ };
}
}
return;
# CHASSIS: Check power supplies
#-----------------------------------------
sub check_powersupplies {
+ return if blacklisted('ps', 'all');
+
my $index = undef;
my $status = undef;
my $type = undef;
'1.3.6.1.4.1.674.10892.1.600.12.1.11.1' => 'powerSupplySensorState',
'1.3.6.1.4.1.674.10892.1.600.12.1.12.1' => 'powerSupplyConfigurationErrorType',
);
- my $result = $snmp_session->get_entries(-columns => [keys %ps_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $powerDeviceTable = '1.3.6.1.4.1.674.10892.1.600.12.1';
+ $result = $snmp_session->get_table(-baseoid => $powerDeviceTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %ps_oid]);
+ }
# No instrumented PSU is OK (blades, low-end servers)
return 0 if !defined $result;
$index = $out->{powerSupplyIndex} - 1;
$status = $snmp_status{$out->{powerSupplyStatus}};
- $type = $ps_type{$out->{powerSupplyType}};
+ $type = get_hashval($out->{powerSupplyType}, \%ps_type);
$err_type = defined $out->{powerSupplyConfigurationErrorType}
? $ps_config_error_type{$out->{powerSupplyConfigurationErrorType}} : undef;
# CHASSIS: Check temperatures
#-----------------------------------------
sub check_temperatures {
+ return if blacklisted('temp', 'all');
+
my $index = undef;
my $status = undef;
my $reading = undef;
? $out->{temperatureProbeLowerCriticalThreshold} / 10 : '[N/A]';
$min_warn = exists $out->{temperatureProbeLowerNonCriticalThreshold}
? $out->{temperatureProbeLowerNonCriticalThreshold} / 10 : '[N/A]';
- $type = $probe_type{$out->{temperatureProbeType}};
+ $type = get_hashval($out->{temperatureProbeType}, \%probe_type);
$discrete = exists $out->{temperatureProbeDiscreteReading}
? $out->{temperatureProbeDiscreteReading} : undef;
}
else {
$msg .= sprintf ' (min=%s/%s, max=%s/%s)',
$min_warn, $min_crit, $max_warn, $max_crit;
- }
+ }
my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status};
report('chassis', $msg, $err, $index);
}
$pname =~ s{_temp\z}{}xms;
$pname =~ s{proc_}{cpu#}xms;
my $pkey = join q{_}, 'temp', $index, $pname;
- my $pval = join q{;}, "${reading}C", $max_warn, $max_crit;
- $perfdata{$pkey} = $pval;
+ push @perfdata, {
+ label => $pkey,
+ mini => "t$index",
+ value => $reading,
+ unit => '',
+ 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;
- my $oid_ver = 'new';
- my @output = ();
+ my $brand = undef;
+ my $family = undef;
+ my $man = undef;
+ my $speed = undef;
+ my @output = ();
if ($snmp) {
# NOTE: For some reason, older models don't have the
- # "Processor Device Status" OIDs. We first check the newer
- # (preferred) OIDs, and if that doesn't work, check the "old"
- # OIDs.
+ # "Processor Device Status" OIDs. We check both the newer
+ # (preferred) OIDs and the old ones.
- my %cpu_oid_new # for newer models
+ my %cpu_oid
= (
- '1.3.6.1.4.1.674.10892.1.1100.32.1.2.1' => 'processorDeviceStatusIndex',
- '1.3.6.1.4.1.674.10892.1.1100.32.1.5.1' => 'processorDeviceStatusStatus',
- '1.3.6.1.4.1.674.10892.1.1100.32.1.6.1' => 'processorDeviceStatusReading',
+ '1.3.6.1.4.1.674.10892.1.1100.30.1.2.1' => 'processorDeviceIndex',
+ '1.3.6.1.4.1.674.10892.1.1100.30.1.5.1' => 'processorDeviceStatus',
+ '1.3.6.1.4.1.674.10892.1.1100.30.1.8.1' => 'processorDeviceManufacturerName',
+ '1.3.6.1.4.1.674.10892.1.1100.30.1.9.1' => 'processorDeviceStatusState',
+ '1.3.6.1.4.1.674.10892.1.1100.30.1.10.1' => 'processorDeviceFamily',
+ '1.3.6.1.4.1.674.10892.1.1100.30.1.12.1' => 'processorDeviceCurrentSpeed',
+ '1.3.6.1.4.1.674.10892.1.1100.30.1.23.1' => 'processorDeviceBrandName',
+ '1.3.6.1.4.1.674.10892.1.1100.32.1.2.1' => 'processorDeviceStatusIndex',
+ '1.3.6.1.4.1.674.10892.1.1100.32.1.5.1' => 'processorDeviceStatusStatus',
+ '1.3.6.1.4.1.674.10892.1.1100.32.1.6.1' => 'processorDeviceStatusReading',
);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $processorDeviceTable = '1.3.6.1.4.1.674.10892.1.1100.30.1';
+ my $processorDeviceStatusTable = '1.3.6.1.4.1.674.10892.1.1100.32.1';
- my %cpu_oid_old # for older models
- = (
- '1.3.6.1.4.1.674.10892.1.1100.30.1.2.1' => 'processorDeviceIndex',
- '1.3.6.1.4.1.674.10892.1.1100.30.1.5.1' => 'processorDeviceStatus',
- '1.3.6.1.4.1.674.10892.1.1100.30.1.9.1' => 'processorDeviceStatusState',
- );
-
- my $result = $snmp_session->get_entries(-columns => [keys %cpu_oid_new]);
+ $result = $snmp_session->get_table(-baseoid => $processorDeviceTable);
+ my $ext = $snmp_session->get_table(-baseoid => $processorDeviceStatusTable);
- if (!defined $result) {
- $oid_ver = 'old';
- $result = $snmp_session->get_entries(-columns => [keys %cpu_oid_old]);
+ defined $ext && map { $$result{$_} = $$ext{$_} } keys %{ $ext };
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %cpu_oid]);
}
if (!defined $result) {
exit $E_UNKNOWN;
}
- if ($oid_ver eq 'new') {
- @output = @{ get_snmp_output($result, \%cpu_oid_new) };
- }
- else {
- @output = @{ get_snmp_output($result, \%cpu_oid_old) };
- }
+ @output = @{ get_snmp_output($result, \%cpu_oid) };
}
else {
@output = @{ run_omreport("$omopt_chassis processors") };
1024 => 'Throttled', # Processor Throttled
);
+ # Mapping between family numbers from SNMP and actual CPU family
+ my %cpu_family
+ = (
+ 1 => 'Other', 2 => 'Unknown',
+ 3 => '8086', 4 => '80286',
+ 5 => '386', 6 => '486',
+ 7 => '8087', 8 => '80287',
+ 9 => '80387', 10 => '80487',
+ 11 => 'Pentium', 12 => 'Pentium Pro',
+ 13 => 'Pentium II', 14 => 'Pentium with MMX',
+ 15 => 'Celeron', 16 => 'Pentium II Xeon',
+ 17 => 'Pentium III', 18 => 'Pentium III Xeon',
+ 19 => 'Pentium III', 20 => 'Itanium',
+ 21 => 'Xeon', 22 => 'Pentium 4',
+ 23 => 'Xeon MP', 24 => 'Itanium 2',
+ 25 => 'K5', 26 => 'K6',
+ 27 => 'K6-2', 28 => 'K6-3',
+ 29 => 'Athlon', 30 => 'AMD2900',
+ 31 => 'K6-2+', 32 => 'Power PC',
+ 33 => 'Power PC 601', 34 => 'Power PC 603',
+ 35 => 'Power PC 603+', 36 => 'Power PC 604',
+ 37 => 'Power PC 620', 38 => 'Power PC x704',
+ 39 => 'Power PC 750', 40 => 'Core Duo',
+ 41 => 'Core Duo mobile', 42 => 'Core Solo mobile',
+ 43 => 'Intel Atom', 44 => undef,
+ 45 => undef, 46 => undef,
+ 47 => undef, 48 => 'Alpha',
+ 49 => 'Alpha 21064', 50 => 'Alpha 21066',
+ 51 => 'Alpha 21164', 52 => 'Alpha 21164PC',
+ 53 => 'Alpha 21164a', 54 => 'Alpha 21264',
+ 55 => 'Alpha 21364', 56 => 'Turion II Ultra Dual-Core Mobile M',
+ 57 => 'Turion II Dual-Core Mobile M', 58 => 'Athlon II Dual-Core Mobile M ',
+ 59 => 'Opteron 6100', 60 => undef,
+ 61 => undef, 62 => undef,
+ 63 => undef, 64 => 'MIPS',
+ 65 => 'MIPS R4000', 66 => 'MIPS R4200',
+ 67 => 'MIPS R4400', 68 => 'MIPS R4600',
+ 69 => 'MIPS R10000', 70 => undef,
+ 71 => undef, 72 => undef,
+ 73 => undef, 74 => undef,
+ 75 => undef, 76 => undef,
+ 77 => undef, 78 => undef,
+ 79 => undef, 80 => 'SPARC',
+ 81 => 'SuperSPARC', 82 => 'microSPARC II',
+ 83 => 'microSPARC IIep', 84 => 'UltraSPARC',
+ 85 => 'UltraSPARC II', 86 => 'UltraSPARC IIi',
+ 87 => 'UltraSPARC III', 88 => 'UltraSPARC IIIi',
+ 89 => undef, 90 => undef,
+ 91 => undef, 92 => undef,
+ 93 => undef, 94 => undef,
+ 95 => undef, 96 => '68040',
+ 97 => '68xxx', 98 => '68000',
+ 99 => '68010', 100 => '68020',
+ 101 => '68030', 102 => undef,
+ 103 => undef, 104 => undef,
+ 105 => undef, 106 => undef,
+ 107 => undef, 108 => undef,
+ 109 => undef, 110 => undef,
+ 111 => undef, 112 => 'Hobbit',
+ 113 => undef, 114 => undef,
+ 115 => undef, 116 => undef,
+ 117 => undef, 118 => undef,
+ 119 => undef, 120 => 'Crusoe TM5000',
+ 121 => 'Crusoe TM3000', 122 => 'Efficeon TM8000',
+ 123 => undef, 124 => undef,
+ 125 => undef, 126 => undef,
+ 127 => undef, 128 => 'Weitek',
+ 129 => undef, 130 => 'Celeron M',
+ 131 => 'Athlon 64', 132 => 'Opteron',
+ 133 => 'Sempron', 134 => 'Turion 64 Mobile',
+ 135 => 'Dual-Core Opteron', 136 => 'Athlon 64 X2 DC',
+ 137 => 'Turion 64 X2 M', 138 => 'Quad-Core Opteron',
+ 139 => '3rd gen Opteron', 140 => 'AMD Phenom FX Quad-Core',
+ 141 => 'AMD Phenom X4 Quad-Core', 142 => 'AMD Phenom X2 Dual-Core',
+ 143 => 'AMD Athlon X2 Dual-Core', 144 => 'PA-RISC',
+ 145 => 'PA-RISC 8500', 146 => 'PA-RISC 8000',
+ 147 => 'PA-RISC 7300LC', 148 => 'PA-RISC 7200',
+ 149 => 'PA-RISC 7100LC', 150 => 'PA-RISC 7100',
+ 151 => undef, 152 => undef,
+ 153 => undef, 154 => undef,
+ 155 => undef, 156 => undef,
+ 157 => undef, 158 => undef,
+ 159 => undef, 160 => 'V30',
+ 161 => 'Quad-Core Xeon 3200', 162 => 'Dual-Core Xeon 3000',
+ 163 => 'Quad-Core Xeon 5300', 164 => 'Dual-Core Xeon 5100',
+ 165 => 'Dual-Core Xeon 5000', 166 => 'Dual-Core Xeon LV',
+ 167 => 'Dual-Core Xeon ULV', 168 => 'Dual-Core Xeon 7100',
+ 169 => 'Quad-Core Xeon 5400', 170 => 'Quad-Core Xeon',
+ 171 => 'Dual-Core Xeon 5200', 172 => 'Dual-Core Xeon 7200',
+ 173 => 'Quad-Core Xeon 7300', 174 => 'Quad-Core Xeon 7400',
+ 175 => 'Multi-Core Xeon 7400', 176 => 'M1',
+ 177 => 'M2', 178 => undef,
+ 179 => 'Pentium 4 HT', 180 => 'AS400',
+ 181 => undef, 182 => 'Athlon XP',
+ 183 => 'Athlon MP', 184 => 'Duron',
+ 185 => 'Pentium M', 186 => 'Celeron D',
+ 187 => 'Pentium D', 188 => 'Pentium Extreme',
+ 189 => 'Core Solo', 190 => 'Core2',
+ 191 => 'Core2 Duo', 192 => 'Core2 Solo',
+ 193 => 'Core2 Extreme', 194 => 'Core2 Quad',
+ 195 => 'Core2 Extreme mobile', 196 => 'Core2 Duo mobile',
+ 197 => 'Core2 Solo mobile', 198 => 'Core i7',
+ 199 => 'Dual-Core Celeron', 200 => 'IBM390',
+ 201 => 'G4', 202 => 'G5',
+ 203 => 'ESA/390 G6', 204 => 'z/Architectur',
+ 205 => 'Core i5', 206 => undef,
+ 207 => undef, 208 => undef,
+ 209 => undef, 210 => 'C7-M',
+ 211 => 'C7-D', 212 => 'C7',
+ 213 => 'Eden', 214 => 'Multi-Core Xeon',
+ 215 => 'Dual-Core Xeon 3xxx', 216 => 'Quad-Core Xeon 3xxx',
+ 217 => undef, 218 => 'Dual-Core Xeon 5xxx',
+ 219 => 'Quad-Core Xeon 5xxx', 220 => undef,
+ 221 => 'Dual-Core Xeon 7xxx', 222 => 'Quad-Core Xeon 7xxx',
+ 223 => 'Multi-Core Xeon 7xxx', 224 => undef,
+ 225 => undef, 226 => undef,
+ 227 => undef, 228 => undef,
+ 229 => undef, 230 => 'Embedded AMD Opteron Quad-Core',
+ 231 => 'AMD Phenom Triple-Core', 232 => 'AMD Turion Ultra Dual-Core Mobile',
+ 233 => 'AMD Turion Dual-Core Mobile', 234 => 'AMD Athlon Dual-Core',
+ 235 => 'AMD Sempron SI', 236 => 'AMD Phenom II',
+ 237 => 'AMD Athlon II', 238 => 'Six-Core AMD Opteron',
+ 239 => 'AMD Sempron M', 240 => undef,
+ 241 => undef, 242 => undef,
+ 243 => undef, 244 => undef,
+ 245 => undef, 246 => undef,
+ 247 => undef, 248 => undef,
+ 249 => undef, 250 => 'i860',
+ 251 => 'i960',
+ );
CPU:
foreach my $out (@output) {
if ($snmp) {
- if ($oid_ver eq 'new') {
+ $index = exists $out->{processorDeviceStatusIndex}
+ ? $out->{processorDeviceStatusIndex} - 1
+ : $out->{processorDeviceIndex} - 1;
+ $status = exists $out->{processorDeviceStatusStatus}
+ ? $snmp_status{$out->{processorDeviceStatusStatus}}
+ : $snmp_status{$out->{processorDeviceStatus}};
+ if (exists $out->{processorDeviceStatusReading}) {
my @states = (); # contains states for the CPU
- $index = $out->{processorDeviceStatusIndex} - 1;
- $status = $snmp_status{$out->{processorDeviceStatusStatus}};
# get the combined state from the StatusReading OID
foreach my $mask (sort keys %cpu_reading) {
$state = join q{, }, @states;
}
else {
- $index = $out->{processorDeviceIndex} - 1;
- $status = $snmp_status{$out->{processorDeviceStatus}};
- $state = $cpu_state{$out->{processorDeviceStatusState}};
+ $state = get_hashval($out->{processorDeviceStatusState}, \%cpu_state);
}
+ $man = $out->{processorDeviceManufacturerName};
+ $family = (exists $out->{processorDeviceFamily}
+ and exists $cpu_family{$out->{processorDeviceFamily}})
+ ? $cpu_family{$out->{processorDeviceFamily}} : undef;
+ $speed = $out->{processorDeviceCurrentSpeed};
+ $brand = $out->{processorDeviceBrandName};
}
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;
}
next CPU if blacklisted('cpu', $index);
$count{cpu}++;
+ if (defined $brand) {
+ $brand =~ s{\s\s+}{ }gxms;
+ $brand =~ s{\((R|tm)\)}{}gxms;
+ $brand =~ s{\s(CPU|Processor)}{}xms;
+ $brand =~ s{\s\@}{}xms;
+ }
+ elsif (defined $family and defined $man and defined $speed) {
+ $speed =~ s{\A (\d+) .*}{$1}xms;
+ $brand = sprintf '%s %s %.2fGHz', $man, $family, $speed / 1000;
+ }
+ else {
+ $brand = "unknown";
+ }
+
# Default
if ($status ne 'Ok') {
- my $msg = sprintf 'CPU %d needs attention: %s',
- $index, $state;
+ my $msg = sprintf 'Processor %d [%s] needs attention: %s',
+ $index, $brand, $state;
report('chassis', $msg, $status2nagios{$status}, $index);
}
# Ok
else {
- my $msg = sprintf 'CPU %d is %s',
- $index, $state;
+ my $msg = sprintf 'Processor %d [%s] is %s',
+ $index, $brand, $state;
report('chassis', $msg, $E_OK, $index);
}
}
# CHASSIS: Check voltage probes
#-----------------------------------------
sub check_volts {
+ return if blacklisted('volt', 'all');
+
my $index = undef;
my $status = undef;
my $reading = undef;
foreach my $out (@output) {
if ($snmp) {
$index = $out->{voltageProbeIndex} - 1;
- $status = $snmp_status{$out->{voltageProbeStatus}};
+ $status = $snmp_probestatus{$out->{voltageProbeStatus}};
$reading = exists $out->{voltageProbeReading}
? sprintf('%.3f V', $out->{voltageProbeReading}/1000)
- : $volt_discrete_reading{$out->{voltageProbeDiscreteReading}};
+ : get_hashval($out->{voltageProbeDiscreteReading}, \%volt_discrete_reading);
$location = $out->{voltageProbeLocationName};
}
else {
# CHASSIS: Check batteries
#-----------------------------------------
sub check_batteries {
+ return if blacklisted('bp', 'all');
+
my $index = undef;
my $status = undef;
my $reading = undef;
'1.3.6.1.4.1.674.10892.1.600.50.1.6.1' => 'batteryReading',
'1.3.6.1.4.1.674.10892.1.600.50.1.7.1' => 'batteryLocationName',
);
- my $result = $snmp_session->get_entries(-columns => [keys %bat_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $batteryTable = '1.3.6.1.4.1.674.10892.1.600.50.1';
+ $result = $snmp_session->get_table(-baseoid => $batteryTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %bat_oid]);
+ }
# No batteries is OK
return 0 if !defined $result;
if ($snmp) {
$index = $out->{batteryIndex} - 1;
$status = $snmp_status{$out->{batteryStatus}};
- $reading = $bat_reading{$out->{batteryReading}};
+ $reading = get_hashval($out->{batteryReading}, \%bat_reading);
$location = $out->{batteryLocationName};
}
else {
# CHASSIS: Check amperage probes (power monitoring)
#-----------------------------------------
sub check_pwrmonitoring {
+ return if blacklisted('amp', 'all');
+
my $index = undef;
my $status = undef;
my $reading = undef;
'1.3.6.1.4.1.674.10892.1.600.30.1.11.1' => 'amperageProbeUpperNonCriticalThreshold',
'1.3.6.1.4.1.674.10892.1.600.30.1.16.1' => 'amperageProbeDiscreteReading',
);
- my $result = $snmp_session->get_entries(-columns => [keys %amp_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $amperageProbeTable = '1.3.6.1.4.1.674.10892.1.600.30.1';
+ $result = $snmp_session->get_table(-baseoid => $amperageProbeTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %amp_oid]);
+ }
# No pwrmonitoring is OK
return 0 if !defined $result;
if ($snmp) {
$index = $out->{amperageProbeIndex} - 1;
$status = $snmp_status{$out->{amperageProbeStatus}};
- $reading = $amp_type{$out->{amperageProbeType}} eq 'amperageProbeTypeIsDiscrete'
- ? $amp_discrete{$out->{amperageProbeDiscreteReading}}
+ $reading = get_hashval($out->{amperageProbeType}, \%amp_type) eq 'amperageProbeTypeIsDiscrete'
+ ? get_hashval($out->{amperageProbeDiscreteReading}, \%amp_discrete)
: $out->{amperageProbeReading};
$location = $out->{amperageProbeLocationName};
$max_crit = exists $out->{amperageProbeUpperCriticalThreshold}
}
else {
$index = $out->{'Index'};
- next if $index !~ m/^\d+$/x;
+ next AMP if (!defined $index || $index !~ m/^\d+$/x);
$status = $out->{'Status'};
$reading = $out->{'Reading'};
$location = $out->{'Probe Name'};
$max_crit =~ s{\A (\d+.*?)\s+[a-zA-Z]+ \s*\z}{$1}xms;
}
- next AMP if blacklisted('pm', $index);
+ next AMP if blacklisted('amp', $index);
next AMP if $index !~ m{\A \d+ \z}xms;
$count{amp}++;
# Collect performance data
if (defined $opt{perfdata}) {
next AMP if $reading !~ m{\A \d+(\.\d+)? \z}xms; # discrete reading (not number)
- my $pname = lc $location;
- $pname =~ s{\s}{_}gxms;
- my $pkey = join q{_}, 'pwr_mon', $index, $pname;
- my $pval = join q{;}, "$reading$unit", $max_warn, $max_crit;
- $perfdata{$pkey} = $pval;
+ my $label = join q{_}, 'pwr_mon', $index, lc $location;
+ $label =~ s{\s}{_}gxms;
+ push @perfdata, {
+ label => $label,
+ mini => "p$index",
+ value => $reading,
+ unit => '',
+ warn => $max_warn,
+ crit => $max_crit,
+ };
}
}
my %used = ();
# find used indexes
- foreach (keys %perfdata) {
- if (m/\A pwr_mon_(\d+)/xms) {
+ foreach (@perfdata) {
+ if ($_->{label} =~ m/\A pwr_mon_(\d+)/xms) {
$used{$1} = 1;
}
}
$found = 0;
next AMP2;
}
- if ($found and $line =~ m/\A ([^;]+?) ; (\d*\.\d+) \s ([AW]) \z/xms) {
+ if ($found and $line =~ m/\A ([^;]+?) ; (\d*\.\d+) \s [AW] \z/xms) {
my $aname = lc $1;
my $aval = $2;
- my $aunit = $3;
$aname =~ s{\s}{_}gxms;
# don't use an existing index
while (exists $used{$index}) { ++$index; }
- $perfdata{"pwr_mon_${index}_${aname}"} = "$aval$aunit;0;0";
+ push @perfdata, {
+ label => "pwr_mon_${index}_${aname}",
+ mini => "p$index",
+ value => $aval,
+ unit => '',
+ 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;
'1.3.6.1.4.1.674.10892.1.300.70.1.5.1' => 'intrusionStatus',
'1.3.6.1.4.1.674.10892.1.300.70.1.6.1' => 'intrusionReading',
);
- my $result = $snmp_session->get_entries(-columns => [keys %int_oid]);
+ my $result = undef;
+ if ($opt{use_get_table}) {
+ my $intrusionTable = '1.3.6.1.4.1.674.10892.1.300.70.1';
+ $result = $snmp_session->get_table(-baseoid => $intrusionTable);
+ }
+ else {
+ $result = $snmp_session->get_entries(-columns => [keys %int_oid]);
+ }
# No intrusion is OK
return 0 if !defined $result;
if ($snmp) {
$index = $out->{intrusionIndex} - 1;
$status = $snmp_status{$out->{intrusionStatus}};
- $reading = $int_reading{$out->{intrusionReading}};
+ $reading = get_hashval($out->{intrusionReading}, \%int_reading);
}
else {
$index = $out->{'Index'};
$snmp ? get_snmp_chassis_bios() : get_omreport_chassis_bios();
}
+ # Get OMSA information. Only if needed
+ if ($opt{okinfo} >= 3 or $opt{debug}) {
+ $snmp ? get_snmp_about() : get_omreport_about();
+ }
+
# Return now if debug
return if $opt{debug};
$snmp ? get_snmp_system_operatingsystem() : get_omreport_system_operatingsystem();
}
- # Get OMSA information. Only if needed
- if ($opt{okinfo} >= 3) {
- $snmp ? get_snmp_about() : get_omreport_about();
- }
-
return;
}
# Print messages
if ($opt{debug}) {
print " System: $sysinfo{model}\n";
- print " ServiceTag: $sysinfo{serial}\n";
- print " BIOS/date: $sysinfo{bios} $sysinfo{biosdate}\n";
+ print " ServiceTag: $sysinfo{serial}";
+ print q{ } x (25 - length $sysinfo{serial}), "OMSA version: $sysinfo{om}\n";
+ print " BIOS/date: $sysinfo{bios} $sysinfo{biosdate}";
+ print q{ } x (25 - length "$sysinfo{bios} $sysinfo{biosdate}"), "Plugin version: $VERSION\n";
if ($#report_storage >= 0) {
print "-----------------------------------------------------------------------------\n";
print " Storage Components \n";
print "-----------------------------------------------------------------------------\n";
print " Chassis Components \n";
print "=============================================================================\n";
- print " STATE | ID | MESSAGE TEXT \n";
+ print " STATE | ID | MESSAGE TEXT \n";
print "---------+------+------------------------------------------------------------\n";
foreach (@report_chassis) {
my ($msg, $level, $nexus) = @{$_};
my @storageprint = ();
foreach my $id (sort keys %{ $sysinfo{controller} }) {
chomp $sysinfo{controller}{$id}{driver};
- push @storageprint, sprintf q{----- CTRL %s (%s): FW='%s', DR='%s'},
+ my $msg = sprintf q{----- Ctrl %s [%s]: Fw='%s', Dr='%s'},
$sysinfo{controller}{$id}{id}, $sysinfo{controller}{$id}{name},
$sysinfo{controller}{$id}{firmware}, $sysinfo{controller}{$id}{driver};
+ if (defined $sysinfo{controller}{$id}{storport}) {
+ $msg .= sprintf q{, Storport: '%s'}, $sysinfo{controller}{$id}{storport};
+ }
+ push @storageprint, $msg;
}
foreach my $id (sort keys %{ $sysinfo{enclosure} }) {
- push @storageprint, sprintf q{----- ENCL %s (%s): FW='%s'},
+ push @storageprint, sprintf q{----- Encl %s [%s]: Fw='%s'},
$sysinfo{enclosure}{$id}->{id}, $sysinfo{enclosure}{$id}->{name},
$sysinfo{enclosure}{$id}->{firmware};
}
}
}
+# Reset the WARN signal
+$SIG{__WARN__} = 'DEFAULT';
+
+# Print any perl warnings that have occured
+if (@perl_warnings) {
+ foreach (@perl_warnings) {
+ chop @$_;
+ print "${linebreak}INTERNAL ERROR: @$_";
+ }
+ $exit_code = $E_UNKNOWN;
+}
+
# Print performance data
-if (defined $opt{perfdata} && !$opt{debug} && %perfdata) {
+if (defined $opt{perfdata} && !$opt{debug} && @perfdata) {
my $lb = $opt{perfdata} eq 'multiline' ? "\n" : q{ }; # line break for perfdata
print q{|};
- sub perfdata {
- my %order
- = (
- fan => 0,
- pwr => 1,
- temp => 2,
- enclosure => 3,
- );
- return ($order{(split /_/, $a, 2)[0]} cmp $order{(split /_/, $b, 2)[0]}) || $a cmp $b;
+ # Sort routine for performance data
+ sub perfsort {
+ 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};
}
- print join $lb, map { "'$_'=$perfdata{$_}" } sort perfdata keys %perfdata;
+ # Print performance data sorted
+ my $type = $opt{perfdata} eq 'minimal' ? 'mini' : 'label';
+ print join $lb, map { "$_->{$type}=$_->{value}$_->{unit};$_->{warn};$_->{crit}" } sort perfsort @perfdata;
}
# Print a linebreak at the end