]> git.uio.no Git - check_openmanage.git/blobdiff - check_openmanage
* version 3.5.8-beta2
[check_openmanage.git] / check_openmanage
index f4d37f9c85d8842f1d7a357ef9570f224cb8cec1..1edeea754d75add5eb94ffb992934bb72d327e61 100755 (executable)
@@ -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.6';
+$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
@@ -299,7 +293,7 @@ if (!$snmp && -f $FW_LOCK) {
     );
 
 # Performance data
-%perfdata = ();
+@perfdata = ();
 
 # Global health status
 $global         = 1;      # default is to check global status
@@ -1063,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
@@ -1136,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
@@ -1170,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;
@@ -1180,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} : undef;
+           $minstdr  = exists $out->{'controllerMinRequiredStorportVer'}
+             ? $out->{controllerMinRequiredStorportVer} : undef;
+           $stdr     = exists $out->{controllerStorportDriverVersion}
+             ? $out->{controllerStorportDriverVersion} : undef;
            $nexus    = convert_nexus($out->{controllerNexusID});
        }
        else {
@@ -1347,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',
@@ -1371,7 +1375,7 @@ sub check_physical_disks {
            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{};
@@ -1425,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
@@ -1533,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',
        );
 
@@ -1543,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});
@@ -1685,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;
@@ -1844,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;
@@ -1931,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});
@@ -2051,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;
@@ -2162,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};
@@ -2279,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};
@@ -2321,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;
@@ -2405,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};
@@ -2654,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;
@@ -2744,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;
 
@@ -2856,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'};
@@ -2885,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);
@@ -2961,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,
+                               };
            }
        }
     }
@@ -3055,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:
@@ -3123,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}
@@ -3238,7 +3347,7 @@ sub check_volts {
            $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 {
@@ -3310,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 {
@@ -3420,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}
@@ -3464,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,
+                           };
        }
     }
 
@@ -3480,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;
            }
        }
@@ -3497,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;
            }
        }
@@ -3565,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'};
@@ -3904,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;
@@ -4345,6 +4457,9 @@ else {
     }
 }
 
+# Reset the WARN signal
+$SIG{__WARN__} = 'DEFAULT';
+
 # Print any perl warnings that have occured
 if (@perl_warnings) {
     foreach (@perl_warnings) {
@@ -4354,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