X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=check_openmanage;h=1edeea754d75add5eb94ffb992934bb72d327e61;hb=7328e97b3219673d48d333478484639badd9a33c;hp=c976561e1c416daecacf1bb1245a4702e112896e;hpb=f86e57b88a44e3268e047d60d244e40a15a7905b;p=check_openmanage.git diff --git a/check_openmanage b/check_openmanage index c976561..1edeea7 100755 --- a/check_openmanage +++ b/check_openmanage @@ -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 $original_sigwarn - %check %opt %perfdata %reverse_exitcode %status2nagios + $exit_code $snmp + %check %opt %reverse_exitcode %status2nagios %snmp_status %snmp_probestatus %probestatus2nagios %sysinfo %blacklist %nagios_alert_count %count - @perl_warnings @controllers @enclosures + @perl_warnings @controllers @enclosures @perfdata @report_storage @report_chassis @report_other ); @@ -46,18 +46,12 @@ use vars qw( $NAME $VERSION $AUTHOR $CONTACT $E_OK $E_WARNING $E_CRITICAL # Initialization and global variables #--------------------------------------------------------------------- -# 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; +# Collect perl warnings in an array +$SIG{__WARN__} = sub { push @perl_warnings, [@_]; }; # Version and similar info $NAME = 'check_openmanage'; -$VERSION = '3.5.4-beta6'; +$VERSION = '3.5.8-beta2'; $AUTHOR = 'Trond H. Amundsen'; $CONTACT = 't.h.amundsen@usit.uio.no'; @@ -90,7 +84,7 @@ GENERAL OPTIONS: 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 @@ -100,9 +94,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: @@ -127,37 +121,38 @@ Written by $AUTHOR <$CONTACT> 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 @@ -172,12 +167,12 @@ 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}, @@ -192,6 +187,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 @@ -297,7 +293,7 @@ if (!$snmp && -f $FW_LOCK) { ); # Performance data -%perfdata = (); +@perfdata = (); # Global health status $global = 1; # default is to check global status @@ -558,7 +554,7 @@ sub snmp_initialize { } } 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; @@ -596,7 +592,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; @@ -827,7 +823,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 # No power monitoring capability +# | Current\sprobes\snot\sfound # OMSA + RHEL5.4 bug }xms; # Errors that are OK on blade servers @@ -951,17 +947,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,6 +1057,15 @@ sub warranty_url { } +# 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 @@ -1098,6 +1112,8 @@ sub check_global { # STORAGE: Check controllers #----------------------------------------- sub check_controllers { + return if blacklisted('ctrl', 'all'); + my $id = undef; my $nexus = undef; my $name = undef; @@ -1107,8 +1123,8 @@ sub check_controllers { my $mindr = undef; my $firmware = undef; my $driver = undef; - my $minstdr = undef; # Minimum required Storport driver version (whats this?) - my $stdr = undef; # Storport driver version (whats this?) + my $minstdr = undef; # Minimum required Storport driver version + my $stdr = undef; # Storport driver version my @output = (); if ($snmp) { @@ -1123,8 +1139,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', + '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 @@ -1157,7 +1173,7 @@ sub check_controllers { if ($snmp) { $id = $out->{controllerNumber} - 1; $name = $out->{controllerName}; - $state = $ctrl_state{$out->{controllerState}}; + $state = get_hashval($out->{controllerState}, \%ctrl_state); $status = $snmp_status{$out->{controllerComponentStatus}}; $minfw = exists $out->{controllerMinFWVersion} ? $out->{controllerMinFWVersion} : undef; @@ -1167,10 +1183,10 @@ sub check_controllers { ? $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} : 'N/A'; + $minstdr = exists $out->{'controllerMinRequiredStorportVer'} + ? $out->{controllerMinRequiredStorportVer} : undef; + $stdr = exists $out->{controllerStorportDriverVersion} + ? $out->{controllerStorportDriverVersion} : undef; $nexus = convert_nexus($out->{controllerNexusID}); } else { @@ -1191,7 +1207,7 @@ sub check_controllers { ? $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'} : 'N/A'; + ? $out->{'Storport Driver Version'} : undef; $nexus = $id; } @@ -1203,6 +1219,7 @@ 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); @@ -1229,7 +1246,7 @@ sub check_controllers { } # 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); @@ -1250,6 +1267,7 @@ sub check_controllers { #----------------------------------------- sub check_physical_disks { return if $#controllers == -1; + return if blacklisted('pdisk', 'all'); my $id = undef; my $nexus = undef; @@ -1280,10 +1298,27 @@ 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 ERROR [storage / pdisk]: %s.\n", $snmp_session->error; @@ -1295,6 +1330,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); } @@ -1311,6 +1350,7 @@ sub check_physical_disks { 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', @@ -1328,24 +1368,30 @@ 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}); } - $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'}; @@ -1383,15 +1429,17 @@ sub check_physical_disks { $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 @@ -1416,6 +1464,7 @@ sub check_physical_disks { #----------------------------------------- sub check_virtual_disks { return if $#controllers == -1; + return if blacklisted('vdisk', 'all'); my $id = undef; my $name = undef; @@ -1440,7 +1489,14 @@ sub check_virtual_disks { '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; @@ -1483,7 +1539,7 @@ sub check_virtual_disks { 8 => 'RAID-6', 10 => 'RAID-10', 12 => 'RAID-50', - 19 => 'Concatenated RAID 1', + 19 => 'Concatenated RAID-1', 24 => 'RAID-60', ); @@ -1493,9 +1549,9 @@ sub check_virtual_disks { 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}); @@ -1549,6 +1605,7 @@ sub check_virtual_disks { #----------------------------------------- sub check_cache_battery { return if $#controllers == -1; + return if blacklisted('bat', 'all'); my $id = undef; my $nexus = undef; @@ -1569,7 +1626,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; @@ -1620,12 +1691,10 @@ sub check_cache_battery { 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; @@ -1707,6 +1776,7 @@ sub check_cache_battery { #----------------------------------------- sub check_connectors { return if $#controllers == -1; + return if blacklisted('conn', 'all'); my $id = undef; my $nexus = undef; @@ -1727,7 +1797,14 @@ 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 ERROR [storage / channel]: %s.\n", $snmp_session->error; @@ -1771,9 +1848,9 @@ sub check_connectors { 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; @@ -1802,6 +1879,8 @@ sub check_connectors { # STORAGE: Check enclosures #----------------------------------------- sub check_enclosures { + return if blacklisted('encl', 'all'); + my $id = undef; my $nexus = undef; my $name = undef; @@ -1822,7 +1901,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; @@ -1849,10 +1935,10 @@ sub check_enclosures { 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}); @@ -1898,6 +1984,7 @@ sub check_enclosures { #----------------------------------------- sub check_enclosure_fans { return if $#controllers == -1; + return if blacklisted('encl_fan', 'all'); my $id = undef; my $nexus = undef; @@ -1921,8 +2008,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; @@ -1955,7 +2055,7 @@ sub check_enclosure_fans { 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; @@ -1997,6 +2097,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; @@ -2018,7 +2119,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; @@ -2051,7 +2166,7 @@ sub check_enclosure_pwr { 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}; @@ -2091,6 +2206,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; @@ -2120,7 +2236,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; @@ -2153,7 +2283,7 @@ sub check_enclosure_temp { 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}; @@ -2195,9 +2325,16 @@ sub check_enclosure_temp { # 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, + warn => $max_warn, + crit => $max_crit, + }; } } return; @@ -2209,6 +2346,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; @@ -2230,7 +2368,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; @@ -2264,7 +2416,7 @@ sub check_enclosure_emms { 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}; @@ -2303,6 +2455,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; @@ -2320,7 +2474,14 @@ 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 ERROR [memory]: %s.\n", $snmp_session->error; @@ -2414,6 +2575,8 @@ sub check_memory { # CHASSIS: Check fans #----------------------------------------- sub check_fans { + return if blacklisted('fan', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -2432,7 +2595,14 @@ 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; @@ -2495,9 +2665,13 @@ sub check_fans { my $pname = lc $location; $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 => "fan_${index}_${pname}", + mini => "f$index", + value => $reading, + warn => $max_warn, + crit => $max_crit, + }; } } return; @@ -2508,6 +2682,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; @@ -2525,7 +2701,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; @@ -2576,7 +2759,7 @@ sub check_powersupplies { $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; @@ -2624,6 +2807,8 @@ sub check_powersupplies { # CHASSIS: Check temperatures #----------------------------------------- sub check_temperatures { + return if blacklisted('temp', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -2686,17 +2871,24 @@ sub check_temperatures { if ($snmp) { $index = $out->{temperatureProbeIndex} - 1; $status = $snmp_probestatus{$out->{temperatureProbeStatus}}; - $reading = $out->{temperatureProbeReading} / 10; $location = $out->{temperatureProbeLocationName}; - $max_crit = $out->{temperatureProbeUpperCriticalThreshold} / 10; - $max_warn = $out->{temperatureProbeUpperNonCriticalThreshold} / 10; + $reading = exists $out->{temperatureProbeReading} + ? $out->{temperatureProbeReading} / 10 : '[N/A]'; + $max_crit = exists $out->{temperatureProbeUpperCriticalThreshold} + ? $out->{temperatureProbeUpperCriticalThreshold} / 10 : '[N/A]'; + $max_warn = exists $out->{temperatureProbeUpperNonCriticalThreshold} + ? $out->{temperatureProbeUpperNonCriticalThreshold} / 10 : '[N/A]'; $min_crit = exists $out->{temperatureProbeLowerCriticalThreshold} ? $out->{temperatureProbeLowerCriticalThreshold} / 10 : '[N/A]'; $min_warn = exists $out->{temperatureProbeLowerNonCriticalThreshold} ? $out->{temperatureProbeLowerNonCriticalThreshold} / 10 : '[N/A]'; - $type = $probe_type{$out->{temperatureProbeType}}; + $type = get_hashval($out->{temperatureProbeType}, \%probe_type); $discrete = exists $out->{temperatureProbeDiscreteReading} - ? $out->{temperatureProbeDiscreteReading} : undef; + ? $out->{temperatureProbeDiscreteReading} : '[N/A]'; + # workaround for bad temp probes + if ($type eq 'AmbientESM' and $reading !~ m{\A \d+(\.\d+)? \z}xms) { + $type = 'Discrete'; + } } else { $index = $out->{'Index'}; @@ -2715,7 +2907,7 @@ sub check_temperatures { $count{temp}++; if ($type eq 'Discrete') { - my $msg = sprintf 'Temperature probe %d (%s): is %s', + my $msg = sprintf 'Temperature probe %d [%s] is %s', $index, $location, $discrete; my $err = $snmp ? $probestatus2nagios{$status} : $status2nagios{$status}; report('chassis', $msg, $err, $index); @@ -2791,9 +2983,13 @@ sub check_temperatures { $pname =~ s{\s}{_}gxms; $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 => "temp_${index}_${pname}", + mini => "t$index", + value => $reading, + warn => $max_warn, + crit => $max_crit, + }; } } } @@ -2805,6 +3001,8 @@ sub check_temperatures { # CHASSIS: Check processors #----------------------------------------- sub check_processors { + return if blacklisted('cpu', 'all'); + my $index = undef; my $status = undef; my $state = undef; @@ -2833,8 +3031,19 @@ sub check_processors { '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 $result = $snmp_session->get_entries(-columns => [keys %cpu_oid]); + $result = $snmp_session->get_table(-baseoid => $processorDeviceTable); + my $ext = $snmp_session->get_table(-baseoid => $processorDeviceStatusTable); + + defined $ext && map { $$result{$_} = $$ext{$_} } keys %{ $ext }; + } + else { + $result = $snmp_session->get_entries(-columns => [keys %cpu_oid]); + } if (!defined $result) { printf "SNMP ERROR [processors]: %s.\n", $snmp_session->error; @@ -2872,49 +3081,132 @@ sub check_processors { # 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', + 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: @@ -2940,7 +3232,7 @@ sub check_processors { $state = join q{, }, @states; } else { - $state = $cpu_state{$out->{processorDeviceStatusState}}; + $state = get_hashval($out->{processorDeviceStatusState}, \%cpu_state); } $man = $out->{processorDeviceManufacturerName}; $family = (exists $out->{processorDeviceFamily} @@ -3009,6 +3301,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; @@ -3050,10 +3344,10 @@ 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}}; + : get_hashval($out->{voltageProbeDiscreteReading}, \%volt_discrete_reading); $location = $out->{voltageProbeLocationName}; } else { @@ -3079,6 +3373,8 @@ sub check_volts { # CHASSIS: Check batteries #----------------------------------------- sub check_batteries { + return if blacklisted('bp', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -3093,7 +3389,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; @@ -3116,7 +3419,7 @@ sub check_batteries { 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 { @@ -3141,6 +3444,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; @@ -3162,7 +3467,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; @@ -3217,8 +3529,8 @@ sub check_pwrmonitoring { 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} @@ -3261,11 +3573,15 @@ sub check_pwrmonitoring { # 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}" . lc $unit, + value => $reading, + warn => $max_warn, + crit => $max_crit, + }; } } @@ -3277,8 +3593,8 @@ sub check_pwrmonitoring { 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; } } @@ -3294,16 +3610,21 @@ sub check_pwrmonitoring { $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}a", + value => $aval, + warn => 0, + crit => 0, + }; ++$index; } } @@ -3317,6 +3638,8 @@ sub check_pwrmonitoring { # CHASSIS: Check intrusion #----------------------------------------- sub check_intrusion { + return if blacklisted('intr', 'all'); + my $index = undef; my $status = undef; my $reading = undef; @@ -3329,7 +3652,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; @@ -3353,7 +3683,7 @@ sub check_intrusion { 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'}; @@ -3692,22 +4022,16 @@ sub get_snmp_system_operatingsystem { # Fetch OMSA version via SNMP, put in sysinfo hash # sub get_snmp_about { - my %omsa_oid - = ( - '1.3.6.1.4.1.674.10892.1.100.10.0' => 'systemManagementSoftwareGlobalVersionName', - ); - my $systemManagementSoftwareGroup = '1.3.6.1.4.1.674.10892.1.100'; - my $result = $snmp_session->get_table(-baseoid => $systemManagementSoftwareGroup); + # systemManagementSoftwareGlobalVersionName + my $oid = '1.3.6.1.4.1.674.10892.1.100.10.0'; + my $result = $snmp_session->get_request(-varbindlist => [$oid]); + if (defined $result) { - foreach my $oid (keys %{ $result }) { - if (exists $omsa_oid{$oid} and $omsa_oid{$oid} eq 'systemManagementSoftwareGlobalVersionName') { - $sysinfo{om} = ($result->{$oid}); - } - } + $sysinfo{om} = exists $result->{$oid} && $result->{$oid} ne q{} + ? $result->{$oid} : 'unknown'; } else { - my $msg = sprintf 'SNMP ERROR getting OMSA info: %s', - $snmp_session->error; + my $msg = sprintf 'SNMP ERROR: Getting OMSA version failed: %s', $snmp_session->error; report('other', $msg, $E_UNKNOWN); } return; @@ -4063,12 +4387,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}; } @@ -4129,6 +4457,9 @@ else { } } +# Reset the WARN signal +$SIG{__WARN__} = 'DEFAULT'; + # Print any perl warnings that have occured if (@perl_warnings) { foreach (@perl_warnings) { @@ -4138,26 +4469,21 @@ if (@perl_warnings) { $exit_code = $E_UNKNOWN; } -# Reset the WARN signal -$SIG{__WARN__} = $original_sigwarn; - # 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};$_->{warn};$_->{crit}" } sort perfsort @perfdata; } # Print a linebreak at the end