X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=check_openmanage;h=b6d7709c95a4adb9651298053e6ad88b0acb5405;hb=c849fd4c1485c050965b70bca2abcb559a49f904;hp=09584fdff906f931e4d132c25612ce09ec75e92c;hpb=669797e15db13b138678ee34917585598c42ca1e;p=check_openmanage.git diff --git a/check_openmanage b/check_openmanage index 09584fd..b6d7709 100755 --- a/check_openmanage +++ b/check_openmanage @@ -7,7 +7,7 @@ # # $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 @@ -34,11 +34,11 @@ use vars qw( $NAME $VERSION $AUTHOR $CONTACT $E_OK $E_WARNING $E_CRITICAL $E_UNKNOWN $FW_LOCK $USAGE $HELP $LICENSE $snmp_session $snmp_error $omreport $globalstatus $global $linebreak $omopt_chassis $omopt_system $blade - $exit_code $snmp + $exit_code $snmp $original_sigwarn %check %opt %perfdata %reverse_exitcode %status2nagios %snmp_status %snmp_probestatus %probestatus2nagios %sysinfo %blacklist %nagios_alert_count %count - @controllers @enclosures + @perl_warnings @controllers @enclosures @report_storage @report_chassis @report_other ); @@ -46,16 +46,18 @@ use vars qw( $NAME $VERSION $AUTHOR $CONTACT $E_OK $E_WARNING $E_CRITICAL # 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'; +# Small subroutine to collect any perl warnings during execution +sub collect_perl_warning { + push @perl_warnings, [@_]; } +# Set the WARN signal to use our collect subroutine above +$original_sigwarn = $SIG{__WARN__}; +$SIG{__WARN__} = \&collect_perl_warning; + # Version and similar info $NAME = 'check_openmanage'; -$VERSION = '3.5.0-beta8'; +$VERSION = '3.5.6-beta6'; $AUTHOR = 'Trond H. Amundsen'; $CONTACT = 't.h.amundsen@usit.uio.no'; @@ -98,9 +100,9 @@ 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 - --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: @@ -116,7 +118,7 @@ END_HELP # 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 This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. @@ -144,6 +146,7 @@ END_LICENSE 'version' => 0, 'all' => 0, 'only' => undef, + 'omreport' => undef, 'port' => 161, # default SNMP port 'hostname' => undef, 'community' => 'public', # SMNP v1 or v2c @@ -155,6 +158,7 @@ END_LICENSE 'privpassword' => undef, # SMNP v3 'privkey' => undef, # SMNP v3 'privprotocol' => undef, # SMNP v3 + 'use_get_table' => 0, ); # Get options @@ -169,14 +173,15 @@ GetOptions('b|blacklist=s' => \@{ $opt{blacklist} }, '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}, 'port=i' => \$opt{port}, 'H|hostname=s' => \$opt{hostname}, 'C|community=s' => \$opt{community}, @@ -188,6 +193,7 @@ GetOptions('b|blacklist=s' => \@{ $opt{blacklist} }, '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 @@ -592,7 +598,7 @@ sub snmp_detect_blade { # 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; @@ -602,21 +608,30 @@ sub snmp_detect_blade { # Locate the omreport binary # sub find_omreport { + # If user has specified path to omreport + if (defined $opt{omreport} and -x $opt{omreport}) { + $omreport = qq{"$opt{omreport}"}; + return; + } + # Possible full paths for omreport 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:\progra~1\dell\sysmgt\oma\bin\omreport.exe', # default on Windows - 'c:\progra~2\dell\sysmgt\oma\bin\omreport.exe', # default on Windows x64 + 'C:\Program Files (x86)\Dell\SysMgt\oma\bin\omreport.exe', # default on Windows x64 + 'C:\Program Files\Dell\SysMgt\oma\bin\omreport.exe', # default on Windows x32 + 'c:\progra~1\dell\sysmgt\oma\bin\omreport.exe', # 8bit legacy default on Windows x32 + 'c:\progra~2\dell\sysmgt\oma\bin\omreport.exe', # 8bit legacy default on Windows x64 ); # Find the one to use OMREPORT_PATH: foreach my $bin (@omreport_paths) { if (-x $bin) { - $omreport = $bin; + $omreport = qq{"$bin"}; last OMREPORT_PATH; } } @@ -730,7 +745,7 @@ sub adjust_checks { 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; } @@ -814,6 +829,7 @@ sub run_omreport { | 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 @@ -827,11 +843,15 @@ sub run_omreport { 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); @@ -839,7 +859,7 @@ sub run_omreport { 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 { @@ -867,7 +887,7 @@ sub blacklisted { 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; } } @@ -933,17 +953,26 @@ sub custom_temperature_thresholds { # 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; } @@ -1052,7 +1081,7 @@ sub check_global { my $systemStateGlobalSystemStatus = '1.3.6.1.4.1.674.10892.1.200.10.1.2.1'; my $result = $snmp_session->get_request(-varbindlist => [$systemStateGlobalSystemStatus]); if (!defined $result) { - printf "SNMP [systemStateGlobalSystemStatus]: %s\n", $snmp_error; + printf "SNMP ERROR [global]: %s\n", $snmp_error; exit $E_UNKNOWN; } $health = $status2nagios{$snmp_status{$result->{$systemStateGlobalSystemStatus}}}; @@ -1080,6 +1109,8 @@ sub check_global { # STORAGE: Check controllers #----------------------------------------- sub check_controllers { + return if blacklisted('ctrl', 'all'); + my $id = undef; my $nexus = undef; my $name = undef; @@ -1089,6 +1120,8 @@ sub check_controllers { 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) { @@ -1103,6 +1136,8 @@ sub check_controllers { '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' => 'FIXME_StorportDriverVersion', + '1.3.6.1.4.1.674.10893.1.20.130.1.1.56' => 'FIXME_StorportMinDriverVersion', ); # We use get_table() here for the odd case where a server has @@ -1133,18 +1168,22 @@ sub check_controllers { 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 = $ctrl_state{$out->{controllerState}}; + $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->{'FIXME_StorportMinDriverVersion'} + ? $out->{FIXME_StorportMinDriverVersion} : undef; + $stdr = exists $out->{FIXME_StorportDriverVersion} + ? $out->{FIXME_StorportDriverVersion} : undef; $nexus = convert_nexus($out->{controllerNexusID}); } else { @@ -1160,6 +1199,12 @@ sub check_controllers { ? $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; } @@ -1171,33 +1216,41 @@ sub check_controllers { $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); # Special case: old firmware if (!blacklisted('ctrl_fw', $id) && defined $minfw) { chomp $firmware; - my $msg = sprintf 'Controller %d (%s): Firmware is out of date (%s)', + my $msg = sprintf q{Controller %d [%s]: Firmware '%s' is out of date}, $id, $name, $firmware; report('storage', $msg, $E_WARNING, $nexus); } # Special case: old driver if (!blacklisted('ctrl_driver', $id) && defined $mindr) { chomp $driver; - my $msg = sprintf 'Controller %d (%s): Driver is out of date (%s)', + my $msg = sprintf q{Controller %d [%s]: Driver '%s' is out of date}, $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))) { - my $msg = sprintf 'Controller %d (%s) is %s', + 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); } # Default else { - my $msg = sprintf 'Controller %d (%s) needs attention: %s', + my $msg = sprintf 'Controller %d [%s] needs attention: %s', $id, $name, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } @@ -1211,6 +1264,7 @@ sub check_controllers { #----------------------------------------- sub check_physical_disks { return if $#controllers == -1; + return if blacklisted('pdisk', 'all'); my $id = undef; my $nexus = undef; @@ -1241,13 +1295,30 @@ sub check_physical_disks { '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 [storage / pdisk]: %s.\n", $snmp_session->error; + printf "SNMP ERROR [storage / pdisk]: %s.\n", $snmp_session->error; $snmp_session->close; exit $E_UNKNOWN; } @@ -1256,6 +1327,10 @@ sub check_physical_disks { } 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); } @@ -1289,9 +1364,9 @@ sub check_physical_disks { 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}); @@ -1300,13 +1375,19 @@ sub check_physical_disks { $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'}; @@ -1334,8 +1415,8 @@ sub check_physical_disks { ? 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); @@ -1345,25 +1426,25 @@ sub check_physical_disks { # Special case: Failure predicted if ($status eq 'Non-Critical' and $fpred) { - my $msg = sprintf '%s (%s %s, %s) on controller %d needs attention: Failure Predicted', + 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 controller %d is %s%s', + my $msg = sprintf '%s [%s] on ctrl %d is %s%s', $name, $capacity, $ctrl, $state, $progr; report('storage', $msg, $E_WARNING, $nexus); } # Default elsif ($status ne 'Ok') { - my $msg = sprintf '%s (%s %s, %s) on controller %d needs attention: %s', + my $msg = sprintf '%s [%s %s, %s] on ctrl %d needs attention: %s', $name, $vendor, $product, $capacity, $ctrl, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } # Ok else { - my $msg = sprintf '%s (%s) on controller %d is %s', + my $msg = sprintf '%s [%s] on ctrl %d is %s', $name, $capacity, $ctrl, $state; report('storage', $msg, $E_OK, $nexus); } @@ -1377,8 +1458,10 @@ sub check_physical_disks { #----------------------------------------- sub check_virtual_disks { return if $#controllers == -1; + return if blacklisted('vdisk', 'all'); my $id = undef; + my $name = undef; my $nexus = undef; my $dev = undef; my $state = undef; @@ -1386,21 +1469,28 @@ sub check_virtual_disks { my $layout = undef; my $size = undef; my $progr = undef; + my $ctrl = undef; my @output = (); if ($snmp) { my %vdisk_oid = ( - '1.3.6.1.4.1.674.10893.1.20.140.1.1.1' => 'virtualDiskNumber', - '1.3.6.1.4.1.674.10893.1.20.140.1.1.2' => 'virtualDiskName', '1.3.6.1.4.1.674.10893.1.20.140.1.1.3' => 'virtualDiskDeviceName', '1.3.6.1.4.1.674.10893.1.20.140.1.1.4' => 'virtualDiskState', '1.3.6.1.4.1.674.10893.1.20.140.1.1.6' => 'virtualDiskLengthInMB', '1.3.6.1.4.1.674.10893.1.20.140.1.1.13' => 'virtualDiskLayout', + '1.3.6.1.4.1.674.10893.1.20.140.1.1.17' => 'virtualDiskTargetID', '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; @@ -1451,7 +1541,7 @@ sub check_virtual_disks { VDISK: foreach my $out (@output) { if ($snmp) { - $id = $out->{virtualDiskNumber} - 1; + $id = $out->{virtualDiskTargetID}; $dev = $out->{virtualDiskDeviceName}; $state = $vdisk_state{$out->{virtualDiskState}}; $status = $snmp_status{$out->{virtualDiskComponentStatus}}; @@ -1459,6 +1549,8 @@ sub check_virtual_disks { $size = sprintf '%.2f GB', $out->{virtualDiskLengthInMB} / 1024; $progr = q{}; # can't get this from SNMP(?) $nexus = convert_nexus($out->{virtualDiskNexusID}); + $ctrl = $nexus; # We use the nexus id to get the controller id + $ctrl =~ s{\A (\d+):\d+ \z}{$1}xms; } else { $id = $out->{ID}; @@ -1470,27 +1562,31 @@ sub check_virtual_disks { $progr = ' [' . $out->{Progress} . ']'; $size =~ s{\A (.*GB).* \z}{$1}xms; $nexus = join q{:}, $out->{ctrl}, $id; + $ctrl = $out->{ctrl}; } 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 'Logical drive %d "%s" (%s, %s) is %s%s', - $id, $dev, $layout, $size, $state, $progr; + my $msg = sprintf q{Logical drive %d '%s' [%s, %s] on ctrl %d is %s%s}, + $id, $dev, $layout, $size, $ctrl, $state, $progr; report('storage', $msg, $E_WARNING, $nexus); } # Default elsif ($status ne 'Ok') { - my $msg = sprintf 'Logical drive %d "%s" (%s, %s) needs attention: %s', - $id, $dev, $layout, $size, $state; + my $msg = sprintf q{Logical drive %d '%s' [%s, %s] on ctrl %d needs attention: %s}, + $id, $dev, $layout, $size, $ctrl, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } # Ok else { - my $msg = sprintf 'Logical drive %d "%s" (%s, %s) is %s', - $id, $dev, $layout, $size, $state; + my $msg = sprintf q{Logical drive %d '%s' [%s, %s] on ctrl %d is %s}, + $id, $dev, $layout, $size, $ctrl, $state; report('storage', $msg, $E_OK, $nexus); } } @@ -1503,6 +1599,7 @@ sub check_virtual_disks { #----------------------------------------- sub check_cache_battery { return if $#controllers == -1; + return if blacklisted('bat', 'all'); my $id = undef; my $nexus = undef; @@ -1516,8 +1613,6 @@ sub check_cache_battery { if ($snmp) { my %bat_oid = ( - '1.3.6.1.4.1.674.10893.1.20.130.15.1.1' => 'batteryNumber', - '1.3.6.1.4.1.674.10893.1.20.130.15.1.2' => 'batteryName', '1.3.6.1.4.1.674.10893.1.20.130.15.1.4' => 'batteryState', '1.3.6.1.4.1.674.10893.1.20.130.15.1.6' => 'batteryComponentStatus', '1.3.6.1.4.1.674.10893.1.20.130.15.1.9' => 'batteryNexusID', @@ -1525,7 +1620,21 @@ sub check_cache_battery { '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; @@ -1553,6 +1662,7 @@ sub check_cache_battery { 36 => 'Learning', ); + # Specifies the learn state activity of the battery my %bat_learn_state = ( 1 => 'Failed', @@ -1562,6 +1672,7 @@ sub check_cache_battery { 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 @@ -1574,7 +1685,6 @@ sub check_cache_battery { BATTERY: foreach my $out (@output) { if ($snmp) { - $id = $out->{batteryNumber} - 1; $state = $bat_state{$out->{batteryState}}; $status = $snmp_status{$out->{batteryComponentStatus}}; $learn = exists $out->{batteryLearnState} @@ -1583,6 +1693,8 @@ sub check_cache_battery { ? $bat_pred_cap{$out->{batteryPredictedCapacity}} : undef; $ctrl = $out->{batteryConnectionControllerNumber} - 1; $nexus = convert_nexus($out->{batteryNexusID}); + $id = $nexus; + $id =~ s{\A \d+:(\d+) \z}{$1}xms; } else { $id = $out->{'ID'}; @@ -1598,22 +1710,46 @@ sub check_cache_battery { # 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)', @@ -1636,6 +1772,7 @@ sub check_cache_battery { #----------------------------------------- sub check_connectors { return if $#controllers == -1; + return if blacklisted('conn', 'all'); my $id = undef; my $nexus = undef; @@ -1656,10 +1793,17 @@ sub check_connectors { '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 [storage / channel]: %s.\n", $snmp_session->error; + printf "SNMP ERROR [storage / channel]: %s.\n", $snmp_session->error; $snmp_session->close; exit $E_UNKNOWN; } @@ -1719,7 +1863,7 @@ sub check_connectors { next CHANNEL if blacklisted('conn', $nexus); - my $msg = sprintf '%s (%s) on controller %d is %s', + my $msg = sprintf '%s [%s] on controller %d is %s', $name, $type, $ctrl, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } @@ -1731,12 +1875,15 @@ sub check_connectors { # STORAGE: Check enclosures #----------------------------------------- sub check_enclosures { + return if blacklisted('encl', 'all'); + my $id = undef; my $nexus = undef; my $name = undef; my $state = undef; my $status = undef; my $firmware = undef; + my $ctrl = undef; my @output = (); if ($snmp) { @@ -1750,7 +1897,14 @@ sub check_enclosures { '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; @@ -1784,6 +1938,8 @@ sub check_enclosures { $firmware = exists $out->{enclosureFirmwareVersion} ? $out->{enclosureFirmwareVersion} : 'N/A'; $nexus = convert_nexus($out->{enclosureNexusID}); + $ctrl = $nexus; + $ctrl =~ s{\A (\d+):.* \z}{$1}xms; } else { $id = $out->{ID}; @@ -1793,6 +1949,7 @@ sub check_enclosures { $firmware = $out->{'Firmware Version'} ne 'Not Applicable' ? $out->{'Firmware Version'} : 'N/A'; $nexus = join q{:}, $out->{ctrl}, $id; + $ctrl = $out->{ctrl}; } $name =~ s{\s+\z}{}xms; # remove trailing whitespace @@ -1810,8 +1967,8 @@ sub check_enclosures { next ENCLOSURE if blacklisted('encl', $nexus); - my $msg = sprintf 'Enclosure %s (%s) is %s', - $nexus, $name, $state; + my $msg = sprintf 'Enclosure %s [%s] on controller %d is %s', + $nexus, $name, $ctrl, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } return; @@ -1823,6 +1980,7 @@ sub check_enclosures { #----------------------------------------- sub check_enclosure_fans { return if $#controllers == -1; + return if blacklisted('encl_fan', 'all'); my $id = undef; my $nexus = undef; @@ -1846,8 +2004,21 @@ sub check_enclosure_fans { '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; @@ -1902,13 +2073,13 @@ sub check_enclosure_fans { # Default if ($status ne 'Ok') { - my $msg = sprintf '%s in enclosure %s (%s) needs attention: %s', + my $msg = sprintf '%s in enclosure %s [%s] needs attention: %s', $name, $encl_id, $encl_name, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } # Ok else { - my $msg = sprintf '%s in enclosure %s (%s) is %s (speed=%s)', + my $msg = sprintf '%s in enclosure %s [%s] is %s (speed=%s)', $name, $encl_id, $encl_name, $state, $speed; report('storage', $msg, $E_OK, $nexus); } @@ -1922,6 +2093,7 @@ sub check_enclosure_fans { #----------------------------------------- sub check_enclosure_pwr { return if $#controllers == -1; + return if blacklisted('encl_ps', 'all'); my $id = undef; my $nexus = undef; @@ -1943,7 +2115,21 @@ sub check_enclosure_pwr { '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; @@ -1996,13 +2182,13 @@ sub check_enclosure_pwr { # Default if ($status ne 'Ok') { - my $msg = sprintf '%s in enclosure %s (%s) needs attention: %s', + my $msg = sprintf '%s in enclosure %s [%s] needs attention: %s', $name, $encl_id, $encl_name, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } # Ok else { - my $msg = sprintf '%s in enclosure %s (%s) is %s', + my $msg = sprintf '%s in enclosure %s [%s] is %s', $name, $encl_id, $encl_name, $state; report('storage', $msg, $E_OK, $nexus); } @@ -2016,6 +2202,7 @@ sub check_enclosure_pwr { #----------------------------------------- sub check_enclosure_temp { return if $#controllers == -1; + return if blacklisted('encl_temp', 'all'); my $id = undef; my $nexus = undef; @@ -2045,7 +2232,21 @@ sub check_enclosure_temp { '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; @@ -2106,13 +2307,13 @@ sub check_enclosure_temp { # Default if ($status ne 'Ok') { - my $msg = sprintf '%s in enclosure %s (%s) is %s at %s (%s max)', + my $msg = sprintf '%s in enclosure %s [%s] is %s C at %s (%s max)', $name, $encl_id, $encl_name, $state, $reading, $max_crit; report('storage', $msg, $status2nagios{$status}, $nexus); } # Ok else { - my $msg = sprintf '%s in enclosure %s (%s): %s (%s max)', + my $msg = sprintf '%s in enclosure %s [%s]: %s C (%s max)', $name, $encl_id, $encl_name, $reading, $max_crit; report('storage', $msg, $E_OK, $nexus); } @@ -2134,6 +2335,7 @@ sub check_enclosure_temp { #----------------------------------------- sub check_enclosure_emms { return if $#controllers == -1; + return if blacklisted('encl_emm', 'all'); my $id = undef; my $nexus = undef; @@ -2155,7 +2357,21 @@ sub check_enclosure_emms { '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; @@ -2209,13 +2425,13 @@ sub check_enclosure_emms { # Default if ($status ne 'Ok') { - my $msg = sprintf '%s in enclosure %s (%s) needs attention: %s', + my $msg = sprintf '%s in enclosure %s [%s] needs attention: %s', $name, $encl_id, $encl_name, $state; report('storage', $msg, $status2nagios{$status}, $nexus); } # Ok else { - my $msg = sprintf '%s in enclosure %s (%s) is %s', + my $msg = sprintf '%s in enclosure %s [%s] is %s', $name, $encl_id, $encl_name, $state; report('storage', $msg, $E_OK, $nexus); } @@ -2228,6 +2444,8 @@ sub check_enclosure_emms { # CHASSIS: Check memory modules #----------------------------------------- sub check_memory { + return if blacklisted('dimm', 'all'); + my $index = undef; my $status = undef; my $location = undef; @@ -2245,10 +2463,17 @@ sub check_memory { '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 [memory]: %s.\n", $snmp_session->error; + printf "SNMP ERROR [memory]: %s.\n", $snmp_session->error; $snmp_session->close; exit $E_UNKNOWN; } @@ -2314,11 +2539,11 @@ sub check_memory { if ($status ne 'Ok') { my $msg = undef; if (scalar @failures == 0) { - $msg = sprintf 'Memory module %d (%s, %s) needs attention (%s)', + $msg = sprintf 'Memory module %d [%s, %s] needs attention (%s)', $index, $location, $size, $status; } else { - $msg = sprintf 'Memory module %d (%s, %s) needs attention: %s', + $msg = sprintf 'Memory module %d [%s, %s] needs attention: %s', $index, $location, $size, (join q{, }, @failures); } @@ -2326,7 +2551,7 @@ sub check_memory { } # Ok else { - my $msg = sprintf 'Memory module %d (%s, %s) is %s', + my $msg = sprintf 'Memory module %d [%s, %s] is %s', $index, $location, $size, $status; report('chassis', $msg, $E_OK, $index); } @@ -2339,6 +2564,8 @@ sub check_memory { # CHASSIS: Check fans #----------------------------------------- sub check_fans { + return if blacklisted('fan', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -2357,13 +2584,20 @@ sub check_fans { '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; } elsif (!$blade && !defined $result) { - printf "SNMP [cooling]: %s.\n", $snmp_session->error; + printf "SNMP ERROR [cooling]: %s.\n", $snmp_session->error; $snmp_session->close; exit $E_UNKNOWN; } @@ -2404,13 +2638,13 @@ sub check_fans { $count{fan}++; if ($status ne 'Ok') { - my $msg = sprintf 'Chassis fan %d (%s) needs attention: %s', + 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', + my $msg = sprintf 'Chassis fan %d [%s]: %s', $index, $location, $reading; report('chassis', $msg, $E_OK, $index); } @@ -2433,6 +2667,8 @@ sub check_fans { # CHASSIS: Check power supplies #----------------------------------------- sub check_powersupplies { + return if blacklisted('ps', 'all'); + my $index = undef; my $status = undef; my $type = undef; @@ -2450,7 +2686,14 @@ sub check_powersupplies { '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; @@ -2531,12 +2774,12 @@ sub check_powersupplies { $count{power}++; if ($status ne 'Ok') { - my $msg = sprintf 'Power Supply %d (%s) needs attention: %s', + my $msg = sprintf 'Power Supply %d [%s] needs attention: %s', $index, $type, $state; report('chassis', $msg, $status2nagios{$status}, $index); } else { - my $msg = sprintf 'Power Supply %d (%s): %s', + my $msg = sprintf 'Power Supply %d [%s]: %s', $index, $type, $state; report('chassis', $msg, $E_OK, $index); } @@ -2549,6 +2792,8 @@ sub check_powersupplies { # CHASSIS: Check temperatures #----------------------------------------- sub check_temperatures { + return if blacklisted('temp', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -2587,7 +2832,7 @@ sub check_temperatures { my $result = $snmp_session->get_table(-baseoid => $temperatureProbeTable); if (!defined $result) { - printf "SNMP [temperatures]: %s.\n", $snmp_session->error; + printf "SNMP ERROR [temperatures]: %s.\n", $snmp_session->error; $snmp_session->close; exit $E_UNKNOWN; } @@ -2649,56 +2894,63 @@ sub check_temperatures { # 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)', + my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom max=%d)', $index, $location, $reading, $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)', + my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom max=%d)', $index, $location, $reading, $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)', + my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom min=%d)', $index, $location, $reading, $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)', + my $msg = sprintf 'Temperature Probe %d [%s] reads %d C (custom min=%d)', $index, $location, $reading, $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', + my $msg = sprintf 'Temperature Probe %d [%s] is critically high at %d C', $index, $location, $reading; 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', + my $msg = sprintf 'Temperature Probe %d [%s] is too high at %d C', $index, $location, $reading; 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', + my $msg = sprintf 'Temperature Probe %d [%s] is critically low at %d C', $index, $location, $reading; 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', + my $msg = sprintf 'Temperature Probe %d [%s] is too low at %d C', $index, $location, $reading; my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status}; report('chassis', $msg, $err, $index); } # Ok else { - my $msg = sprintf 'Temperature Probe %d (%s) reads %d C (min=%s/%s, max=%s/%s)', - $index, $location, $reading, $min_warn, $min_crit, $max_warn, $max_crit; + my $msg = sprintf 'Temperature Probe %d [%s] reads %d C', + $index, $location, $reading; + if ($min_warn eq '[N/A]' and $min_crit eq '[N/A]') { + $msg .= sprintf ' (max=%s/%s)', $max_warn, $max_crit; + } + 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); } @@ -2723,52 +2975,57 @@ sub check_temperatures { # 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', - ); + $result = $snmp_session->get_table(-baseoid => $processorDeviceTable); + my $ext = $snmp_session->get_table(-baseoid => $processorDeviceStatusTable); - my $result = $snmp_session->get_entries(-columns => [keys %cpu_oid_new]); - - 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) { - printf "SNMP [processors]: %s.\n", $snmp_session->error; + printf "SNMP ERROR [processors]: %s.\n", $snmp_session->error; $snmp_session->close; 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") }; @@ -2795,14 +3052,65 @@ sub check_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', + 48 => 'Alpha', 49 => 'Alpha 21064', 50 => 'Alpha 21066', + 51 => 'Alpha 21164', 52 => 'Alpha 21164PC', 53 => 'Alpha 21164a', + 54 => 'Alpha 21264', 55 => 'Alpha 21364', 64 => 'MIPS', + 65 => 'MIPS R4000', 66 => 'MIPS R4200', 67 => 'MIPS R4400', + 68 => 'MIPS R4600', 69 => 'MIPS R10000', 80 => 'SPARC', + 81 => 'SuperSPARC', 82 => 'microSPARC II', 83 => 'microSPARC IIep', + 84 => 'UltraSPARC', 85 => 'UltraSPARC II', 86 => 'UltraSPARC IIi', + 87 => 'UltraSPARC III', 88 => 'UltraSPARC IIIi', 96 => '68040', + 97 => '68xxx', 98 => '68000', 99 => '68010', + 100 => '68020', 101 => '68030', 112 => 'Hobbit', + 120 => 'Crusoe TM5000', 121 => 'Crusoe TM3000', 122 => 'Efficeon TM8000', + 128 => 'Weitek', 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', 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', 160 => 'V30', + 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', 180 => 'AS400', 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', + 198 => 'Core i7', 199 => 'Dual-Core Celeron', 200 => 'IBM390', + 201 => 'G4', 202 => 'G5', 203 => 'ESA/390 G6', + 204 => 'z/Architectur', 210 => 'C7-M', 211 => 'C7-D', + 212 => 'C7', 213 => 'Eden', 214 => 'Multi-Core Xeon', + 215 => 'Dual-Core Xeon 3xxx', 216 => 'Quad-Core Xeon 3xxx', 218 => 'Dual-Core Xeon 5xxx', + 219 => 'Quad-Core Xeon 5xxx', 221 => 'Dual-Core Xeon 7xxx', 222 => 'Quad-Core Xeon 7xxx', + 223 => 'Multi-Core Xeon 7xxx', 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) { @@ -2815,15 +3123,23 @@ sub check_processors { $state = join q{, }, @states; } else { - $index = $out->{processorDeviceIndex} - 1; - $status = $snmp_status{$out->{processorDeviceStatus}}; $state = $cpu_state{$out->{processorDeviceStatusState}}; } + $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); @@ -2841,16 +3157,30 @@ sub check_processors { $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); } } @@ -2862,6 +3192,8 @@ sub check_processors { # CHASSIS: Check voltage probes #----------------------------------------- sub check_volts { + return if blacklisted('volt', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -2882,7 +3214,7 @@ sub check_volts { my $result = $snmp_session->get_table(-baseoid => $voltageProbeTable); if (!defined $result) { - printf "SNMP [voltage probes]: %s.\n", $snmp_session->error; + printf "SNMP ERROR [voltage]: %s.\n", $snmp_session->error; $snmp_session->close; exit $E_UNKNOWN; } @@ -2903,7 +3235,7 @@ sub check_volts { 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}}; @@ -2919,7 +3251,7 @@ sub check_volts { next VOLT if blacklisted('volt', $index); $count{volt}++; - my $msg = sprintf 'Voltage sensor %d (%s) is %s', + my $msg = sprintf 'Voltage sensor %d [%s] is %s', $index, $location, $reading; my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status}; report('chassis', $msg, $err, $index); @@ -2932,6 +3264,8 @@ sub check_volts { # CHASSIS: Check batteries #----------------------------------------- sub check_batteries { + return if blacklisted('bp', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -2946,7 +3280,14 @@ sub check_batteries { '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; @@ -2982,7 +3323,7 @@ sub check_batteries { next BATTERY if blacklisted('bp', $index); $count{bat}++; - my $msg = sprintf 'Battery probe %d (%s) is %s', + my $msg = sprintf 'Battery probe %d [%s] is %s', $index, $location, $reading; report('chassis', $msg, $status2nagios{$status}, $index); } @@ -2994,6 +3335,8 @@ sub check_batteries { # CHASSIS: Check amperage probes (power monitoring) #----------------------------------------- sub check_pwrmonitoring { + return if blacklisted('amp', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -3015,7 +3358,14 @@ sub check_pwrmonitoring { '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; @@ -3089,7 +3439,7 @@ sub check_pwrmonitoring { } 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'}; @@ -3103,11 +3453,11 @@ sub check_pwrmonitoring { $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}++; - my $msg = sprintf 'Amperage probe %d (%s) reads %s %s', + my $msg = sprintf 'Amperage probe %d [%s] reads %s %s', $index, $location, $reading, $unit, $status; report('chassis', $msg, $status2nagios{$status}, $index); @@ -3170,6 +3520,8 @@ sub check_pwrmonitoring { # CHASSIS: Check intrusion #----------------------------------------- sub check_intrusion { + return if blacklisted('intr', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -3182,7 +3534,14 @@ sub check_intrusion { '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; @@ -3266,7 +3625,7 @@ sub check_esmlog_health { my $systemStateEventLogStatus = '1.3.6.1.4.1.674.10892.1.200.10.1.41.1'; my $result = $snmp_session->get_request(-varbindlist => [$systemStateEventLogStatus]); if (!defined $result) { - my $msg = sprintf 'SNMP ERROR getting systemStateEventLogStatus OID: %s', + my $msg = sprintf 'SNMP ERROR [esmhealth]: %s', $snmp_session->error; report('other', $msg, $E_UNKNOWN); } @@ -3286,11 +3645,11 @@ sub check_esmlog_health { # fill grade of the log is more than 80% and the log should be # cleared if ($health eq 'Ok') { - my $msg = sprintf 'ESM log is health is OK (less than 80%% full)'; + my $msg = sprintf 'ESM log health is Ok (less than 80%% full)'; report('other', $msg, $E_OK); } elsif ($health eq 'Critical') { - my $msg = sprintf 'ESM log is 100%% full!'; + my $msg = sprintf 'ESM log is 100%% full'; report('other', $msg, $status2nagios{$health}); } else { @@ -3581,6 +3940,11 @@ sub get_sysinfo $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}; @@ -3589,11 +3953,6 @@ sub get_sysinfo $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; } @@ -3762,8 +4121,10 @@ if ($snmp) { # 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"; @@ -3781,7 +4142,7 @@ if ($opt{debug}) { 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) = @{$_}; @@ -3914,12 +4275,16 @@ elsif ($exit_code == $E_OK && !$opt{debug}) { 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}; } @@ -3980,6 +4345,18 @@ else { } } +# Print any perl warnings that have occured +if (@perl_warnings) { + foreach (@perl_warnings) { + chop @$_; + print "${linebreak}INTERNAL ERROR: @$_"; + } + $exit_code = $E_UNKNOWN; +} + +# Reset the WARN signal +$SIG{__WARN__} = $original_sigwarn; + # Print performance data if (defined $opt{perfdata} && !$opt{debug} && %perfdata) { my $lb = $opt{perfdata} eq 'multiline' ? "\n" : q{ }; # line break for perfdata @@ -3998,6 +4375,8 @@ if (defined $opt{perfdata} && !$opt{debug} && %perfdata) { print join $lb, map { "'$_'=$perfdata{$_}" } sort perfdata keys %perfdata; } + +# Print a linebreak at the end print "\n" if !$opt{debug}; # Exit with proper exit code