--- /dev/null
+#! /usr/bin/perl -w
+# nagios: -epn
+
+package Nagios::MiniPlugin;
+
+use strict;
+use Getopt::Long qw(:config no_ignore_case bundling);
+
+our @STATUS_CODES = qw(OK WARNING CRITICAL UNKNOWN DEPENDENT);
+
+require Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = (@STATUS_CODES, qw(nagios_exit nagios_die check_messages));
+our @EXPORT_OK = qw(%ERRORS);
+
+use constant OK => 0;
+use constant WARNING => 1;
+use constant CRITICAL => 2;
+use constant UNKNOWN => 3;
+use constant DEPENDENT => 4;
+
+our %ERRORS = (
+ 'OK' => OK,
+ 'WARNING' => WARNING,
+ 'CRITICAL' => CRITICAL,
+ 'UNKNOWN' => UNKNOWN,
+ 'DEPENDENT' => DEPENDENT,
+);
+
+our %STATUS_TEXT = reverse %ERRORS;
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ perfdata => [],
+ messages => {
+ ok => [],
+ warning => [],
+ critical => [],
+ unknown => [],
+ },
+ args => [],
+ opts => Nagios::MiniPlugin::Getopt->new(%params),
+ };
+ foreach (qw(shortname usage version url plugin blurb extra
+ license timeout)) {
+ $self->{$_} = $params{$_};
+ }
+ bless $self, $class;
+}
+
+sub add_arg {
+ my $self = shift;
+ $self->{opts}->add_arg(@_);
+}
+
+sub getopts {
+ my $self = shift;
+ $self->{opts}->getopts();
+}
+
+sub opts {
+ my $self = shift;
+ return $self->{opts};
+}
+
+sub add_message {
+ my $self = shift;
+ my ($code, @messages) = @_;
+ $code = (qw(ok warning critical unknown))[$code] if $code =~ /^\d+$/;
+ $code = lc $code;
+ push @{$self->{messages}->{$code}}, @messages;
+}
+
+sub remove_message {
+ my $self = shift;
+ my ($code, @messages) = @_;
+ $code = (qw(ok warning critical unknown))[$code] if $code =~ /^\d+$/;
+ $code = lc $code;
+ pop @{$self->{messages}->{$code}};
+}
+
+sub add_perfdata {
+ my ($self, %args) = @_;
+ my $str = $args{label}.'='.$args{value};
+ if ($args{uom}) {
+ $str .= $args{uom};
+ }
+ if ($args{warning}) {
+ $str .= ';'.$args{warning};
+ }
+ if ($args{critical}) {
+ $str .= ';'.$args{critical};
+ }
+ push @{$self->{perfdata}}, $str;
+}
+
+
+sub check_messages {
+ my $self = shift;
+ my %args = @_;
+
+ # Add object messages to any passed in as args
+ for my $code (qw(critical warning unknown ok)) {
+ my $messages = $self->{messages}->{$code} || [];
+ if ($args{$code}) {
+ unless (ref $args{$code} eq 'ARRAY') {
+ if ($code eq 'ok') {
+ $args{$code} = [ $args{$code} ];
+ }
+ }
+ push @{$args{$code}}, @$messages;
+ } else {
+ $args{$code} = $messages;
+ }
+ }
+ my %arg = %args;
+ $arg{join} = ' ' unless defined $arg{join};
+
+ # Decide $code
+ my $code = OK;
+ $code ||= CRITICAL if @{$arg{critical}};
+ $code ||= WARNING if @{$arg{warning}};
+ $code ||= UNKNOWN if @{$arg{unknown}};
+ return $code unless wantarray;
+
+ # Compose message
+ my $message = '';
+ if ($arg{join_all}) {
+ $message = join( $arg{join_all},
+ map { @$_ ? join( $arg{'join'}, @$_) : () }
+ $arg{critical},
+ $arg{warning},
+ $arg{unknown},
+ $arg{ok} ? (ref $arg{ok} ? $arg{ok} : [ $arg{ok} ]) : []
+ );
+ }
+
+ else {
+ $message ||= join( $arg{'join'}, @{$arg{critical}} )
+ if $code == CRITICAL;
+ $message ||= join( $arg{'join'}, @{$arg{warning}} )
+ if $code == WARNING;
+ $message ||= join( $arg{'join'}, @{$arg{unknown}} )
+ if $code == UNKNOWN;
+ $message ||= ref $arg{ok} ? join( $arg{'join'}, @{$arg{ok}} ) : $arg{ok}
+ if $arg{ok};
+ }
+
+ return ($code, $message);
+}
+
+sub nagios_exit {
+ my $self = shift;
+ my ($code, $message, $arg) = @_;
+ $code = $ERRORS{$code} if defined $code && exists $ERRORS{$code};
+ $code = UNKNOWN unless defined $code && exists $STATUS_TEXT{$code};
+ $message = '' unless defined $message;
+ if (ref $message && ref $message eq 'ARRAY') {
+ $message = join(' ', map { chomp; $_ } @$message);
+ } else {
+ chomp $message;
+ }
+ my $output = "$STATUS_TEXT{$code}";
+ $output .= " - $message" if defined $message && $message ne '';
+ if (scalar (@{$self->{perfdata}})) {
+ $output .= " | ".join(" ", @{$self->{perfdata}});
+ }
+ $output .= "\n";
+ print $output;
+ exit $code;
+}
+
+package Nagios::MiniPlugin::Getopt;
+
+use strict;
+use File::Basename;
+use Data::Dumper;
+use Getopt::Long qw(:config no_ignore_case bundling);
+
+# Standard defaults
+my %DEFAULT = (
+ timeout => 15,
+ verbose => 0,
+ license =>
+"This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY.
+It may be used, redistributed and/or modified under the terms of the GNU
+General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt).",
+);
+# Standard arguments
+my @ARGS = ({
+ spec => 'usage|?',
+ help => "-?, --usage\n Print usage information",
+ }, {
+ spec => 'help|h',
+ help => "-h, --help\n Print detailed help screen",
+ }, {
+ spec => 'version|V',
+ help => "-V, --version\n Print version information",
+ }, {
+ #spec => 'extra-opts:s@',
+ #help => "--extra-opts=[<section>[@<config_file>]]\n Section and/or config_file from which to load extra options (may repeat)",
+ }, {
+ spec => 'timeout|t=i',
+ help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)",
+ default => $DEFAULT{timeout},
+ }, {
+ spec => 'verbose|v+',
+ help => "-v, --verbose\n Show details for command-line debugging (can repeat up to 3 times)",
+ default => $DEFAULT{verbose},
+ },
+);
+# Standard arguments we traditionally display last in the help output
+my %DEFER_ARGS = map { $_ => 1 } qw(timeout verbose);
+
+sub _init
+{
+ my $self = shift;
+ my %params = @_;
+ # Check params
+ my $plugin = basename($ENV{NAGIOS_PLUGIN} || $0);
+ #my %attr = validate( @_, {
+ my %attr = (
+ usage => 1,
+ version => 0,
+ url => 0,
+ plugin => { default => $plugin },
+ blurb => 0,
+ extra => 0,
+ 'extra-opts' => 0,
+ license => { default => $DEFAULT{license} },
+ timeout => { default => $DEFAULT{timeout} },
+ );
+
+ # Add attr to private _attr hash (except timeout)
+ $self->{timeout} = delete $attr{timeout};
+ $self->{_attr} = { %attr };
+ foreach (keys %{$self->{_attr}}) {
+ if (exists $params{$_}) {
+ $self->{_attr}->{$_} = $params{$_};
+ } else {
+ $self->{_attr}->{$_} = $self->{_attr}->{$_}->{default}
+ if ref ($self->{_attr}->{$_}) eq 'HASH' &&
+ exists $self->{_attr}->{$_}->{default};
+ }
+ }
+ # Chomp _attr values
+ chomp foreach values %{$self->{_attr}};
+
+ # Setup initial args list
+ $self->{_args} = [ grep { exists $_->{spec} } @ARGS ];
+
+ $self
+}
+
+sub new
+{
+ my $class = shift;
+ my $self = bless {}, $class;
+ $self->_init(@_);
+}
+
+sub add_arg {
+ my $self = shift;
+ my %arg = @_;
+ push (@{$self->{_args}}, \%arg);
+}
+
+sub getopts {
+ my $self = shift;
+ my %commandline = ();
+ my @params = map { $_->{spec} } @{$self->{_args}};
+ if (! GetOptions(\%commandline, @params)) {
+ $self->print_help();
+ exit 0;
+ } else {
+ no strict 'refs';
+ do { $self->print_help(); exit 0; } if $commandline{help};
+ do { $self->print_version(); exit 0 } if $commandline{version};
+ do { $self->print_usage(); exit 0 } if $commandline{usage};
+ foreach (map { $_->{spec} =~ /^([\w\-]+)/; $1; } @{$self->{_args}}) {
+ my $field = $_;
+ *{"$field"} = sub {
+ return $self->{opts}->{$field};
+ };
+ }
+ foreach (grep { exists $_->{default} } @{$self->{_args}}) {
+ $_->{spec} =~ /^([\w\-]+)/;
+ my $spec = $1;
+ $self->{opts}->{$spec} = $_->{default};
+ }
+ foreach (keys %commandline) {
+ $self->{opts}->{$_} = $commandline{$_};
+ }
+ }
+}
+
+sub get {
+ my $self = shift;
+ my $opt = shift;
+ return $self->{opts}->{$opt};
+}
+
+sub print_help {
+ my $self = shift;
+ $self->print_version();
+ printf "\n%s\n", $self->{_attr}->{license};
+ printf "\n%s\n\n", $self->{_attr}->{blurb};
+ $self->print_usage();
+ foreach (@{$self->{_args}}) {
+ printf " %s\n", $_->{help};
+ }
+ exit 0;
+}
+
+sub print_usage {
+ my $self = shift;
+ printf $self->{_attr}->{usage}, $self->{_attr}->{plugin};
+ print "\n";
+}
+
+sub print_version {
+ my $self = shift;
+ printf "%s %s", $self->{_attr}->{plugin}, $self->{_attr}->{version};
+ printf " [%s]", $self->{_attr}->{url} if $self->{_attr}->{url};
+ print "\n";
+}
+
+sub print_license {
+ my $self = shift;
+ printf "%s\n", $self->{_attr}->{license};
+ print "\n";
+}
+
+
+package SNMP::Utils;
+
+use strict;
+
+{
+ sub get_indices {
+ my $oids = shift;
+ my $entry = shift;
+ my $numindices = shift;
+ # find all oids beginning with $entry
+ # then skip one field for the sequence
+ # then read the next numindices fields
+ my $entrypat = $entry;
+ $entrypat =~ s/\./\\\./g;
+ my @indices = map {
+ /^$entrypat\.\d+\.(.*)/ && $1;
+ } grep {
+ /^$entrypat/
+ } keys %{$oids};
+ my %seen = ();
+ my @o = map {[split /\./]} sort grep !$seen{$_}++, @indices;
+ return @o;
+ }
+
+ sub get_size {
+ my $oids = shift;
+ my $entry = shift;
+ my $entrypat = $entry;
+ $entrypat =~ s/\./\\\./g;
+ my @entries = grep {
+ /^$entrypat/
+ } keys %{$oids};
+ return scalar(@entries);
+ }
+
+ sub get_object {
+ my $oids = shift;
+ my $object = shift;
+ my @indices = @_;
+ #my $oid = $object.'.'.join('.', @indices);
+ my $oid = $object;
+ $oid .= '.'.join('.', @indices) if (@indices);
+ return $oids->{$oid};
+ }
+
+ sub get_object_value {
+ my $oids = shift;
+ my $object = shift;
+ my $values = shift;
+ my @indices = @_;
+ my $key = get_object($oids, $object, @indices);
+ if (defined $key) {
+ return $values->{$key};
+ } else {
+ return undef;
+ }
+ }
+
+ #SNMP::Utils::counter([$idxs1, $idxs2], $idx1, $idx2),
+ # this flattens a n-dimensional array and returns the absolute position
+ # of the element at position idx1,idx2,...,idxn
+ # element 1,2 in table 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2 is at pos 6
+ sub get_number {
+ my $indexlists = shift; #, zeiger auf array aus [1, 2]
+ my @element = @_;
+ my $dimensions = scalar(@{$indexlists->[0]});
+ my @sorted = ();
+ my $number = 0;
+ if ($dimensions == 1) {
+ @sorted =
+ sort { $a->[0] <=> $b->[0] } @{$indexlists};
+ } elsif ($dimensions == 2) {
+ @sorted =
+ sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @{$indexlists};
+ } elsif ($dimensions == 3) {
+ @sorted =
+ sort { $a->[0] <=> $b->[0] ||
+ $a->[1] <=> $b->[1] ||
+ $a->[2] <=> $b->[2] } @{$indexlists};
+ }
+ foreach (@sorted) {
+ if ($dimensions == 1) {
+ if ($_->[0] == $element[0]) {
+ last;
+ }
+ } elsif ($dimensions == 2) {
+ if ($_->[0] == $element[0] && $_->[1] == $element[1]) {
+ last;
+ }
+ } elsif ($dimensions == 3) {
+ if ($_->[0] == $element[0] &&
+ $_->[1] == $element[1] &&
+ $_->[2] == $element[2]) {
+ last;
+ }
+ }
+ $number++;
+ }
+ return ++$number;
+ }
+
+}
+
+package HP::Proliant::Component::EventSubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ events => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ $self = HP::Proliant::Component::EventSubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ $self = HP::Proliant::Component::EventSubsystem::CLI->new(%params);
+ } else {
+ die "unknown method";
+ }
+ # repair dates
+ my $lasttime = 0;
+ for my $event (reverse @{$self->{events}}) {
+ if ($event->{cpqHeEventLogUpdateTime} != 0) {
+ $lasttime = $event->{cpqHeEventLogUpdateTime};
+ } else {
+ $event->{cpqHeEventLogUpdateTime} = $lasttime;
+ }
+ }
+ # maybe the most recent events had zero timestamps.
+ # fill them up with timestamps from the past.
+ for my $event (@{$self->{events}}) {
+ if ($event->{cpqHeEventLogUpdateTime} != 0) {
+ $lasttime = $event->{cpqHeEventLogUpdateTime};
+ } else {
+ $event->{cpqHeEventLogUpdateTime} = $lasttime;
+ }
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking events');
+ if (scalar (@{$self->{events}}) == 0) {
+ #$self->overall_check();
+ $self->add_info('no events found');
+ } else {
+ foreach (sort { $a->{cpqHeEventLogEntryNumber} <=> $b->{cpqHeEventLogEntryNumber}}
+ @{$self->{events}}) {
+ $_->check($self->{warningtime}, $self->{criticaltime});
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{events}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::EventSubsystem::Event;
+our @ISA = qw(HP::Proliant::Component::EventSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+{
+ our $interesting_events = {
+ # POST Error: 201-Memory Error Multi-bit error occurred during memory initialization, Board 1, Bank B. Bank containing DIMM(s) has been disabled..
+ # POST Error: 201-Memory Error Single-bit error occured during memory initialization, Board 1, DIMM 1. Bank containing DIMM(s) has been disabled..
+ # POST Error: 207-Memory initialization error on Memory Board 5 DIMM 7. The operating system may not have access to all of the memory installed in the system..
+ # POST Error: 207-Invalid Memory Configuration-Mismatched DIMMs within DIMM Bank Memory in Bank A Not Utilized..
+ # POST Error: 210 - Quick Path Interconnect (QPI) Link Degradation. A QPI link is operating in a degraded performace state..
+ 'POST Messages' => [
+ '201-Memory', '207-Memory',
+ '210\s*-\s*Quick Path Interconnect.*degraded.*'
+ ],
+ 'Main Memory' => [
+ 'Corrected Memory Error threshold exceeded',
+ ],
+ };
+}
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqHeEventLogEntryNumber => $params{cpqHeEventLogEntryNumber},
+ cpqHeEventLogEntrySeverity => lc $params{cpqHeEventLogEntrySeverity},
+ cpqHeEventLogEntryClass => $params{cpqHeEventLogEntryClass},
+ cpqHeEventLogEntryCount => $params{cpqHeEventLogEntryCount} || 1,
+ cpqHeEventLogInitialTime => $params{cpqHeEventLogInitialTime},
+ cpqHeEventLogUpdateTime => $params{cpqHeEventLogUpdateTime},
+ cpqHeEventLogErrorDesc => $params{cpqHeEventLogErrorDesc},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ if (! $self->{cpqHeEventLogInitialTime}) {
+ $self->{cpqHeEventLogInitialTime} = $self->{cpqHeEventLogUpdateTime};
+ }
+ #
+ #
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ # |warn |crit |now
+ #
+ #<----- ignore -------><----- warning ------><---------- critical --------->
+ #
+ # If we have --eventrange <warnlookback>/<critlookback>
+ # Very young events are shown as critical
+ # If the event gets older, it is shown as warning
+ # At some time, the event is no longer shown
+ # Without --eventrange the event is shown as critical until you manually repair it
+ if ($params{runtime}->{options}->{eventrange}) {
+ my ($warningrange, $criticalrange) = split(/\//, $params{runtime}->{options}->{eventrange});
+ if (! $criticalrange) {
+ $criticalrange = $warningrange;
+ }
+ if ($criticalrange =~ /^(\d+)[s]*$/) {
+ $criticalrange = $1;
+ } elsif ($criticalrange =~ /^(\d+)m$/) {
+ $criticalrange = $1 * 60;
+ } elsif ($criticalrange =~ /^(\d+)h$/) {
+ $criticalrange = $1 * 3600;
+ } elsif ($criticalrange =~ /^(\d+)d$/) {
+ $criticalrange = $1 * 3600 * 24;
+ } else {
+ die "range has to be <number>[smhd]";
+ }
+ if ($warningrange =~ /^(\d+)[s]*$/) {
+ $warningrange = $1;
+ } elsif ($warningrange =~ /^(\d+)m$/) {
+ $warningrange = $1 * 60;
+ } elsif ($warningrange =~ /^(\d+)h$/) {
+ $warningrange = $1 * 3600;
+ } elsif ($warningrange =~ /^(\d+)d$/) {
+ $warningrange = $1 * 3600 * 24;
+ } else {
+ die "range has to be <number>[smhd]";
+ }
+ $self->{warningtime} = time - $warningrange;
+ $self->{criticaltime} = time - $criticalrange;
+ } else {
+ $self->{warningtime} = 0;
+ $self->{criticaltime} = 0;
+ }
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('evt', $self->{cpqHeEventLogEntryNumber});
+ # only check severity "critical" and "caution"
+ # optional: only check interesting events
+ # POST events only if they date maximum from reboot-5min
+ # younger than critical? -> critical
+ #
+ my $uptime = do { local (@ARGV, $/) = "/proc/uptime"; my $x = <>; close ARGV; $x };
+ # also watch 10 minutes of booting before the operating system starts ticking
+ my $boottime = time - int((split(/\s+/, $uptime))[0]) - 600;
+ $self->add_info(sprintf "Event: %d Added: %s Class: (%s) %s %s",
+ $self->{cpqHeEventLogEntryNumber},
+ $self->{cpqHeEventLogUpdateTime},
+ $self->{cpqHeEventLogEntryClass},
+ $self->{cpqHeEventLogEntrySeverity},
+ $self->{cpqHeEventLogErrorDesc});
+ if ($self->{cpqHeEventLogEntrySeverity} eq "caution" ||
+ $self->{cpqHeEventLogEntrySeverity} eq "critical") {
+ if ($self->{cpqHeEventLogUpdateTime} >= $boottime) {
+ foreach my $class (keys %{$HP::Proliant::Component::EventSubsystem::Event::interesting_events}) {
+ foreach my $pattern (@{$HP::Proliant::Component::EventSubsystem::Event::interesting_events->{$class}}) {
+ if ($self->{cpqHeEventLogErrorDesc} =~ /$pattern/) {
+ if ($self->{cpqHeEventLogUpdateTime} < $self->{warningtime}) {
+ # you didn't care for this problem too long.
+ # don't say i didn't warn you.
+ if (0) {
+ # auto-ack?
+ }
+ } elsif ($self->{cpqHeEventLogUpdateTime} < $self->{criticaltime}) {
+ $self->add_message(WARNING, $self->{info});
+ } else {
+ $self->add_message(CRITICAL, $self->{info});
+ }
+ }
+ }
+ }
+ }
+ } else {
+ # info, repair...
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[EVENT_%s]\n", $self->{cpqHeEventLogEntryNumber};
+ foreach (qw(cpqHeEventLogEntryNumber cpqHeEventLogEntrySeverity
+ cpqHeEventLogEntryCount cpqHeEventLogInitialTime
+ cpqHeEventLogUpdateTime cpqHeEventLogErrorDesc)) {
+ if ($_ =~ /.*Time$/) {
+ printf "%s: %s\n", $_, scalar localtime $self->{$_};
+ } else {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ }
+ printf "info: %s\n\n", $self->{info};
+}
+
+
+
+package HP::Proliant::Component::EventSubsystem::CLI;
+our @ISA = qw(HP::Proliant::Component::EventSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+use Time::Local;
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ events => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my %tmpevent = (
+ runtime => $params{runtime},
+ );
+ my $inblock = 0;
+ foreach (grep(/^iml/, split(/\n/, $self->{rawdata}))) {
+ s/^iml\s*//g;
+ if (/^Event:\s+(\d+)\s+[\w]+:\s+(\d+)\/(\d+)\/(\d+)\s+(\d+):(\d+)/) {
+ # Event: 31 Added: 09/22/2011 05:11
+ # 1 2 3 4 5 6
+ $tmpevent{cpqHeEventLogEntryNumber} = $1;
+ if ($4 == 0) {
+ # Event: 29 Added: 00/00/0000 00:00
+ $tmpevent{cpqHeEventLogUpdateTime} = 0;
+ } else {
+ eval {
+ $tmpevent{cpqHeEventLogUpdateTime} = timelocal(0, $6, $5, $3, $2 - 1, $4);
+ };
+ if ($@) {
+ # Event: 10 Added: 27/27/2027 27:27
+ $tmpevent{cpqHeEventLogUpdateTime} = 0;
+ }
+ }
+ $inblock = 1;
+ } elsif (/^(\w+):\s+(.*?)\s+\-\s+(.*)/) {
+ $tmpevent{cpqHeEventLogEntrySeverity} = $1;
+ $tmpevent{cpqHeEventLogEntryClass} = $2;
+ $tmpevent{cpqHeEventLogErrorDesc} = $3;
+ if ($tmpevent{cpqHeEventLogErrorDesc} =~ /.*?:\s+(\d+)/) {
+ $tmpevent{cpqHeEventLogEntryCode} = $1;
+ } else {
+ $tmpevent{cpqHeEventLogEntryCode} = 0;
+ }
+ } elsif (/^\s*$/) {
+ if ($inblock) {
+ $inblock = 0;
+ push(@{$self->{events}},
+ HP::Proliant::Component::EventSubsystem::Event->new(%tmpevent));
+ %tmpevent = (
+ runtime => $params{runtime},
+ );
+ }
+ }
+ }
+ if ($inblock) {
+ push(@{$self->{events}},
+ HP::Proliant::Component::EventSubsystem::Event->new(%tmpevent));
+ }
+}
+
+
+
+package HP::Proliant::Component::EventSubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::EventSubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+use Time::Local;
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ events => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->overall_init(%params);
+ $self->init(%params);
+ return $self;
+}
+
+sub overall_init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $params{rawdata};
+ # overall
+ my $cpqHeEventLogSupported = '1.3.6.1.4.1.232.6.2.11.1';
+ my $cpqHeEventLogSupportedValue = {
+ 1 => 'other',
+ 2 => 'notSupported',
+ 3 => 'supported',
+ 4 => 'clear',
+ };
+ my $cpqHeEventLogCondition = '1.3.6.1.4.1.232.6.2.11.2';
+ my $cpqHeEventLogConditionValue = {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ };
+ $self->{eventstatus} = lc SNMP::Utils::get_object_value(
+ $snmpwalk, $cpqHeEventLogCondition,
+ $cpqHeEventLogSupportedValue);
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqHeEventLogEntry => "1.3.6.1.4.1.232.6.2.11.3.1",
+ cpqHeEventLogEntryNumber => "1.3.6.1.4.1.232.6.2.11.3.1.1",
+ cpqHeEventLogEntrySeverity => "1.3.6.1.4.1.232.6.2.11.3.1.2",
+ cpqHeEventLogEntryClass => "1.3.6.1.4.1.232.6.2.11.3.1.3",
+ cpqHeEventLogEntryCode => "1.3.6.1.4.1.232.6.2.11.3.1.4",
+ cpqHeEventLogEntryCount => "1.3.6.1.4.1.232.6.2.11.3.1.5",
+ cpqHeEventLogInitialTime => "1.3.6.1.4.1.232.6.2.11.3.1.6",
+ cpqHeEventLogUpdateTime => "1.3.6.1.4.1.232.6.2.11.3.1.7",
+ cpqHeEventLogErrorDesc => "1.3.6.1.4.1.232.6.2.11.3.1.8",
+
+ cpqHeEventLogEntryClassValue => {
+ # 2 Fan Failure (Fan 1, Location I/O Board)
+ # Internal Storage System Overheating (Slot 0, Zone 1, Location Storage, Temperature Unknown)
+ # System Fans Not Redundant (Location I/O Board)
+ # MY MUSTARD: only critical events should lead to an alert, if at all. The caution events mean "loss of redundancy".
+ # We monitor temperatures and fan status anyway.
+ #2 => "",
+ # 3 Corrected Memory Error threshold exceeded (System Memory, Memory Module 1)
+ # Uncorrectable Memory Error detected by ROM-based memory validation (Board 1, Memory Module 4)
+ # MY MUSTARD: threshold exceeded is caution. Uncorrectable errors are critical. Both should be detected anyway.
+ 3 => "Main Memory",
+ # 4 Accelerator Cache Memory Parity Error (Socket 1)
+ #4 => "",
+ # 5 Processor Correctable error threshold exceeded (Board 0, Processor 2)
+ #5 => "",
+ # 6 Unrecoverable Intermodule Bus error (Error code 0x00000000)
+ #6 => "",
+ # 8 PCI Bus Error (Slot 0, Bus 0, Device 0, Function 0)
+ 8 => "PCI Bus",
+ # 10 1720-S.M.A.R.T. Hard Drive Detects Imminent Failure
+ # POST Error: 201-Memory Error Multi-bit error occurred during memory initialization, Board 1, Bank B. Bank containing DIMM(s) has been disabled..
+ # POST Error: 201-Memory Error Single-bit error occured during memory initialization, Board 1, DIMM 1. Bank containing DIMM(s) has been disabled..
+ # POST Error: 207-Memory Configuration Warning - memory boards should be installed sequentially.
+ # POST Error: 210-Memory Board Failure on board 4.
+ # POST Error: 210-Memory Board Power Fault on board 3.
+ # POST Error: 207-Memory initialization error on Memory Board 5 DIMM 7. The operating system may not have access to all of the memory installed in the system..
+ # POST Error: 207-Invalid Memory Configuration-Mismatched DIMMs within DIMM Bank Memory in Bank A Not Utilized..
+ 10 => "POST Messages",
+ 11 => "Power Subsystem",
+ 13 => "ASR",
+ # 14 Automatic Operating System Shutdown Initiated Due to Overheat Condition
+ # Automatic Operating System Shutdown Initiated Due to Fan Failure
+ # Blue Screen Trap (BugCheck, STOP: 0x00000050 (0x9CB2C5B4, 0x00000001, 0x00000004, 0x00000000))
+ # Operating System failure (BugCheck, STOP: 0x000000AB (0x00000005, 0x00000488, 0x00000000, 0x00000002))
+ 14 => "OS Class",
+ # 15 Unknown Event (Class 15, Code 255)
+ #15 => "",
+ # 17 Network Adapter Link Down (Slot 0, Port 4)
+ # Network Adapters Redundancy Reduced (Slot 0, Port 1)
+ 17 => "Network Adapter",
+ # 19 Drive Array Device Failure (Slot 0, Bus 2, Bay 4)
+ # Internal SAS Enclosure Device Failure (Bay 1, Box 1, Port 2I, Slot 1)
+ #19 => "",
+ # 20 An Unrecoverable System Error (NMI) has occurred
+ # Unrecoverable System Error has occurred (Error code 0x01AE0E2F, 0x00000000)
+ 20 => "Unrecoverable System Error",
+ # 32 ROM flashed (New version: 01/09/2008)
+ 32 => "System Revision",
+ # 33 IML Cleared (Administrator)
+ # IML cleared through HP ProLiant Health Agent (cmahealthd)
+ # Insight Diagnostics Note: Physisches Festplattenlaufwerk 5, Controller Steckplatz 0-Diagnosis: Fehlgeschlagen
+ 33 => "Maintenance Note",
+ # 34 New Chassis Connected (Enclosure Address 27AC)
+ # Loss Of Chassis Connectivity (Enclosure Serial Number 8004******)
+ # Server Blade Enclosure Server Blade Inserted (Slot 16, Enclosure Address 0000)
+ #34 => "",
+ },
+ cpqHeEventLogEntrySeverityValue => {
+ 2 => "informational",
+ 3 => "infoWithAlert",
+ 6 => "repaired",
+ 9 => "caution",
+ 15 => "critical",
+ },
+ # Time
+ # 07 D8 09 02 11 11
+ };
+ # INDEX { cpqHeEventLogEntryNumber }
+ foreach ($self->get_entries($oids, 'cpqHeEventLogEntry')) {
+ if ($_->{cpqHeEventLogInitialTime} =~ /^(([0-9a-fA-F]{2})( [0-9a-fA-F]{2})*)\s*$/) {
+ $_->{cpqHeEventLogInitialTime} =~ s/ //;
+ my ($year, $month, $day, $hour, $min) = map { hex($_) } split(/\s+/, $_->{cpqHeEventLogInitialTime});
+ if ($year == 0) {
+ $_->{cpqHeEventLogInitialTime} = 0;
+ } else {
+ eval {
+ $_->{cpqHeEventLogInitialTime} = timelocal(0, $min, $hour, $day, $month - 1, $year);
+ };
+ if ($@) {
+ $_->{cpqHeEventLogInitialTime} = 0;
+ }
+ }
+ }
+ if ($_->{cpqHeEventLogUpdateTime} =~ /^(([0-9a-fA-F]{2})( [0-9a-fA-F]{2})*)\s*$/) {
+ $_->{cpqHeEventLogUpdateTime} =~ s/ //;
+ my ($year, $month, $day, $hour, $min) = map { hex($_) } split(/\s+/, $_->{cpqHeEventLogUpdateTime});
+ if ($year == 0) {
+ $_->{cpqHeEventLogUpdateTime} = 0;
+ } else {
+ eval {
+ $_->{cpqHeEventLogUpdateTime} = timelocal(0, $min, $hour, $day, $month - 1, $year);
+ };
+ if ($@) {
+ $_->{cpqHeEventLogUpdateTime} = 0;
+ }
+ }
+ }
+ if ($_->{cpqHeEventLogErrorDesc} =~ /^(([0-9a-fA-F]{2})(\s+[0-9a-fA-F]{2})*)\s*$/) {
+ $_->{cpqHeEventLogErrorDesc} = join "", map { chr($_) } map { if (hex($_) > 127) { 20; } else { hex($_) } } split(/\s+/, $_->{cpqHeEventLogErrorDesc});
+ }
+ push(@{$self->{events}},
+ HP::Proliant::Component::EventSubsystem::Event->new(%{$_}));
+ }
+}
+
+sub overall_check {
+ my $self = shift;
+ my $result = 0;
+ $self->blacklist('oe', '');
+ if ($self->{eventstatus}) {
+ if ($self->{eventstatus} eq "ok") {
+ $result = 0;
+ $self->add_info('eventlog system is ok');
+ } else {
+ $result = 0;
+ $self->add_info(sprintf "eventlog system is %s", $self->{eventstatus});
+ }
+ } else {
+ $result = 0;
+ $self->add_info('no event status found');
+ }
+}
+
+
+package HP::Proliant::Component::PowersupplySubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ powersupplies => [],
+ powerconverters => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ return HP::Proliant::Component::PowersupplySubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ return HP::Proliant::Component::PowersupplySubsystem::CLI->new(%params);
+ } else {
+ die "unknown method";
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking power supplies');
+ if (scalar (@{$self->{powersupplies}}) == 0) {
+ #$self->overall_check();
+ } else {
+ foreach (@{$self->{powersupplies}}) {
+ $_->check();
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{powersupplies}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::PowersupplySubsystem::Powersupply;
+our @ISA = qw(HP::Proliant::Component::PowersupplySubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqHeFltTolPowerSupplyChassis => $params{cpqHeFltTolPowerSupplyChassis},
+ cpqHeFltTolPowerSupplyBay => $params{cpqHeFltTolPowerSupplyBay},
+ cpqHeFltTolPowerSupplyPresent => $params{cpqHeFltTolPowerSupplyPresent},
+ cpqHeFltTolPowerSupplyCondition => $params{cpqHeFltTolPowerSupplyCondition},
+ cpqHeFltTolPowerSupplyRedundant => $params{cpqHeFltTolPowerSupplyRedundant},
+ blacklisted => 0,
+ info => undef,
+ extendexinfo => undef,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('p', $self->{cpqHeFltTolPowerSupplyBay});
+ if ($self->{cpqHeFltTolPowerSupplyPresent} eq "present") {
+ if ($self->{cpqHeFltTolPowerSupplyCondition} ne "ok") {
+ if ($self->{cpqHeFltTolPowerSupplyCondition} eq "other") {
+ $self->add_info(sprintf "powersupply %d is missing",
+ $self->{cpqHeFltTolPowerSupplyBay});
+ } else {
+ $self->add_info(sprintf "powersupply %d needs attention (%s)",
+ $self->{cpqHeFltTolPowerSupplyBay},
+ $self->{cpqHeFltTolPowerSupplyCondition});
+ }
+ $self->add_message(CRITICAL, $self->{info});
+ } else {
+ $self->add_info(sprintf "powersupply %d is %s",
+ $self->{cpqHeFltTolPowerSupplyBay},
+ $self->{cpqHeFltTolPowerSupplyCondition});
+ }
+ $self->add_extendedinfo(sprintf "ps_%s=%s",
+ $self->{cpqHeFltTolPowerSupplyBay},
+ $self->{cpqHeFltTolPowerSupplyCondition});
+ } else {
+ $self->add_info(sprintf "powersupply %d is %s",
+ $self->{cpqHeFltTolPowerSupplyBay},
+ $self->{cpqHeFltTolPowerSupplyPresent});
+ $self->add_extendedinfo(sprintf "ps_%s=%s",
+ $self->{cpqHeFltTolPowerSupplyBay},
+ $self->{cpqHeFltTolPowerSupplyPresent});
+ }
+}
+
+
+sub dump {
+ my $self = shift;
+ printf "[PS_%s]\n", $self->{cpqHeFltTolPowerSupplyBay};
+ foreach (qw(cpqHeFltTolPowerSupplyBay cpqHeFltTolPowerSupplyChassis
+ cpqHeFltTolPowerSupplyPresent cpqHeFltTolPowerSupplyCondition
+ cpqHeFltTolPowerSupplyRedundant)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n\n", $self->{info};
+}
+
+
+package HP::Proliant::Component::PowersupplySubsystem::Powerconverter;
+our @ISA = qw(HP::Proliant::Component::PowersupplySubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+
+ cpqHePowerConvEntry => $params{cpqHePowerConvEntry},
+ cpqHePowerConvChassis => $params{cpqHePowerConvChassis},
+ cpqHePowerConvIndex => $params{cpqHePowerConvIndex},
+ cpqHePowerConvPresent => $params{cpqHePowerConvPresent},
+ cpqHePowerConvRedundant => $params{cpqHePowerConvRedundant},
+ cpqHePowerConvCondition => $params{cpqHePowerConvCondition},
+ cpqHePowerConvHwLocation => $params{cpqHePowerConvHwLocation},
+ blacklisted => 0,
+ info => undef,
+ extendexinfo => undef,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('pc', $self->{cpqHePowerConvIndex});
+ if ($self->{cpqHePowerConvPresent} eq "present") {
+ if ($self->{cpqHePowerConvCondition} ne "ok") {
+ if ($self->{cpqHePowerConvCondition} eq "other") {
+ $self->add_info(sprintf "powerconverter %d is missing",
+ $self->{cpqHePowerConvIndex});
+ } else {
+ $self->add_info(sprintf "powerconverter %d needs attention (%s)",
+ $self->{cpqHePowerConvIndex},
+ $self->{cpqHePowerConvCondition});
+ }
+ $self->add_message(CRITICAL, $self->{info});
+ } else {
+ $self->add_info(sprintf "powerconverter %d is %s",
+ $self->{cpqHePowerConvIndex},
+ $self->{cpqHePowerConvCondition});
+ }
+ $self->add_extendedinfo(sprintf "pc_%s=%s",
+ $self->{cpqHePowerConvIndex},
+ $self->{cpqHePowerConvCondition});
+ } else {
+ $self->add_info(sprintf "powerconverter %d is %s",
+ $self->{cpqHePowerConvIndex},
+ $self->{cpqHePowerConvPresent});
+ $self->add_extendedinfo(sprintf "pc_%s=%s",
+ $self->{cpqHePowerConvIndex},
+ $self->{cpqHePowerConvPresent});
+ }
+}
+
+
+sub dump {
+ my $self = shift;
+ printf "[PS_%s]\n", ($self->{cpqHePowerConvChassis} ? $self->{cpqHePowerConvChassis}.":" : "").$self->{cpqHePowerConvIndex};
+ foreach (qw(cpqHePowerConvIndex cpqHePowerConvPresent cpqHePowerConvRedundant cpqHePowerConvCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n\n", $self->{info};
+}
+
+
+
+package HP::Proliant::Component::PowersupplySubsystem::CLI;
+our @ISA = qw(HP::Proliant::Component::PowersupplySubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ powersupplies => [],
+ powerconverters => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my %tmpps = (
+ runtime => $self->{runtime},
+ cpqHeFltTolPowerSupplyChassis => 1,
+ );
+ my $inblock = 0;
+ foreach (grep(/^powersupply/, split(/\n/, $self->{rawdata}))) {
+ s/^powersupply\s*//g;
+ if (/^Power supply #(\d+)/) {
+ if ($inblock) {
+ $inblock = 0;
+ push(@{$self->{powersupplies}},
+ HP::Proliant::Component::PowersupplySubsystem::Powersupply->new(%tmpps));
+ %tmpps = (
+ runtime => $self->{runtime},
+ cpqHeFltTolPowerSupplyChassis => 1,
+ );
+ }
+ $tmpps{cpqHeFltTolPowerSupplyBay} = $1;
+ $inblock = 1;
+ } elsif (/\s*Present\s+:\s+(\w+)/) {
+ $tmpps{cpqHeFltTolPowerSupplyPresent} = lc $1 eq 'yes' ? 'present' :
+ lc $1 eq 'no' ? 'absent': 'other';
+ } elsif (/\s*Redundant\s*:\s+(\w+)/) {
+ $tmpps{cpqHeFltTolPowerSupplyRedundant} = lc $1 eq 'yes' ? 'redundant' :
+ lc $1 eq 'no' ? 'notRedundant' : 'other';
+ } elsif (/\s*Condition\s*:\s+(\w+)/) {
+ $tmpps{cpqHeFltTolPowerSupplyCondition} = lc $1;
+ } elsif (/\s*Power Supply not present/) {
+ $tmpps{cpqHeFltTolPowerSupplyPresent} = "absent";
+ $tmpps{cpqHeFltTolPowerSupplyCondition} = "other";
+ $tmpps{cpqHeFltTolPowerSupplyRedundant} = "notRedundant";
+ } elsif (/^\s*$/) {
+ if ($inblock) {
+ $inblock = 0;
+ push(@{$self->{powersupplies}},
+ HP::Proliant::Component::PowersupplySubsystem::Powersupply->new(%tmpps));
+ %tmpps = (
+ runtime => $self->{runtime},
+ cpqHeFltTolPowerSupplyChassis => 1,
+ );
+ }
+ }
+ }
+ if ($inblock) {
+ push(@{$self->{powersupplies}},
+ HP::Proliant::Component::PowersupplySubsystem::Powersupply->new(%tmpps));
+ %tmpps = (
+ runtime => $params{runtime},
+ );
+ }
+}
+
+
+package HP::Proliant::Component::PowersupplySubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::PowersupplySubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ powersupplies => [],
+ powerconverters => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqHeFltTolPowerSupplyEntry => "1.3.6.1.4.1.232.6.2.9.3.1",
+ cpqHeFltTolPowerSupplyChassis => "1.3.6.1.4.1.232.6.2.9.3.1.1",
+ cpqHeFltTolPowerSupplyBay => "1.3.6.1.4.1.232.6.2.9.3.1.2",
+ cpqHeFltTolPowerSupplyPresent => "1.3.6.1.4.1.232.6.2.9.3.1.3",
+ cpqHeFltTolPowerSupplyCondition => "1.3.6.1.4.1.232.6.2.9.3.1.4",
+ cpqHeFltTolPowerSupplyRedundant => "1.3.6.1.4.1.232.6.2.9.3.1.9",
+ cpqHeFltTolPowerSupplyPresentValue => {
+ 1 => "other",
+ 2 => "absent",
+ 3 => "present",
+ },
+ cpqHeFltTolPowerSupplyConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqHeFltTolPowerSupplyRedundantValue => {
+ 1 => "other",
+ 2 => "notRedundant",
+ 3 => "redundant",
+ },
+ };
+
+ # INDEX { cpqHeFltTolPowerSupplyChassis, cpqHeFltTolPowerSupplyBay }
+ foreach ($self->get_entries($oids, 'cpqHeFltTolPowerSupplyEntry')) {
+ push(@{$self->{powersupplies}},
+ HP::Proliant::Component::PowersupplySubsystem::Powersupply->new(%{$_}));
+ }
+
+ $oids = {
+ cpqHePowerConvEntry => "1.3.6.1.4.1.232.6.2.13.3.1",
+ cpqHePowerConvChassis => "1.3.6.1.4.1.232.6.2.13.3.1.1",
+ cpqHePowerConvIndex => "1.3.6.1.4.1.232.6.2.13.3.1.2",
+ cpqHePowerConvPresent => "1.3.6.1.4.1.232.6.2.13.3.1.3",
+ cpqHePowerConvRedundant => "1.3.6.1.4.1.232.6.2.13.3.1.6",
+ cpqHePowerConvCondition => "1.3.6.1.4.1.232.6.2.13.3.1.8",
+ cpqHePowerConvPresentValue => {
+ 1 => "other",
+ 2 => "absent",
+ 3 => "present",
+ },
+ cpqHePowerConvRedundantValue => {
+ 1 => "other",
+ 2 => "notRedundant",
+ 3 => "redundant",
+ },
+ cpqHePowerConvConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqHePowerConvHwLocation => "1.3.6.1.4.1.232.6.2.13.3.1.9",
+ };
+
+ # INDEX { cpqHePowerConvChassis cpqHePowerConvIndex }
+ foreach ($self->get_entries($oids, 'cpqHePowerConvEntry')) {
+ push(@{$self->{powerconverters}},
+ HP::Proliant::Component::PowersupplySubsystem::Powerconverter->new(%{$_}));
+ }
+ # keine ahnung, was man damit machen kann
+
+}
+
+package HP::Proliant::Component::TemperatureSubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+################################## custom_thresholds
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ temperatures => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($params{runtime}->{options}->{customthresholds}) {
+ if (-f $params{runtime}->{options}->{customthresholds}) {
+ $params{runtime}->{options}->{customthresholds} =
+ do { local (@ARGV, $/) =
+ $params{runtime}->{options}->{customthresholds}; <> };
+ }
+ foreach my $ct_items
+ (split(/\//, $params{runtime}->{options}->{customthresholds})) {
+ if ($ct_items =~ /^(\d+):(\d+)$/) {
+ $params{runtime}->{options}->{thresholds}->{$1} = $2;
+ } else {
+ die sprintf "invalid threshold %s", $ct_items;
+ }
+ }
+ }
+ if ($self->{method} eq 'snmp') {
+ return HP::Proliant::Component::TemperatureSubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ return HP::Proliant::Component::TemperatureSubsystem::CLI->new(%params);
+ } else {
+ die "unknown method";
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking temperatures');
+ if (scalar (@{$self->{temperatures}}) == 0) {
+ #$self->overall_check();
+ $self->add_info('no temperatures found');
+ } else {
+ foreach (sort { $a->{cpqHeTemperatureIndex} <=> $b->{cpqHeTemperatureIndex}}
+ @{$self->{temperatures}}) {
+ $_->check();
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{temperatures}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::TemperatureSubsystem::Temperature;
+our @ISA = qw(HP::Proliant::Component::TemperatureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqHeTemperatureChassis => $params{cpqHeTemperatureChassis},
+ cpqHeTemperatureIndex => $params{cpqHeTemperatureIndex},
+ cpqHeTemperatureLocale => $params{cpqHeTemperatureLocale},
+ cpqHeTemperatureCelsius => $params{cpqHeTemperatureCelsius},
+ cpqHeTemperatureThresholdCelsius => $params{cpqHeTemperatureThresholdCelsius},
+ cpqHeTemperatureCondition => $params{cpqHeTemperatureCondition},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($params{runtime}->{options}->{celsius}) {
+ $self->{cpqHeTemperatureUnits} = 'C';
+ $self->{cpqHeTemperature} = $self->{cpqHeTemperatureCelsius};
+ $self->{cpqHeTemperatureThreshold} =
+ $self->{cpqHeTemperatureThresholdCelsius};
+ } else {
+ $self->{cpqHeTemperatureUnits} = 'F';
+ $self->{cpqHeTemperature} =
+ (($self->{cpqHeTemperatureCelsius} * 9) / 5) + 32;
+ $self->{cpqHeTemperatureThreshold} =
+ (($self->{cpqHeTemperatureThresholdCelsius} * 9) / 5) + 32;
+ }
+ my $index = $self->{cpqHeTemperatureIndex};
+ if (exists $params{runtime}->{options}->{thresholds}->{$index}) {
+ $self->{cpqHeTemperatureThreshold} =
+ $params{runtime}->{options}->{thresholds}->{$index};
+
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('t', $self->{cpqHeTemperatureIndex});
+ if ($self->{cpqHeTemperature} > $self->{cpqHeTemperatureThreshold}) {
+ $self->add_info(sprintf "%d %s temperature too high (%d%s, %d max)",
+ $self->{cpqHeTemperatureIndex}, $self->{cpqHeTemperatureLocale},
+ $self->{cpqHeTemperature}, $self->{cpqHeTemperatureUnits},
+ $self->{cpqHeTemperatureThreshold});
+ $self->add_message(CRITICAL, $self->{info});
+ } elsif ($self->{cpqHeTemperature} < 0) {
+ # #21 SCSI_BACKPLANE_ZONE -1C/31F 60C/140F OK - can't be true
+ $self->add_info(sprintf "%d %s temperature too low (%d%s)",
+ $self->{cpqHeTemperatureIndex}, $self->{cpqHeTemperatureLocale},
+ $self->{cpqHeTemperature}, $self->{cpqHeTemperatureUnits});
+ $self->add_message(CRITICAL, $self->{info});
+ } else {
+ $self->add_info(sprintf "%d %s temperature is %d%s (%d max)",
+ $self->{cpqHeTemperatureIndex}, $self->{cpqHeTemperatureLocale},
+ $self->{cpqHeTemperature}, $self->{cpqHeTemperatureUnits},
+ $self->{cpqHeTemperatureThreshold});
+ }
+ if ($self->{runtime}->{options}->{perfdata} == 2) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('temp_%s', $self->{cpqHeTemperatureIndex}),
+ value => $self->{cpqHeTemperature},
+ warning => $self->{cpqHeTemperatureThreshold},
+ critical => $self->{cpqHeTemperatureThreshold}
+ );
+ } elsif ($self->{runtime}->{options}->{perfdata} == 1) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('temp_%s_%s', $self->{cpqHeTemperatureIndex},
+ $self->{cpqHeTemperatureLocale}),
+ value => $self->{cpqHeTemperature},
+ warning => $self->{cpqHeTemperatureThreshold},
+ critical => $self->{cpqHeTemperatureThreshold}
+ );
+ }
+ $self->add_extendedinfo(sprintf "temp_%s=%d",
+ $self->{cpqHeTemperatureIndex},
+ $self->{cpqHeTemperature});
+}
+
+sub dump {
+ my $self = shift;
+ printf "[TEMP_%s]\n", $self->{cpqHeTemperatureIndex};
+ foreach (qw(cpqHeTemperatureChassis cpqHeTemperatureIndex
+ cpqHeTemperatureLocale cpqHeTemperatureCelsius cpqHeTemperatureThreshold
+ cpqHeTemperatureCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n\n", $self->{info};
+}
+
+
+
+package HP::Proliant::Component::TemperatureSubsystem::CLI;
+our @ISA = qw(HP::Proliant::Component::TemperatureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ temperatures => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my $tempcnt = 1;
+ foreach (grep(/^temp/, split(/\n/, $params{rawdata}))) {
+ s/^temp\s*//g;
+ if (/^#(\d+)\s+([\w_\/\-#]+)\s+(-*\d+)C\/(\d+)F\s+(\d+)C\/(\d+)F/) {
+ my %params = ();
+ $params{runtime} = $self->{runtime};
+ $params{cpqHeTemperatureChassis} = 1;
+ $params{cpqHeTemperatureIndex} = $1;
+ $params{cpqHeTemperatureLocale} = lc $2;
+ $params{cpqHeTemperatureCelsius} = $3;
+ $params{cpqHeTemperatureThresholdCelsius} = $5;
+ $params{cpqHeTemperatureCondition} = 'unknown';
+ push(@{$self->{temperatures}},
+ HP::Proliant::Component::TemperatureSubsystem::Temperature->new(
+ %params));
+ } elsif (/^#(\d+)\s+([\w_\/\-#]+)\s+\-\s+(\d+)C\/(\d+)F/) {
+ # #3 CPU#2 - 0C/0F
+ $self->trace(2, sprintf "skipping temperature %s", $_);
+ } elsif (/^#(\d+)\s+([\w_\/\-#]+)\s+(\d+)C\/(\d+)F\s+\-/) {
+ # #3 CPU#2 0C/0F -
+ $self->trace(2, sprintf "skipping temperature %s", $_);
+ } elsif (/^#(\d+)\s+([\w_\/\-#]+)\s+\-\s+\-/) {
+ # #3 CPU#2 - -
+ $self->trace(2, sprintf "skipping temperature %s", $_);
+ } elsif (/^#(\d+)/) {
+ $self->trace(0, sprintf "send this to lausser: %s", $_);
+ }
+ }
+}
+
+
+package HP::Proliant::Component::TemperatureSubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::TemperatureSubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ temperatures => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->overall_init(%params);
+ $self->init(%params);
+ return $self;
+}
+
+sub overall_init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $params{rawdata};
+ # overall
+ my $cpqHeThermalTempStatus = '1.3.6.1.4.1.232.6.2.6.3.0';
+ my $cpqHeThermalTempStatusValue = {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ };
+ $self->{tempstatus} = lc SNMP::Utils::get_object_value(
+ $snmpwalk, $cpqHeThermalTempStatus,
+ $cpqHeThermalTempStatusValue);
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqHeTemperatureEntry => "1.3.6.1.4.1.232.6.2.6.8.1",
+ cpqHeTemperatureChassis => "1.3.6.1.4.1.232.6.2.6.8.1.1",
+ cpqHeTemperatureIndex => "1.3.6.1.4.1.232.6.2.6.8.1.2",
+ cpqHeTemperatureLocale => "1.3.6.1.4.1.232.6.2.6.8.1.3",
+ cpqHeTemperatureCelsius => "1.3.6.1.4.1.232.6.2.6.8.1.4",
+ cpqHeTemperatureThresholdCelsius => "1.3.6.1.4.1.232.6.2.6.8.1.5",
+ cpqHeTemperatureCondition => "1.3.6.1.4.1.232.6.2.6.8.1.6",
+ cpqHeTemperatureLocaleValue => {
+ 1 => "other",
+ 2 => "unknown",
+ 3 => "system",
+ 4 => "systemBoard",
+ 5 => "ioBoard",
+ 6 => "cpu",
+ 7 => "memory",
+ 8 => "storage",
+ 9 => "removableMedia",
+ 10 => "powerSupply",
+ 11 => "ambient",
+ 12 => "chassis",
+ 13 => "bridgeCard",
+ },
+ cpqHeTemperatureConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ }
+ };
+ # INDEX { cpqHeTemperatureChassis, cpqHeTemperatureIndex }
+ foreach ($self->get_entries($oids, 'cpqHeTemperatureEntry')) {
+ push(@{$self->{temperatures}},
+ HP::Proliant::Component::TemperatureSubsystem::Temperature->new(%{$_}));
+ }
+}
+
+sub overall_check {
+ my $self = shift;
+ my $result = 0;
+ $self->blacklist('ots', '');
+ if ($self->{tempstatus}) {
+ if ($self->{tempstatus} eq "ok") {
+ $result = 0;
+ $self->add_info('all temp sensors are within normal operating range');
+ } elsif ($self->{tempstatus} eq "degraded") {
+ $result = 1;
+ $self->add_info('a temp sensor is outside of normal operating range');
+ } elsif ($self->{tempstatus} eq "failed") {
+ $result = 2;
+ $self->add_info('a temp sensor detects a condition that could permanently
+damage the system');
+ } elsif ($self->{tempstatus} eq "other") {
+ $result = 0;
+ $self->add_info('temp sensing is not supported by this system or driver');
+ }
+ } else {
+ $result = 0;
+ $self->add_info('no global temp status found');
+ }
+}
+
+
+package HP::Proliant::Component::CpuSubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+################################## scrapiron ##########
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ cpus => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ return HP::Proliant::Component::CpuSubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ return HP::Proliant::Component::CpuSubsystem::CLI->new(%params);
+ } else {
+ die "unknown method";
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking cpus');
+ if (scalar (@{$self->{cpus}}) == 0) {
+ # sachen gibts.....
+ # $self->overall_check(); # sowas ist mir nur einmal untergekommen
+ } else {
+ foreach (@{$self->{cpus}}) {
+ $_->check();
+ }
+ }
+}
+
+sub num_cpus {
+ my $self = shift;
+ return scalar @{$self->{cpus}};
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{cpus}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::CpuSubsystem::Cpu;
+our @ISA = qw(HP::Proliant::Component::CpuSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqSeCpuSlot => $params{cpqSeCpuSlot},
+ cpqSeCpuUnitIndex => $params{cpqSeCpuUnitIndex},
+ cpqSeCpuName => $params{cpqSeCpuName},
+ cpqSeCpuStatus => $params{cpqSeCpuStatus},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('c', $self->{cpqSeCpuUnitIndex});
+ if ($self->{cpqSeCpuStatus} ne "ok") {
+ if ($self->{runtime}->{options}{scrapiron} &&
+ ($self->{cpqSeCpuStatus} eq "unknown")) {
+ $self->add_info(sprintf "cpu %d probably ok (%s)",
+ $self->{cpqSeCpuUnitIndex}, $self->{cpqSeCpuStatus});
+ } else {
+ $self->add_info(sprintf "cpu %d needs attention (%s)",
+ $self->{cpqSeCpuUnitIndex}, $self->{cpqSeCpuStatus});
+ $self->add_message(CRITICAL, $self->{info});
+ }
+ } else {
+ $self->add_info(sprintf "cpu %d is %s",
+ $self->{cpqSeCpuUnitIndex}, $self->{cpqSeCpuStatus});
+ }
+ $self->add_extendedinfo(sprintf "cpu_%s=%s",
+ $self->{cpqSeCpuUnitIndex}, $self->{cpqSeCpuStatus});
+}
+
+sub dump {
+ my $self = shift;
+ printf "[CPU_%s]\n", $self->{cpqSeCpuUnitIndex};
+ foreach (qw(cpqSeCpuSlot cpqSeCpuUnitIndex cpqSeCpuName cpqSeCpuStatus)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+package HP::Proliant::Component::CpuSubsystem::CLI;
+our @ISA = qw(HP::Proliant::Component::CpuSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ cpus => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my %tmpcpu = (
+ runtime => $params{runtime},
+ );
+ my $inblock = 0;
+ foreach (grep(/^server/, split(/\n/, $self->{rawdata}))) {
+ if (/Processor:\s+(\d+)/) {
+ $tmpcpu{cpqSeCpuUnitIndex} = $1;
+ $inblock = 1;
+ } elsif (/Name\s*:\s+(.+?)\s*$/) {
+ $tmpcpu{cpqSeCpuName} = $1;
+ } elsif (/Status\s*:\s+(.+?)\s*$/) {
+ $tmpcpu{cpqSeCpuStatus} = lc $1;
+ } elsif (/Socket\s*:\s+(.+?)\s*$/) {
+ $tmpcpu{cpqSeCpuSlot} = $1;
+ } elsif (/^server\s*$/) {
+ if ($inblock) {
+ $inblock = 0;
+ push(@{$self->{cpus}},
+ HP::Proliant::Component::CpuSubsystem::Cpu->new(%tmpcpu));
+ %tmpcpu = (
+ runtime => $params{runtime},
+ );
+ }
+ }
+ }
+ if ($inblock) {
+ push(@{$self->{cpus}},
+ HP::Proliant::Component::CpuSubsystem::Cpu->new(%tmpcpu));
+ }
+}
+
+
+package HP::Proliant::Component::CpuSubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::CpuSubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ cpus => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ # CPQSTDEQ-MIB
+ my $oids = {
+ cpqSeCpuEntry => '1.3.6.1.4.1.232.1.2.2.1.1',
+ cpqSeCpuUnitIndex => '1.3.6.1.4.1.232.1.2.2.1.1.1',
+ cpqSeCpuSlot => '1.3.6.1.4.1.232.1.2.2.1.1.2',
+ cpqSeCpuName => '1.3.6.1.4.1.232.1.2.2.1.1.3',
+ cpqSeCpuStatus => '1.3.6.1.4.1.232.1.2.2.1.1.6',
+ cpqSeCpuStatusValue => {
+ 1 => "unknown",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ 5 => "disabled",
+ },
+ };
+
+ # INDEX { cpqSeCpuUnitIndex }
+ foreach ($self->get_entries($oids, 'cpqSeCpuEntry')) {
+ push(@{$self->{cpus}},
+ HP::Proliant::Component::CpuSubsystem::Cpu->new(%{$_}));
+ }
+}
+
+
+package HP::Proliant::Component::FanSubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+################################## fan_redundancy ##########
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ fans => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ return HP::Proliant::Component::FanSubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ return HP::Proliant::Component::FanSubsystem::CLI->new(%params);
+ } else {
+ die 'unknown method';
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking fans');
+ $self->blacklist('ff', '');
+ if (scalar (@{$self->{fans}}) == 0) {
+ $self->overall_check(); # sowas ist mir nur einmal untergekommen
+ # die maschine hatte alles in allem nur 2 oids (cpqHeFltTolFanChassis)
+ # SNMPv2-SMI::enterprises.232.6.2.6.7.1.1.0.1 = INTEGER: 0
+ # SNMPv2-SMI::enterprises.232.6.2.6.7.1.1.0.2 = INTEGER: 0
+ } else {
+ my $overallhealth = $self->overall_check();
+ foreach (@{$self->{fans}}) {
+ $_->{overallhealth} = $overallhealth;
+ $_->check();
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{fans}}) {
+ $_->dump();
+ }
+}
+
+sub get_fan_by_index {
+ my $self = shift;
+ my $index;
+ foreach (@{$self->{fans}}) {
+ return $_ if exists $_->{cpqHeFltTolFanIndex} &&
+ $_->{cpqHeFltTolFanIndex} == $index;
+ }
+ return undef;
+}
+
+
+package HP::Proliant::Component::FanSubsystem::Fan;
+our @ISA = qw(HP::Proliant::Component::FanSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ if (exists $params{cpqHeFltTolFanRedundant}) {
+ return HP::Proliant::Component::FanSubsystem::Fan::FTol->new(%params);
+ } else {
+ return HP::Proliant::Component::FanSubsystem::Fan::Thermal->new(%params);
+ }
+}
+
+
+package HP::Proliant::Component::FanSubsystem::Fan::FTol;
+our @ISA = qw(HP::Proliant::Component::FanSubsystem::Fan);
+
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqHeFltTolFanChassis => $params{cpqHeFltTolFanChassis},
+ cpqHeFltTolFanIndex => $params{cpqHeFltTolFanIndex},
+ cpqHeFltTolFanLocale => $params{cpqHeFltTolFanLocale},
+ cpqHeFltTolFanPresent => $params{cpqHeFltTolFanPresent},
+ cpqHeFltTolFanType => $params{cpqHeFltTolFanType},
+ cpqHeFltTolFanSpeed => $params{cpqHeFltTolFanSpeed},
+ cpqHeFltTolFanRedundant => $params{cpqHeFltTolFanRedundant},
+ cpqHeFltTolFanRedundantPartner => $params{cpqHeFltTolFanRedundantPartner},
+ cpqHeFltTolFanCondition => $params{cpqHeFltTolFanCondition},
+ cpqHeFltTolFanPctMax => $params{cpqHeFltTolFanPctMax}, #!!!
+ cpqHeFltTolFanHotPlug => $params{cpqHeFltTolFanHotPlug}, #!!!
+ partner => $params{partner},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if (($self->{cpqHeFltTolFanRedundant} eq 'redundant') &&
+ ((! defined $self->{cpqHeFltTolFanRedundantPartner}) ||
+ (! $self->{cpqHeFltTolFanRedundantPartner}))) {
+ $self->{cpqHeFltTolFanRedundant} = 'notRedundant';
+ # cpqHeFltTolFanRedundantPartner=0: partner not avail
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('f', $self->{cpqHeFltTolFanIndex});
+ $self->add_info(sprintf 'fan %d is %s, speed is %s, pctmax is %s%%, '.
+ 'location is %s, redundance is %s, partner is %s',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanPresent},
+ $self->{cpqHeFltTolFanSpeed}, $self->{cpqHeFltTolFanPctMax},
+ $self->{cpqHeFltTolFanLocale}, $self->{cpqHeFltTolFanRedundant},
+ $self->{cpqHeFltTolFanRedundantPartner});
+ $self->add_extendedinfo(sprintf 'fan_%s=%d%%',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanPctMax});
+ if ($self->{cpqHeFltTolFanPresent} eq 'present') {
+ if ($self->{cpqHeFltTolFanSpeed} eq 'high') {
+ $self->add_info(sprintf 'fan %d (%s) runs at high speed',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ $self->add_message(CRITICAL, $self->{info});
+ } elsif ($self->{cpqHeFltTolFanSpeed} ne 'normal') {
+ $self->add_info(sprintf 'fan %d (%s) needs attention',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ $self->add_message(CRITICAL, $self->{info});
+ }
+ if ($self->{cpqHeFltTolFanCondition} eq 'failed') {
+ $self->add_info(sprintf 'fan %d (%s) failed',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ $self->add_message(CRITICAL, $self->{info});
+ } elsif ($self->{cpqHeFltTolFanCondition} eq 'degraded') {
+ $self->add_info(sprintf 'fan %d (%s) degraded',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ $self->add_message(WARNING, $self->{info});
+ } elsif ($self->{cpqHeFltTolFanCondition} ne 'ok') {
+ $self->add_info(sprintf 'fan %d (%s) is not ok',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ $self->add_message(WARNING, $self->{info});
+ }
+ if ($self->{cpqHeFltTolFanRedundant} eq 'notRedundant') {
+ # sieht so aus, als waere notRedundant und partner=0 normal z.b. dl360
+ # das duerfte der fall sein, wenn nur eine cpu verbaut wurde und
+ # statt einem redundanten paar nur dummies drinstecken.
+ # "This specifies if the fan is in a redundant configuration"
+ # notRedundant heisst also sowohl nicht redundant wegen ausfall
+ # des partners als auch von haus aus nicht redundant ausgelegt
+ if ($self->{cpqHeFltTolFanRedundantPartner}) {
+ # nicht redundant, hat aber einen partner. da muss man genauer
+ # hinschauen
+ #if (my $partner = $self->{partner}) {
+ #}
+ if ($self->{overallhealth}) {
+ # da ist sogar das system der meinung, dass etwas faul ist
+ if (! $self->{runtime}->{options}->{ignore_fan_redundancy}) {
+ $self->add_info(sprintf 'fan %d (%s) is not redundant',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ $self->add_message(WARNING, $self->{info});
+ }
+ } else {
+ # das ist wohl so gewollt, dass einzelne fans eingebaut werden,
+ # obwohl redundante paerchen vorgesehen sind.
+ # scheint davon abzuhaengen, wieviele cpus geordert wurden.
+ }
+ }
+ } elsif ($self->{cpqHeFltTolFanRedundant} eq 'other') {
+ #seen on a dl320 g5p with bios from 2008.
+ # maybe redundancy is not supported at all
+ }
+ } elsif ($self->{cpqHeFltTolFanPresent} eq 'failed') { # from cli
+ $self->add_info(sprintf 'fan %d (%s) failed',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ $self->add_message(CRITICAL, $self->{info});
+ } elsif ($self->{cpqHeFltTolFanPresent} eq 'absent') {
+ $self->add_info(sprintf 'fan %d (%s) needs attention (is absent)',
+ $self->{cpqHeFltTolFanIndex}, $self->{cpqHeFltTolFanLocale});
+ # weiss nicht, ob absent auch kaputt bedeuten kann
+ # wenn nicht, dann wuerde man sich hier dumm und daemlich blacklisten
+ #$self->add_message(CRITICAL, $self->{info});
+ $self->add_message(WARNING, $self->{info}) if $self->{overallhealth};
+ }
+ if ($self->{runtime}->{options}->{perfdata}) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('fan_%s', $self->{cpqHeFltTolFanIndex}),
+ value => $self->{cpqHeFltTolFanPctMax},
+ uom => '%',
+ );
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FAN_%s]\n", $self->{cpqHeFltTolFanIndex};
+ foreach (qw(cpqHeFltTolFanChassis cpqHeFltTolFanIndex cpqHeFltTolFanLocale
+ cpqHeFltTolFanPresent cpqHeFltTolFanType cpqHeFltTolFanSpeed
+ cpqHeFltTolFanRedundant cpqHeFltTolFanRedundantPartner
+ cpqHeFltTolFanCondition cpqHeFltTolFanHotPlug)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::FanSubsystem::Fan::Thermal;
+our @ISA = qw(HP::Proliant::Component::FanSubsystem::Fan);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqHeThermalFanIndex => $params{cpqHeThermalFanIndex},
+ cpqHeThermalFanRequired => $params{cpqHeThermalFanRequired},
+ cpqHeThermalFanPresent => $params{cpqHeThermalFanPresent},
+ cpqHeThermalFanCpuFan => $params{cpqHeThermalFanCpuFan},
+ cpqHeThermalFanStatus => $params{cpqHeThermalFanStatus},
+ cpqHeThermalFanHwLocation => $params{cpqHeThermalFanHwLocation},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FAN_%s]\n", $self->{cpqHeThermalFanIndex};
+ foreach (qw(cpqHeThermalFanIndex cpqHeThermalFanRequired
+ cpqHeThermalFanPresent cpqHeThermalFanCpuFan cpqHeThermalFanStatus
+ cpqHeThermalFanHwLocation)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+package HP::Proliant::Component::FanSubsystem::CLI;
+our @ISA = qw(HP::Proliant::Component::FanSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ fans => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+# partner not available = cpqHeFltTolFanRedundantPartner=0
+# cpqHeFltTolFanTypeValue = other
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my %tmpfan = ();
+ foreach (grep(/^fans/, split(/\n/, $self->{rawdata}))) {
+ s/^fans //g;
+ if (/^#(\d+)\s+([\w#_\/\-]+)\s+(\w+)\s+(\w+)\s+(FAILED|[N\/A\d]+)%*\s+([\w\/]+)\s+(FAILED|[N\/A\d]+)\s+(\w+)/) {
+ %tmpfan = (
+ cpqHeFltTolFanIndex => $1,
+ cpqHeFltTolFanLocale => lc $2,
+ cpqHeFltTolFanPresent => lc $3,
+ cpqHeFltTolFanSpeed => lc $4,
+ cpqHeFltTolFanPctMax => lc $5, # (FAILED|[N\/A\d]+)
+ cpqHeFltTolFanRedundant => lc $6,
+ cpqHeFltTolFanRedundantPartner => lc $7, # (FAILED|[N\/A\d]+)
+ cpqHeFltTolFanHotPlug => lc $8,
+ );
+ } elsif (/^#(\d+)\s+([\w#_\/\-]+?)(Yes|No|N\/A)\s+(\w+)\s+(FAILED|[N\/A\d]+)%*\s+([\w\/]+)\s+(FAILED|[N\/A\d]+)\s+(\w+)/) {
+ # #5 SCSI_BACKPLANE_ZONEYes NORMAL N/A ....
+ %tmpfan = (
+ cpqHeFltTolFanIndex => $1,
+ cpqHeFltTolFanLocale => lc $2,
+ cpqHeFltTolFanPresent => lc $3,
+ cpqHeFltTolFanSpeed => lc $4,
+ cpqHeFltTolFanPctMax => lc $5,
+ cpqHeFltTolFanRedundant => lc $6,
+ cpqHeFltTolFanRedundantPartner => lc $7,
+ cpqHeFltTolFanHotPlug => lc $8,
+ );
+ } elsif (/^#(\d+)\s+([\w#_\/\-]+)\s+[NOno]+\s/) {
+ # Fan is not installed. #2 CPU#2 No - - No N/A -
+ } elsif (/^#(\d+)/) {
+ main::contact_author("FAN", $_);
+ }
+ if (%tmpfan) {
+ $tmpfan{runtime} = $params{runtime};
+ $tmpfan{cpqHeFltTolFanChassis} = 1; # geht aus hpasmcli nicht hervor
+ $tmpfan{cpqHeFltTolFanType} = 'other';
+ if ($tmpfan{cpqHeFltTolFanPctMax} !~ /^\d+$/) {
+ if ($tmpfan{cpqHeFltTolFanSpeed} eq 'normal') {
+ $tmpfan{cpqHeFltTolFanPctMax} = 50;
+ } elsif ($tmpfan{cpqHeFltTolFanSpeed} eq 'high') {
+ $tmpfan{cpqHeFltTolFanPctMax} = 100;
+ } else {
+ $tmpfan{cpqHeFltTolFanPctMax} = 0;
+ }
+ }
+ if($tmpfan{cpqHeFltTolFanSpeed} eq 'failed') {
+ $tmpfan{cpqHeFltTolFanCondition} = 'failed';
+ } elsif($tmpfan{cpqHeFltTolFanSpeed} eq 'n/a') {
+ $tmpfan{cpqHeFltTolFanCondition} = 'other';
+ } else {
+ $tmpfan{cpqHeFltTolFanCondition} = 'ok';
+ }
+ $tmpfan{cpqHeFltTolFanRedundant} =
+ $tmpfan{cpqHeFltTolFanRedundant} eq 'yes' ? 'redundant' :
+ $tmpfan{cpqHeFltTolFanRedundant} eq 'no' ? 'notRedundant' : 'other';
+ $tmpfan{cpqHeFltTolFanPresent} =
+ $tmpfan{cpqHeFltTolFanPresent} eq 'yes' ? 'present' :
+ $tmpfan{cpqHeFltTolFanPresent} eq 'failed' ? 'present' :
+ $tmpfan{cpqHeFltTolFanPresent} eq 'no' ? 'absent' : 'other';
+ $tmpfan{cpqHeFltTolFanHotPlug} =
+ $tmpfan{cpqHeFltTolFanHotPlug} eq 'yes' ? 'hotPluggable' :
+ $tmpfan{cpqHeFltTolFanHotPlug} eq 'no' ? 'nonHotPluggable' : 'other';
+ push(@{$self->{fans}},
+ HP::Proliant::Component::FanSubsystem::Fan->new(%tmpfan));
+ %tmpfan = ();
+ }
+ }
+}
+
+sub overall_check {
+ my $self = shift;
+ # nix. nur wegen der gleichheit mit snmp
+ return 0;
+}
+
+package HP::Proliant::Component::FanSubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::FanSubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ fans => [],
+ he_fans => [],
+ th_fans => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->overall_init(%params);
+ $self->he_init(%params);
+ $self->te_init(%params);
+ $self->unite();
+ return $self;
+}
+
+sub overall_init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $params{rawdata};
+ # overall
+ my $cpqHeThermalSystemFanStatus = '1.3.6.1.4.1.232.6.2.6.4.0';
+ my $cpqHeThermalSystemFanStatusValue = {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ };
+ my $cpqHeThermalCpuFanStatus = '1.3.6.1.4.1.232.6.2.6.5.0';
+ my $cpqHeThermalCpuFanStatusValue = {
+ 1 => 'other',
+ 2 => 'ok',
+ 4 => 'failed', # shutdown
+ };
+ $self->{sysstatus} = lc SNMP::Utils::get_object_value(
+ $snmpwalk, $cpqHeThermalSystemFanStatus,
+ $cpqHeThermalSystemFanStatusValue);
+ $self->{cpustatus} = lc SNMP::Utils::get_object_value(
+ $snmpwalk, $cpqHeThermalCpuFanStatus,
+ $cpqHeThermalCpuFanStatusValue);
+}
+
+sub te_init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $params{rawdata};
+ my $ignore_redundancy = $params{ignore_redundancy};
+ # cpqHeThermalFanTable
+ my $oids = {
+ cpqHeThermalFanEntry => '1.3.6.1.4.1.232.6.2.6.6.1',
+ cpqHeThermalFanIndex => '1.3.6.1.4.1.232.6.2.6.6.1.1',
+ cpqHeThermalFanRequired => '1.3.6.1.4.1.232.6.2.6.6.1.2',
+ cpqHeThermalFanPresent => '1.3.6.1.4.1.232.6.2.6.6.1.3',
+ cpqHeThermalFanCpuFan => '1.3.6.1.4.1.232.6.2.6.6.1.4',
+ cpqHeThermalFanStatus => '1.3.6.1.4.1.232.6.2.6.6.1.5',
+ cpqHeThermalFanHwLocation => '1.3.6.1.4.1.232.6.2.6.6.1.6',
+ cpqHeThermalFanRequiredValue => {
+ 1 => 'other',
+ 2 => 'nonRequired',
+ 3 => 'required',
+ },
+ cpqHeThermalFanPresentValue => {
+ 1 => 'other',
+ 2 => 'absent',
+ 3 => 'present',
+ },
+ cpqHeThermalFanCpuFanValue => {
+ 1 => 'other',
+ 2 => 'systemFan',
+ 3 => 'cpuFan',
+ },
+ cpqHeThermalFanStatusValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 4 => 'failed',
+ },
+ };
+ # INDEX { cpqHeThermalFanIndex }
+ foreach ($self->get_entries($oids, 'cpqHeThermalFanEntry')) {
+ next if ! $_->{cpqHeThermalFanPresent};
+ push(@{$self->{th_fans}},
+ HP::Proliant::Component::FanSubsystem::Fan->new(%{$_}));
+ }
+}
+
+sub he_init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $params{rawdata};
+ my $ignore_redundancy = $params{ignore_redundancy};
+ # cpqHeFltTolFanTable
+ my $oids = {
+ cpqHeFltTolFanEntry => '1.3.6.1.4.1.232.6.2.6.7.1',
+ cpqHeFltTolFanChassis => '1.3.6.1.4.1.232.6.2.6.7.1.1',
+ cpqHeFltTolFanIndex => '1.3.6.1.4.1.232.6.2.6.7.1.2',
+ cpqHeFltTolFanLocale => '1.3.6.1.4.1.232.6.2.6.7.1.3',
+ cpqHeFltTolFanPresent => '1.3.6.1.4.1.232.6.2.6.7.1.4',
+ cpqHeFltTolFanType => '1.3.6.1.4.1.232.6.2.6.7.1.5',
+ cpqHeFltTolFanSpeed => '1.3.6.1.4.1.232.6.2.6.7.1.6',
+ cpqHeFltTolFanRedundant => '1.3.6.1.4.1.232.6.2.6.7.1.7',
+ cpqHeFltTolFanRedundantPartner => '1.3.6.1.4.1.232.6.2.6.7.1.8',
+ cpqHeFltTolFanCondition => '1.3.6.1.4.1.232.6.2.6.7.1.9',
+ cpqHeFltTolFanHotPlug => '1.3.6.1.4.1.232.6.2.6.7.1.10',
+ cpqHeFltTolFanHwLocation => '1.3.6.1.4.1.232.6.2.6.7.1.11',
+ cpqHeFltTolFanCurrentSpeed => '1.3.6.1.4.1.232.6.2.6.7.1.12',
+ cpqHeFltTolFanLocaleValue => {
+ 1 => "other",
+ 2 => "unknown",
+ 3 => "system",
+ 4 => "systemBoard",
+ 5 => "ioBoard",
+ 6 => "cpu",
+ 7 => "memory",
+ 8 => "storage",
+ 9 => "removableMedia",
+ 10 => "powerSupply",
+ 11 => "ambient",
+ 12 => "chassis",
+ 13 => "bridgeCard",
+ },
+ cpqHeFltTolFanPresentValue => {
+ 1 => "other",
+ 2 => "absent",
+ 3 => "present",
+ },
+ cpqHeFltTolFanSpeedValue => {
+ 1 => "other",
+ 2 => "normal",
+ 3 => "high",
+ },
+ cpqHeFltTolFanRedundantValue => {
+ 1 => "other",
+ 2 => "notRedundant",
+ 3 => "redundant",
+ },
+ cpqHeFltTolFanTypeValue => {
+ 1 => "other",
+ 2 => "tachInput",
+ 3 => "spinDetect",
+ },
+ cpqHeFltTolFanConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqHeFltTolFanHotPlugValue => {
+ 1 => "other",
+ 2 => "nonHotPluggable",
+ 3 => "hotPluggable",
+ },
+ };
+ # INDEX { cpqHeFltTolFanChassis, cpqHeFltTolFanIndex }
+ foreach ($self->get_entries($oids, 'cpqHeFltTolFanEntry')) {
+ next if ! defined $_->{cpqHeFltTolFanIndex};
+ # z.b. USM65201WS hat nur solche fragmente. die werden erst gar nicht
+ # als fans akzeptiert. dafuer gibts dann die overall condition
+ # SNMPv2-SMI::enterprises.232.6.2.6.7.1.1.0.1 = INTEGER: 0
+ # SNMPv2-SMI::enterprises.232.6.2.6.7.1.1.0.2 = INTEGER: 0
+ $_->{cpqHeFltTolFanPctMax} = ($_->{cpqHeFltTolFanPresent} eq 'present') ?
+ 50 : 0;
+ push(@{$self->{he_fans}},
+ HP::Proliant::Component::FanSubsystem::Fan->new(%{$_}));
+ }
+
+}
+
+sub unite {
+ my $self = shift;
+ my $tmpfans = {};
+ foreach (@{$self->{he_fans}}) {
+ $tmpfans->{$_->{cpqHeFltTolFanIndex}} = $_;
+ }
+ foreach (@{$self->{he_fans}}) {
+ if (exists $tmpfans->{$_->{cpqHeFltTolFanRedundantPartner}}) {
+ $_->{partner} = $tmpfans->{$_->{cpqHeFltTolFanRedundantPartner}};
+ } else {
+ $_->{partner} = undef;
+ }
+ }
+ @{$self->{fans}} = @{$self->{he_fans}};
+}
+
+sub overall_check {
+ my $self = shift;
+ my $result = 0;
+ $self->blacklist('ofs', '');
+ if ($self->{sysstatus} && $self->{cpustatus}) {
+ if ($self->{sysstatus} eq 'degraded') {
+ $result = 1;
+ $self->add_message(WARNING,
+ sprintf 'system fan overall status is %s', $self->{sysstatus});
+ } elsif ($self->{sysstatus} eq 'failed') {
+ $result = 2;
+ $self->add_message(CRITICAL,
+ sprintf 'system fan overall status is %s', $self->{sysstatus});
+ }
+ if ($self->{cpustatus} eq 'degraded') {
+ $result = 1;
+ $self->add_message(WARNING,
+ sprintf 'cpu fan overall status is %s', $self->{cpustatus});
+ } elsif ($self->{cpustatus} eq 'failed') {
+ $result = 2;
+ $self->add_message(CRITICAL,
+ sprintf 'cpu fan overall status is %s', $self->{cpustatus});
+ }
+ $self->add_info(sprintf 'overall fan status: system=%s, cpu=%s',
+ $self->{sysstatus}, $self->{cpustatus});
+ } else {
+ $result = 0;
+ $self->add_info('this system seems to be water-cooled. no fans found');
+ }
+ return $result;
+}
+
+
+
+package HP::Proliant::Component::MemorySubsystem::CLI;
+our @ISA = qw(HP::Proliant::Component::MemorySubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ dimms => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ $self->{dimms} = [];
+ my %tmpdimm = (
+ runtime => $params{runtime},
+ );
+ my $inblock = 0;
+ foreach (grep(/^dimm/, split(/\n/, $self->{rawdata}))) {
+ s/^dimm\s*$//g;
+ if (/Cartridge #:\s+(\d+)/ || /Processor #:\s+(\d+)/) {
+ # neuerdings (g6) tauchen hier prozessor- statt cartridge-angaben auf
+ $tmpdimm{cartridge} = $1;
+ $tmpdimm{board} = $1;
+ $inblock = 1;
+ } elsif (/Module #:\s+(\d+)/) {
+ $tmpdimm{module} = $1;
+ } elsif (/Present:\s+(\w+)/) {
+ $tmpdimm{status} = lc $1 eq 'yes' ? 'present' :
+ lc $1 eq 'no' ? 'notPresent' : 'other';
+ } elsif (/Status:\s+(.+?)\s*$/) {
+ $tmpdimm{condition} = lc $1 =~ /degraded/ ? 'degraded' :
+ lc $1 eq 'ok' ? 'ok' : lc $1 =~ /n\/a/ ? 'n/a' : 'other';
+ } elsif (/Size:\s+(\d+)\s*(.+?)\s*$/) {
+ $tmpdimm{size} = $1 * (lc $2 eq 'mb' ? 1024*1024 :
+ lc $2 eq 'gb' ? 1024*1024*1024 : 1);
+ } elsif (/^\s*$/) {
+ if ($inblock) {
+ $inblock = 0;
+ push(@{$self->{dimms}},
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(%tmpdimm));
+ %tmpdimm = (
+ runtime => $params{runtime},
+ );
+ }
+ } elsif (/(\d+)\s+(\d+)\s+(\w+)\s+(0x\w+)\s+(0x\w+)\s+(\d+[MGT]B)\s+(\d+MHz)\s+(\w+)/) {
+ $tmpdimm{cartridge} = $1;
+ $tmpdimm{module} = $2;
+ $tmpdimm{status} = lc $3 eq 'yes' ? 'present' :
+ lc $3 eq 'no' ? 'notPresent' : 'other';
+ my $formfactor = $4;
+ my $memorytype = $5;
+ my $memorysize = $6;
+ my $memoryspeed = $7;
+ $tmpdimm{condition} = lc $8 =~ /degraded/ ? 'degraded' :
+ lc $8 eq 'ok' ? 'ok' : lc $8 =~ /n\/a/ ? 'n/a' : 'other';
+ $memorysize =~ /(\d+)([MGT]B)/;
+ $tmpdimm{size} = $1 * (lc $2 eq 'mb' ? 1024*1024 :
+ lc $2 eq 'gb' ? 1024*1024*1024 : 1);
+ push(@{$self->{dimms}},
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(%tmpdimm));
+ }
+ }
+ if ($inblock) {
+ push(@{$self->{dimms}},
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(%tmpdimm));
+ }
+}
+
+sub is_faulty {
+ my $self = shift;
+ return 0; # cli hat so einen globalen status nicht
+}
+
+
+package HP::Proliant::Component::MemorySubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::MemorySubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ dimms => [],
+ si_dimms => [],
+ he_dimms => [],
+ h2_dimms => [],
+ he_cartridges => [],
+ h2_cartridges => [],
+ si_overall_condition => undef,
+ he_overall_condition => undef,
+ h2_overall_condition => undef,
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->si_init();
+ $self->he_init();
+ $self->he_cartridge_init();
+ $self->h2_init();
+ #$self->h2_cartridge_init();
+ $self->condense();
+ return $self;
+}
+
+sub si_init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqSiMemModuleEntry => '1.3.6.1.4.1.232.2.2.4.5.1',
+ cpqSiMemBoardIndex => '1.3.6.1.4.1.232.2.2.4.5.1.1',
+ cpqSiMemModuleIndex => '1.3.6.1.4.1.232.2.2.4.5.1.2',
+ cpqSiMemModuleSize => '1.3.6.1.4.1.232.2.2.4.5.1.3',
+ cpqSiMemModuleType => '1.3.6.1.4.1.232.2.2.4.5.1.4',
+ cpqSiMemECCStatus => '1.3.6.1.4.1.232.2.2.4.5.1.11',
+ cpqSiMemModuleHwLocation => '1.3.6.1.4.1.232.2.2.4.5.1.12',
+ cpqSiMemModuleTypeValue => {
+ 1 => 'other',
+ 2 => 'board',
+ 3 => 'cpqSingleWidthModule',
+ 4 => 'cpqDoubleWidthModule',
+ 5 => 'simm',
+ 6 => 'pcmcia',
+ 7 => 'compaq-specific',
+ 8 => 'dimm',
+ 9 => 'smallOutlineDimm',
+ 10 => 'rimm',
+ 11 => 'srimm',
+ },
+ cpqSiMemECCStatusValue => {
+ 0 => "n/a",
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "degradedModuleIndexUnknown",
+ 34 => 'n/a', # es ist zum kotzen...
+ 104 => 'n/a',
+ },
+ };
+ # INDEX { cpqSiMemBoardIndex, cpqSiMemModuleIndex }
+ foreach ($self->get_entries($oids, 'cpqSiMemModuleEntry')) {
+ $_->{cartridge} = $_->{cpqSiMemBoardIndex};
+ $_->{module} = $_->{cpqSiMemModuleIndex};
+ next if (! defined $_->{cartridge} || ! defined $_->{module});
+ $_->{size} = $_->{cpqSiMemModuleSize};
+ $_->{type} = $_->{cpqSiMemModuleType};
+ $_->{condition} = $_->{cpqSiMemECCStatus};
+ $_->{status} = ($_->{cpqSiMemModuleSize} > 0) ? 'present' : 'notPresent';
+ push(@{$self->{si_dimms}},
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(%{$_})
+ );
+ }
+ my $cpqSiMemECCCondition = '1.3.6.1.4.1.232.2.2.4.15.0';
+ my $cpqSiMemECCConditionValue = {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ };
+ $self->{si_overall_condition} = SNMP::Utils::get_object_value(
+ $self->{rawdata}, $cpqSiMemECCCondition,
+ $cpqSiMemECCConditionValue);
+ $self->trace(2, sprintf 'overall si condition is %s',
+ $self->{si_overall_condition} || 'undefined');
+}
+
+sub he_init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqHeResMemModuleEntry => '1.3.6.1.4.1.232.6.2.14.11.1',
+ cpqHeResMemBoardIndex => '1.3.6.1.4.1.232.6.2.14.11.1.1',
+ cpqHeResMemModuleIndex => '1.3.6.1.4.1.232.6.2.14.11.1.2',
+ cpqHeResMemModuleStatus => '1.3.6.1.4.1.232.6.2.14.11.1.4',
+ cpqHeResMemModuleCondition => '1.3.6.1.4.1.232.6.2.14.11.1.5',
+ cpqHeResMemModuleStatusValue => {
+ 1 => "other", # unknown or could not be determined
+ 2 => "notPresent", # not present or un-initialized
+ 3 => "present", # present but not in use
+ 4 => "good", # present and in use. ecc threshold not exceeded
+ 5 => "add", # added but not yet in use
+ 6 => "upgrade", # upgraded but not yet in use
+ 7 => "missing", # expected but missing
+ 8 => "doesNotMatch", # does not match the other modules in the bank
+ 9 => "notSupported", # module not supported
+ 10 => "badConfig", # violates add/upgrade configuration
+ 11 => "degraded", # ecc exceeds threshold
+ },
+ # condition = status of the correctable memory errors
+ cpqHeResMemModuleConditionValue => {
+ 0 => "n/a", # this appears only with buggy firmwares.
+ # (only 1 module shows up)
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ },
+ };
+ my $tablesize = SNMP::Utils::get_size($snmpwalk,
+ $oids->{cpqHeResMemModuleEntry});
+ # INDEX { cpqHeResMemBoardIndex, cpqHeResMemModuleIndex }
+ foreach ($self->get_entries($oids, 'cpqHeResMemModuleEntry')) {
+ $_->{cartridge} = $_->{cpqHeResMemBoardIndex};
+ $_->{module} = $_->{cpqHeResMemModuleIndex};
+ $_->{present} = $_->{cpqHeResMemModuleStatus};
+ $_->{status} = $_->{cpqHeResMemModuleStatus};
+ $_->{condition} = $_->{cpqHeResMemModuleCondition};
+ if ((! defined $_->{module}) && ($_->{cartridge} == 0)) {
+ $_->{module} = $_->{index2}; # auf dem systemboard verbaut
+ }
+
+ push(@{$self->{he_dimms}},
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(%{$_})
+ ) unless (! defined $_->{cartridge} || ! defined $_->{module} ||
+ $tablesize == 1);
+ }
+ my $cpqHeResilientMemCondition = '1.3.6.1.4.1.232.6.2.14.4.0';
+ my $cpqHeResilientMemConditionValue = {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ };
+ $self->{he_overall_condition} = SNMP::Utils::get_object_value(
+ $self->{rawdata}, $cpqHeResilientMemCondition,
+ $cpqHeResilientMemConditionValue);
+ $self->trace(2, sprintf 'overall he condition is %s',
+ $self->{hei_overall_condition} || 'undefined');
+}
+
+sub he_cartridge_init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqHeResMemBoardEntry => '1.3.6.1.4.1.232.6.2.14.10.1',
+ cpqHeResMemBoardSlotIndex => '1.3.6.1.4.1.232.6.2.14.10.1.1',
+ cpqHeResMemBoardOnlineStatus => '1.3.6.1.4.1.232.6.2.14.10.1.2',
+ cpqHeResMemBoardErrorStatus => '1.3.6.1.4.1.232.6.2.14.10.1.3',
+ cpqHeResMemBoardNumSockets => '1.3.6.1.4.1.232.6.2.14.10.1.5',
+ cpqHeResMemBoardOsMemSize => '1.3.6.1.4.1.232.6.2.14.10.1.6',
+ cpqHeResMemBoardTotalMemSize => '1.3.6.1.4.1.232.6.2.14.10.1.7',
+ cpqHeResMemBoardCondition => '1.3.6.1.4.1.232.6.2.14.10.1.8',
+ # onlinestatus
+ cpqHeResMemBoardOnlineStatusValue => {
+ 0 => "n/a", # this appears only with buggy firmwares.
+ # (only 1 module shows up)
+ 1 => "other",
+ 2 => "present",
+ 3 => "absent",
+ },
+ cpqHeResMemBoardErrorStatusValue => {
+ 1 => "other", #
+ 2 => "noError", #
+ 3 => "dimmEccError", #
+ 4 => "unlockError", #
+ 5 => "configError", #
+ 6 => "busError", #
+ 7 => "powerError", #
+ },
+ # condition = status of the correctable memory errors
+ cpqHeResMemBoardConditionValue => {
+ 0 => "n/a", # this appears only with buggy firmwares.
+ # (only 1 module shows up)
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ },
+ };
+ my $tablesize = SNMP::Utils::get_size($snmpwalk,
+ $oids->{cpqHeResMemBoardEntry});
+ # INDEX { cpqHeResMemBoardIndex, cpqHeResMemBoardIndex }
+ foreach ($self->get_entries($oids, 'cpqHeResMemBoardEntry')) {
+ push(@{$self->{he_cartridges}},
+ HP::Proliant::Component::MemorySubsystem::Cartridge->new(%{$_})
+ ) unless (! defined $_->{cpqHeResMemBoardSlotIndex} || $tablesize == 1);
+ }
+}
+
+sub h2_init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqHeResMem2ModuleEntry => '1.3.6.1.4.1.232.6.2.14.13.1',
+ cpqHeResMem2BoardNum => '1.3.6.1.4.1.232.6.2.14.13.1.2',
+ cpqHeResMem2ModuleNum => '1.3.6.1.4.1.232.6.2.14.13.1.5',
+ cpqHeResMem2ModuleStatus => '1.3.6.1.4.1.232.6.2.14.13.1.19',
+ cpqHeResMem2ModuleCondition => '1.3.6.1.4.1.232.6.2.14.13.1.20',
+ cpqHeResMem2ModuleSize => '1.3.6.1.4.1.232.6.2.14.13.1.6',
+
+ cpqHeResMem2ModuleStatusValue => {
+ 1 => "other", # unknown or could not be determined
+ 2 => "notPresent", # not present or un-initialized
+ 3 => "present", # present but not in use
+ 4 => "good", # present and in use. ecc threshold not exceeded
+ 5 => "add", # added but not yet in use
+ 6 => "upgrade", # upgraded but not yet in use
+ 7 => "missing", # expected but missing
+ 8 => "doesNotMatch", # does not match the other modules in the bank
+ 9 => "notSupported", # module not supported
+ 10 => "badConfig", # violates add/upgrade configuration
+ 11 => "degraded", # ecc exceeds threshold
+ },
+ # condition = status of the correctable memory errors
+ cpqHeResMem2ModuleConditionValue => {
+ 0 => "n/a", # this appears only with buggy firmwares.
+ # (only 1 module shows up)
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ },
+ };
+ # INDEX { cpqHeResMem2ModuleNum }
+ my $lastboard = 0;
+ my $lastmodule = 0;
+ my $myboard= 0;
+ my $hpboard = 0;
+ foreach (sort { $a->{index1} <=> $b->{index1} }
+ $self->get_entries($oids, 'cpqHeResMem2ModuleEntry')) {
+ $hpboard = $_->{cpqHeResMem2BoardNum};
+ # dass hier faelschlicherweise 0 zurueckkommt, wundert mich schon
+ # gar nicht mehr
+ $_->{module} = $_->{cpqHeResMem2ModuleNum};
+ if ($_->{module} < $lastmodule) {
+ # sieht so aus, als haette man es mit einem neuen board zu tun
+ # da hp zu bloed ist, selber hochzuzaehlen, muss ich das tun
+ $myboard++;
+ }
+ $lastmodule = $_->{cpqHeResMem2ModuleNum};
+ $_->{cartridge} = ($myboard != $hpboard) ? $myboard : $hpboard;
+ $_->{present} = $_->{cpqHeResMem2ModuleStatus};
+ $_->{status} = $_->{cpqHeResMem2ModuleStatus};
+ $_->{condition} = $_->{cpqHeResMem2ModuleCondition};
+ $_->{size} = $_->{cpqHeResMem2ModuleSize};
+ push(@{$self->{h2_dimms}},
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(%{$_})
+ ) unless (! defined $_->{cpqHeResMem2BoardNum} ||
+ ! defined $_->{cpqHeResMem2ModuleNum});
+ }
+}
+
+sub h2_cartridge_init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqHeResMem2BoardEntry => '1.3.6.1.4.1.232.6.2.14.12.1',
+ cpqHeResMem2BoardIndex => '1.3.6.1.4.1.232.6.2.14.12.1.1',
+ cpqHeResMem2BoardOnlineStatus => '1.3.6.1.4.1.232.6.2.14.12.1.5',
+ cpqHeResMem2BoardErrorStatus => '1.3.6.1.4.1.232.6.2.14.12.1.6',
+ cpqHeResMem2BoardNumSockets => '1.3.6.1.4.1.232.6.2.14.12.1.8',
+ cpqHeResMem2BoardOsMemSize => '1.3.6.1.4.1.232.6.2.14.12.1.9',
+ cpqHeResMem2BoardTotalMemSize => '1.3.6.1.4.1.232.6.2.14.12.1.10',
+ cpqHeResMem2BoardCondition => '1.3.6.1.4.1.232.6.2.14.12.1.11',
+ # onlinestatus
+ cpqHeResMem2BoardOnlineStatusValue => {
+ 0 => "n/a", # this appears only with buggy firmwares.
+ # (only 1 module shows up)
+ 1 => "other",
+ 2 => "present",
+ 3 => "absent",
+ },
+ cpqHeResMem2BoardErrorStatusValue => {
+ 1 => "other", #
+ 2 => "noError", #
+ 3 => "dimmEccError", #
+ 4 => "unlockError", #
+ 5 => "configError", #
+ 6 => "busError", #
+ 7 => "powerError", #
+ },
+ # condition = status of the correctable memory errors
+ cpqHeResMem2BoardConditionValue => {
+ 0 => "n/a", # this appears only with buggy firmwares.
+ # (only 1 module shows up)
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ },
+ };
+ my $tablesize = SNMP::Utils::get_size($snmpwalk,
+ $oids->{cpqHeResMemBoardEntry});
+ # INDEX { cpqHeResMem2BoardIndex, cpqHeResMem2BoardIndex }
+ foreach ($self->get_entries($oids, 'cpqHeResMem2BoardEntry')) {
+ push(@{$self->{h2_cartridges}},
+ HP::Proliant::Component::MemorySubsystem::Cartridge->new(%{$_})
+ ) unless (! defined $_->{cpqHeRes2MemBoardIndex} || $tablesize == 1);
+ }
+}
+
+sub condense {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ # wenn saemtliche dimms n/a sind
+ # wenn ignore dimms: ignoring %d dimms with status 'n/a'
+ # wenn buggyfirmware: ignoring %d dimms with status 'n/a' because of buggy firmware
+ # if buggy firmware : condition n/a ist normal
+ # ignore-dimms :
+ # es gibt si_dimms und he_dimms
+ my $si_dimms = scalar(@{$self->{si_dimms}});
+ my $he_dimms = scalar(@{$self->{he_dimms}});
+ my $h2_dimms = scalar(@{$self->{h2_dimms}});
+ $self->trace(2, sprintf "SI: %02d HE: %02d H2: %02d",
+ $si_dimms, $he_dimms, $h2_dimms)
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ foreach ($self->get_si_boards()) {
+ printf "SI%02d-> ", $_ if ($self->{runtime}->{options}->{verbose} >= 2);
+ foreach ($self->get_si_modules($_)) {
+ printf "%02d ", $_ if ($self->{runtime}->{options}->{verbose} >= 2);
+ }
+ printf "\n" if ($self->{runtime}->{options}->{verbose} >= 2);
+ }
+ foreach ($self->get_he_boards()) {
+ printf "HE%02d-> ", $_ if ($self->{runtime}->{options}->{verbose} >= 2);
+ foreach ($self->get_he_modules($_)) {
+ printf "%02d ", $_ if ($self->{runtime}->{options}->{verbose} >= 2);
+ }
+ printf "\n" if ($self->{runtime}->{options}->{verbose} >= 2);
+ }
+ foreach ($self->get_h2_boards()) {
+ printf "H2%02d-> ", $_ if ($self->{runtime}->{options}->{verbose} >= 2);
+ foreach ($self->get_h2_modules($_)) {
+ printf "%02d ", $_ if ($self->{runtime}->{options}->{verbose} >= 2);
+ }
+ printf "\n" if ($self->{runtime}->{options}->{verbose} >= 2);
+ }
+ if (($h2_dimms == 0) && ($he_dimms == 0) && ($si_dimms > 0)) {
+ printf "TYP1 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_si_with_si();
+ } elsif (($h2_dimms == 0) && ($he_dimms > 0) && ($si_dimms > 0)) {
+ printf "TYP2 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_si_with_he();
+ } elsif (($h2_dimms == 0) && ($he_dimms > 0) && ($si_dimms == 0)) {
+ printf "TYP3 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_he_with_he();
+ } elsif (($h2_dimms > 0) && ($he_dimms == 0) && ($si_dimms == 0)) {
+ printf "TYP4 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_h2_with_h2();
+ } elsif (($h2_dimms > 0) && ($he_dimms > 0) && ($si_dimms == 0)) {
+ printf "TYP5 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_he_with_h2();
+ } elsif (($h2_dimms > 0) && ($he_dimms == 0) && ($si_dimms > 0)) {
+ printf "TYP6 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_si_with_h2();
+ } elsif (($h2_dimms > 0) && ($he_dimms > 0) && ($si_dimms > 0)) {
+ if ($h2_dimms > $si_dimms) {
+ printf "TYP7 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_he_with_h2();
+ } else {
+ printf "TYP8 %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ @{$self->{dimms}} = $self->update_si_with_he();
+ }
+ } else {
+ printf "TYPX %s\n", $self->{runtime}->{product}
+ if ($self->{runtime}->{options}->{verbose} >= 2);
+ }
+ my $all_dimms = scalar(@{$self->{dimms}});
+ $self->trace(2, sprintf "ALL: %02d", $all_dimms);
+}
+
+sub dump {
+ my $self = shift;
+ if ($self->{runtime}->{options}->{verbose} > 2) {
+ printf "[SI]\n";
+ foreach (@{$self->{si_dimms}}) {
+ $_->dump();
+ }
+ printf "[HE]\n";
+ foreach (@{$self->{he_dimms}}) {
+ $_->dump();
+ }
+ printf "[H2]\n";
+ foreach (@{$self->{h2_dimms}}) {
+ $_->dump();
+ }
+ }
+ $self->SUPER::dump();
+}
+
+sub update_si_with_si {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my @dimms = ();
+ my $repaircondition = undef;
+ # wenn si keine statusinformationen liefert, dann besteht die chance
+ # dass ein undokumentiertes he-fragment vorliegt
+ # 1.3.6.1.4.1.232.6.2.14.11.1.1.0.<anzahl der dimms>
+ my $cpqHeResMemModuleEntry = "1.3.6.1.4.1.232.6.2.14.11.1";
+ if (SNMP::Utils::get_size($snmpwalk, $cpqHeResMemModuleEntry) == 1) {
+ $repaircondition = lc SNMP::Utils::get_object(
+ $snmpwalk, $cpqHeResMemModuleEntry.'.1.0.'.scalar(@{$self->{si_dimms}}));
+ # repaircondition 0 (ok) biegt alles wieder gerade
+ } else {
+ # anderer versuch
+ if ($self->{si_overall_condition} &&
+ $self->{si_overall_condition} eq 'ok') {
+ $repaircondition = 0;
+ }
+ }
+ foreach my $si_dimm (@{$self->{si_dimms}}) {
+ if (($si_dimm->{condition} eq 'n/a') ||
+ ($si_dimm->{condition} eq 'other')) {
+ $si_dimm->{condition} = 'ok' if
+ (defined $repaircondition && $repaircondition == 0);
+ }
+ push(@dimms,
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(
+ runtime => $si_dimm->{runtime},
+ cartridge => $si_dimm->{cartridge},
+ module => $si_dimm->{module},
+ size => $si_dimm->{size},
+ status => $si_dimm->{status},
+ condition => $si_dimm->{condition},
+ ));
+ }
+ return @dimms;
+}
+
+sub update_si_with_he {
+ my $self = shift;
+ my @dimms = ();
+ my $first_si_cartridge = ($self->get_si_boards())[0];
+ my $first_he_cartridge = ($self->get_he_boards())[0];
+ my $offset = 0;
+ if (scalar(@{$self->{si_dimms}}) == scalar(@{$self->{he_dimms}})) {
+ # aufpassen! sowas kann vorkommen: si cartridge 0...6, he cartridge 1...7
+ if ($first_si_cartridge != $first_he_cartridge) {
+ # README case 5
+ $offset = $first_si_cartridge - $first_he_cartridge;
+ }
+ } elsif ((scalar(@{$self->{si_dimms}}) > 1) &&
+ (scalar(@{$self->{he_dimms}}) == 1)) {
+ # siehe update_si_with_si. he-fragment
+ return $self->update_si_with_si();
+ } else {
+ # z.b. 4 si notpresent, 4 si present, 4 he
+ }
+ foreach my $si_dimm (@{$self->{si_dimms}}) {
+ if (($si_dimm->{condition} eq 'n/a') ||
+ ($si_dimm->{condition} eq 'other')) {
+ if (my $he_dimm = $self->get_he_module(
+ $si_dimm->{cartridge} - $offset, $si_dimm->{module})) {
+ # vielleicht hat he mehr ahnung
+ $si_dimm->{condition} = $he_dimm->{condition};
+ if (($si_dimm->{condition} eq 'n/a') ||
+ ($si_dimm->{condition} eq 'other')) {
+ # wenns immer noch kein brauchbares ergebnis gibt....
+ if ($self->{he_overall_condition} &&
+ $self->{he_overall_condition} eq 'ok') {
+ # wird schon stimmen...
+ $si_dimm->{condition} = 'ok';
+ } else {
+ # ansonsten stellen wir uns dumm
+ $si_dimm->{status} = 'notPresent';
+ }
+ }
+ } else {
+ # in dem fall zeigt si unbestueckte cartridges an
+ }
+ }
+ push(@dimms,
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(
+ runtime => $si_dimm->{runtime},
+ cartridge => $si_dimm->{cartridge},
+ module => $si_dimm->{module},
+ size => $si_dimm->{size},
+ status => $si_dimm->{status},
+ condition => $si_dimm->{condition},
+ ));
+ }
+ return @dimms;
+}
+
+sub update_he_with_he {
+ my $self = shift;
+ my @dimms = ();
+ foreach my $he_dimm (@{$self->{he_dimms}}) {
+ push(@dimms,
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(
+ runtime => $he_dimm->{runtime},
+ cartridge => $he_dimm->{cartridge},
+ module => $he_dimm->{module},
+ size => $he_dimm->{size},
+ status => $he_dimm->{status},
+ condition => $he_dimm->{condition},
+ ));
+ }
+ return @dimms;
+}
+
+sub update_si_with_h2 {
+ my $self = shift;
+ my @dimms = ();
+ my $first_si_cartridge = ($self->get_si_boards())[0];
+ my $first_h2_cartridge = ($self->get_h2_boards())[0];
+ my $offset = 0;
+ if (scalar(@{$self->{si_dimms}}) == scalar(@{$self->{h2_dimms}})) {
+ # aufpassen! sowas kann vorkommen: si cartridge 0...6, he cartridge 1...7
+ if ($first_si_cartridge != $first_h2_cartridge) {
+ # README case 5
+ $offset = $first_si_cartridge - $first_h2_cartridge;
+ }
+ } else {
+ # z.b. 4 si notpresent, 4 si present, 4 he
+ }
+ foreach my $si_dimm (@{$self->{si_dimms}}) {
+ if (($si_dimm->{condition} eq 'n/a') ||
+ ($si_dimm->{condition} eq 'other')) {
+ if (my $h2_dimm = $self->get_h2_module(
+ $si_dimm->{cartridge} - $offset, $si_dimm->{module})) {
+ # vielleicht hat h2 mehr ahnung
+ $si_dimm->{condition} = $h2_dimm->{condition};
+ if (1) {
+ # ist zwar da, aber irgendwie auskonfiguriert
+ $si_dimm->{status} = 'notPresent' if $h2_dimm->{status} eq 'other';
+ }
+ } else {
+ # in dem fall zeigt si unbestueckte cartridges an
+ }
+ }
+ push(@dimms,
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(
+ runtime => $si_dimm->{runtime},
+ cartridge => $si_dimm->{cartridge},
+ module => $si_dimm->{module},
+ size => $si_dimm->{size},
+ status => $si_dimm->{status},
+ condition => $si_dimm->{condition},
+ ));
+ }
+ return @dimms;
+}
+
+sub update_he_with_h2 {
+ my $self = shift;
+ my @dimms = ();
+ my $first_he_cartridge = ($self->get_he_boards())[0];
+ my $first_h2_cartridge = ($self->get_h2_boards())[0];
+ my $offset = 0;
+ # auch hier koennte sowas u.u.vorkommen: he cartridge 0..6, h2 cartridge 1..7
+ # ich habs zwar nie gesehen, aber wer weiss...
+ if ($first_h2_cartridge != $first_he_cartridge) {
+ $offset = $first_h2_cartridge - $first_he_cartridge;
+ }
+ foreach my $he_dimm (@{$self->{he_dimms}}) {
+ if (($he_dimm->{condition} eq 'n/a') ||
+ ($he_dimm->{condition} eq 'other')) {
+ if (my $h2_dimm = $self->get_h2_module(
+ $he_dimm->{cartridge} + $offset, $he_dimm->{module})) {
+ # vielleicht hat h2 mehr ahnung
+ $he_dimm->{condition} = $h2_dimm->{condition};
+ if (1) {
+ # ist zwar da, aber irgendwie auskonfiguriert
+ $he_dimm->{status} = 'notPresent' if $h2_dimm->{status} eq 'other';
+ }
+ } else {
+ # in dem fall weiss he mehr als h2
+ }
+ }
+ if ($he_dimm->{size} == 0) {
+ if (my $h2_dimm = $self->get_h2_module(
+ $he_dimm->{cartridge} + $offset, $he_dimm->{module})) {
+ $he_dimm->{size} = $h2_dimm->{size};
+ # h2 beinhaltet eine size-oid
+ }
+ }
+ push(@dimms,
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(
+ runtime => $he_dimm->{runtime},
+ cartridge => $he_dimm->{cartridge},
+ module => $he_dimm->{module},
+ size => $he_dimm->{size},
+ status => $he_dimm->{status},
+ condition => $he_dimm->{condition},
+ ));
+ }
+ return @dimms;
+}
+
+sub update_h2_with_h2 {
+ my $self = shift;
+ my @dimms = ();
+ foreach my $h2_dimm (@{$self->{h2_dimms}}) {
+ push(@dimms,
+ HP::Proliant::Component::MemorySubsystem::Dimm->new(
+ runtime => $h2_dimm->{runtime},
+ cartridge => $h2_dimm->{cartridge},
+ module => $h2_dimm->{module},
+ size => $h2_dimm->{size},
+ status => $h2_dimm->{status},
+ condition => $h2_dimm->{condition},
+ ));
+ }
+ return @dimms;
+}
+
+sub is_faulty {
+ my $self = shift;
+ if (scalar(@{$self->{si_dimms}}) > 0 &&
+ scalar(@{$self->{he_dimms}}) > 0) {
+ return $self->si_is_faulty() || $self->he_is_faulty();
+ } elsif (scalar(@{$self->{si_dimms}}) > 0 &&
+ scalar(@{$self->{he_dimms}}) == 0) {
+ return $self->si_is_faulty();
+ } elsif (scalar(@{$self->{si_dimms}}) == 0 &&
+ scalar(@{$self->{he_dimms}}) > 0) {
+ return $self->he_is_faulty();
+ } else {
+ return 0;
+ }
+}
+
+sub si_is_faulty {
+ my $self = shift;
+ return ! defined $self->{si_overall_condition} ? 0 :
+ $self->{si_overall_condition} eq 'degraded' ? 1 : 0;
+}
+
+sub si_is_ok {
+ my $self = shift;
+ return ! defined $self->{si_overall_condition} ? 1 :
+ $self->{si_overall_condition} eq 'ok' ? 1 : 0;
+}
+
+sub he_is_faulty {
+ my $self = shift;
+ return ! defined $self->{he_overall_condition} ? 0 :
+ $self->{he_overall_condition} eq 'degraded' ? 1 : 0;
+}
+
+sub he_is_ok {
+ my $self = shift;
+ return ! defined $self->{he_overall_condition} ? 1 :
+ $self->{he_overall_condition} eq 'ok' ? 1 : 0;
+}
+
+sub get_si_boards {
+ my $self = shift;
+ my %found = ();
+ foreach (@{$self->{si_dimms}}) {
+ $found{$_->{cartridge}} = 1;
+ }
+ return sort { $a <=> $b } keys %found;
+}
+
+sub get_si_modules {
+ my $self = shift;
+ my $board = shift;
+ my %found = ();
+ foreach (grep { $_->{cartridge} == $board } @{$self->{si_dimms}}) {
+ $found{$_->{module}} = 1;
+ }
+ return sort { $a <=> $b } keys %found;
+}
+
+sub get_he_boards {
+ my $self = shift;
+ my %found = ();
+ foreach (@{$self->{he_dimms}}) {
+ $found{$_->{cartridge}} = 1;
+ }
+ return sort { $a <=> $b } keys %found;
+}
+
+sub get_he_modules {
+ my $self = shift;
+ my $board = shift;
+ my %found = ();
+ foreach (grep { $_->{cartridge} == $board } @{$self->{he_dimms}}) {
+ $found{$_->{module}} = 1;
+ }
+ return sort { $a <=> $b } keys %found;
+}
+
+sub get_he_module {
+ my $self = shift;
+ my $board = shift;
+ my $module = shift;
+ my $found = (grep { $_->{cartridge} == $board && $_->{module} == $module }
+ @{$self->{he_dimms}})[0];
+ return $found;
+}
+
+sub get_h2_boards {
+ my $self = shift;
+ my %found = ();
+ #
+ foreach (@{$self->{h2_dimms}}) {
+ $found{$_->{cartridge}} = 1;
+ }
+ return sort { $a <=> $b } keys %found;
+}
+
+sub get_h2_modules {
+ my $self = shift;
+ my $board = shift;
+ my %found = ();
+ foreach (grep { $_->{cartridge} == $board } @{$self->{h2_dimms}}) {
+ $found{$_->{module}} = 1;
+ }
+ return sort { $a <=> $b } keys %found;
+}
+
+sub get_h2_module {
+ my $self = shift;
+ my $board = shift;
+ my $module = shift;
+ my $found = (grep { $_->{cartridge} == $board && $_->{module} == $module }
+ @{$self->{h2_dimms}})[0];
+ return $found;
+}
+
+
+package HP::Proliant::Component::MemorySubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ dimms => [],
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ return HP::Proliant::Component::MemorySubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ return HP::Proliant::Component::MemorySubsystem::CLI->new(%params);
+ } else {
+ die "unknown method";
+ }
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking memory');
+ foreach (@{$self->{dimms}}) {
+ $_->check(); # info ausfuellen
+ }
+ if ((scalar(grep {
+ $_->is_present() &&
+ ($_->{condition} ne 'n/a' && $_->{condition} ne 'other' )
+ } @{$self->{dimms}})) != 0) {
+ foreach (@{$self->{dimms}}) {
+ if (($_->is_present()) && ($_->{condition} ne 'ok')) {
+ $_->add_message(CRITICAL, $_->{info});
+ $errorfound++;
+ }
+ }
+ } else {
+ if ($self->{runtime}->{options}->{ignore_dimms}) {
+ $self->add_message(OK,
+ sprintf "ignoring %d dimms with status 'n/a' ",
+ scalar(grep { ($_->is_present()) } @{$self->{dimms}}));
+ } elsif ($self->{runtime}->{options}->{buggy_firmware}) {
+ $self->add_message(OK,
+ sprintf "ignoring %d dimms with status 'n/a' because of buggy firmware",
+ scalar(grep { ($_->is_present()) } @{$self->{dimms}}));
+ } else {
+ $self->add_message(WARNING,
+ sprintf "status of all %d dimms is n/a (please upgrade firmware)",
+ scalar(grep { $_->is_present() } @{$self->{dimms}}));
+ $errorfound++;
+ }
+ }
+ foreach (@{$self->{dimms}}) {
+ printf "%s\n", $_->{info} if $self->{runtime}->{options}->{verbose} >= 2;
+ }
+ if (! $errorfound && $self->is_faulty()) {
+ #if ($self->is_faulty()) {
+ $self->add_message(WARNING,
+ sprintf 'overall memory error found');
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "i dump the memory\n";
+ foreach (@{$self->{dimms}}) {
+ $_->dump();
+ }
+}
+
+package HP::Proliant::Component::MemorySubsystem::Dimm;
+our @ISA = qw(HP::Proliant::Component::MemorySubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cartridge => $params{cartridge},
+ module => $params{module},
+ size => $params{size} || 0,
+ status => $params{status},
+ condition => $params{condition},
+ type => $params{type},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->{name} = sprintf '%s:%s',
+ $self->{cartridge}, $self->{module};
+ $self->{location} = sprintf 'module %s @ cartridge %s',
+ $self->{module}, $self->{cartridge};
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ # check dient nur dazu, info und extended_info zu füllen
+ # die eigentliche bewertung findet eins höher statt
+ $self->blacklist('d', $self->{name});
+ if (($self->{status} eq 'present') || ($self->{status} eq 'good')) {
+ if ($self->{condition} eq 'other') {
+ $self->add_info(sprintf 'dimm %s (%s) is n/a',
+ $self->{name}, $self->{location});
+ } elsif ($self->{condition} ne 'ok') {
+ $self->add_info(
+ sprintf "dimm module %s (%s) needs attention (%s)",
+ $self->{name}, $self->{location}, $self->{condition});
+ } else {
+ $self->add_info(sprintf 'dimm module %s (%s) is %s',
+ $self->{name}, $self->{location}, $self->{condition});
+ }
+ } elsif ($self->{status} eq 'notPresent') {
+ $self->add_info(sprintf 'dimm module %s (%s) is not present',
+ $self->{name}, $self->{location});
+ } else {
+ $self->add_info(
+ sprintf "dimm module %s (%s) needs attention (%s)",
+ $self->{name}, $self->{location}, $self->{condition});
+ }
+}
+
+sub is_present {
+ my $self = shift;
+ my @signs_of_presence = (qw(present good add upgraded doesnotmatch
+ notsupported badconfig degraded));
+ return scalar(grep { $self->{status} eq $_ } @signs_of_presence);
+}
+
+
+sub dump {
+ my $self = shift;
+ #printf "[DIMM_%s_%s]\n", $self->{cartridge}, $self->{module};
+ #foreach (qw(cartridge module size status condition info)) {
+ # printf "%s: %s\n", $_, $self->{$_};
+ #}
+ #printf "status: %s\n", $self->{status} if exists $self->{status};
+ #printf "\n";
+ printf "car %02d mod %02d siz %.0f sta %-12s con %-10s typ %s\n",
+ $self->{cartridge}, $self->{module}, $self->{size},
+ $self->{status}, $self->{condition}, defined $self->{type} ? $self->{type} : "";
+}
+
+
+package HP::Proliant::Component::MemorySubsystem::Cartridge;
+our @ISA = qw(HP::Proliant::Component::MemorySubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ cpqHeResMemBoardSlotIndex => $params{cpqHeResMemBoardSlotIndex},
+ cpqHeResMemBoardOnlineStatus => $params{cpqHeResMemBoardOnlineStatus},
+ cpqHeResMemBoardErrorStatus => $params{cpqHeResMemBoardErrorStatus},
+ cpqHeResMemBoardNumSockets => $params{cpqHeResMemBoardNumSockets},
+ cpqHeResMemBoardOsMemSize => $params{cpqHeResMemBoardOsMemSize},
+ cpqHeResMemBoardTotalMemSize => $params{cpqHeResMemBoardTotalMemSize},
+ cpqHeResMemBoardCondition => $params{cpqHeResMemBoardCondition},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub dump {
+ my $self = shift;
+ #printf "[CARTRIDGE_%s_%s]\n", $self->{cpqHeResMemBoardSlotIndex};
+ #foreach (qw(cpqHeResMemBoardSlotIndex cpqHeResMemBoardOnlineStatus
+ # cpqHeResMemBoardErrorStatus cpqHeResMemBoardNumSockets
+ # cpqHeResMemBoardOsMemSize cpqHeResMemBoardTotalMemSize
+ # cpqHeResMemBoardCondition)) {
+ # printf "%s: %s\n", $_, $self->{$_};
+ #}
+ #printf "\n";
+}
+
+
+package HP::Proliant::Component::NicSubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::NicSubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ logical_nics => [],
+ physical_nics => [],
+ };
+ bless $self, $class;
+ $self->overall_init();
+ $self->init();
+ return $self;
+}
+
+sub overall_init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $params{rawdata};
+ # overall
+ my $cpqNicIfLogMapOverallCondition = '1.3.6.1.4.1.232.18.2.2.2.0';
+ my $cpqNicIfLogMapOverallConditionValue = {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ };
+ $self->{lognicstatus} = lc SNMP::Utils::get_object_value(
+ $snmpwalk, $cpqNicIfLogMapOverallCondition,
+ $cpqNicIfLogMapOverallConditionValue);
+}
+
+sub init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my $ifconnect = {};
+ # CPQNIC-MIB
+ my $oids = {
+ cpqNicIfLogMapEntry => '1.3.6.1.4.1.232.18.2.2.1.1',
+ cpqNicIfLogMapIndex => '1.3.6.1.4.1.232.18.2.2.1.1.1',
+ cpqNicIfLogMapIfNumber => '1.3.6.1.4.1.232.18.2.2.1.1.2',
+ cpqNicIfLogMapDescription => '1.3.6.1.4.1.232.18.2.2.1.1.3',
+ cpqNicIfLogMapGroupType => '1.3.6.1.4.1.232.18.2.2.1.1.4',
+ cpqNicIfLogMapAdapterCount => '1.3.6.1.4.1.232.18.2.2.1.1.5',
+ cpqNicIfLogMapAdapterOKCount => '1.3.6.1.4.1.232.18.2.2.1.1.6',
+ cpqNicIfLogMapPhysicalAdapters => '1.3.6.1.4.1.232.18.2.2.1.1.7',
+ cpqNicIfLogMapMACAddress => '1.3.6.1.4.1.232.18.2.2.1.1.8',
+ cpqNicIfLogMapSwitchoverMode => '1.3.6.1.4.1.232.18.2.2.1.1.9',
+ cpqNicIfLogMapCondition => '1.3.6.1.4.1.232.18.2.2.1.1.10',
+ cpqNicIfLogMapStatus => '1.3.6.1.4.1.232.18.2.2.1.1.11',
+ cpqNicIfLogMapNumSwitchovers => '1.3.6.1.4.1.232.18.2.2.1.1.12',
+ cpqNicIfLogMapHwLocation => '1.3.6.1.4.1.232.18.2.2.1.1.13',
+ cpqNicIfLogMapSpeed => '1.3.6.1.4.1.232.18.2.2.1.1.14',
+ cpqNicIfLogMapVlanCount => '1.3.6.1.4.1.232.18.2.2.1.1.15',
+ cpqNicIfLogMapVlans => '1.3.6.1.4.1.232.18.2.2.1.1.16',
+
+ cpqNicIfLogMapGroupTypeValue => {
+ 1 => "unknown",
+ 2 => "none",
+ 3 => "redundantPair",
+ 4 => "nft",
+ 5 => "alb",
+ 6 => "fec",
+ 7 => "gec",
+ 8 => "ad",
+ 9 => "slb",
+ 10 => "tlb",
+ 11 => "redundancySet",
+ },
+ cpqNicIfLogMapConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqNicIfLogMapStatusValue => {
+ 1 => "unknown",
+ 2 => "ok",
+ 3 => "primaryFailed",
+ 4 => "standbyFailed",
+ 5 => "groupFailed",
+ 6 => "redundancyReduced",
+ 7 => "redundancyLost",
+ },
+ cpqNicIfLogMapSwitchoverModeValue => {
+ 1 => "unknown",
+ 2 => "none",
+ 3 => "manual",
+ 4 => "switchOnFail",
+ 5 => "preferredPrimary",
+ },
+ };
+
+ # INDEX { cpqNicIfLogMapIndex }
+ foreach ($self->get_entries($oids, 'cpqNicIfLogMapEntry')) {
+ push(@{$self->{logical_nics}},
+ HP::Proliant::Component::NicSubsystem::LogicalNic->new(%{$_})
+ );
+ }
+
+ $oids = {
+ cpqNicIfPhysAdapterEntry => '1.3.6.1.4.1.232.18.2.3.1.1',
+ cpqNicIfPhysAdapterIndex => '1.3.6.1.4.1.232.18.2.3.1.1.1',
+ cpqNicIfPhysAdapterIfNumber => '1.3.6.1.4.1.232.18.2.3.1.1.2',
+ cpqNicIfPhysAdapterRole => '1.3.6.1.4.1.232.18.2.3.1.1.3',
+ cpqNicIfPhysAdapterMACAddress => '1.3.6.1.4.1.232.18.2.3.1.1.4',
+ cpqNicIfPhysAdapterSlot => '1.3.6.1.4.1.232.18.2.3.1.1.5',
+ cpqNicIfPhysAdapterIoAddr => '1.3.6.1.4.1.232.18.2.3.1.1.6',
+ cpqNicIfPhysAdapterIrq => '1.3.6.1.4.1.232.18.2.3.1.1.7',
+ cpqNicIfPhysAdapterDma => '1.3.6.1.4.1.232.18.2.3.1.1.8',
+ cpqNicIfPhysAdapterMemAddr => '1.3.6.1.4.1.232.18.2.3.1.1.9',
+ cpqNicIfPhysAdapterPort => '1.3.6.1.4.1.232.18.2.3.1.1.10',
+ cpqNicIfPhysAdapterDuplexState => '1.3.6.1.4.1.232.18.2.3.1.1.11',
+ cpqNicIfPhysAdapterCondition => '1.3.6.1.4.1.232.18.2.3.1.1.12',
+ cpqNicIfPhysAdapterState => '1.3.6.1.4.1.232.18.2.3.1.1.13',
+ cpqNicIfPhysAdapterStatus => '1.3.6.1.4.1.232.18.2.3.1.1.14',
+ cpqNicIfPhysAdapterStatsValid => '1.3.6.1.4.1.232.18.2.3.1.1.15',
+ cpqNicIfPhysAdapterGoodTransmits => '1.3.6.1.4.1.232.18.2.3.1.1.16',
+ cpqNicIfPhysAdapterGoodReceives => '1.3.6.1.4.1.232.18.2.3.1.1.17',
+ cpqNicIfPhysAdapterBadTransmits => '1.3.6.1.4.1.232.18.2.3.1.1.18',
+ cpqNicIfPhysAdapterBadReceives => '1.3.6.1.4.1.232.18.2.3.1.1.19',
+ cpqNicIfPhysAdapterAlignmentErrors => '1.3.6.1.4.1.232.18.2.3.1.1.20',
+ cpqNicIfPhysAdapterFCSErrors => '1.3.6.1.4.1.232.18.2.3.1.1.21',
+ cpqNicIfPhysAdapterSingleCollisionFrames => '1.3.6.1.4.1.232.18.2.3.1.1.22',
+ cpqNicIfPhysAdapterMultipleCollisionFrames => '1.3.6.1.4.1.232.18.2.3.1.1.23',
+ cpqNicIfPhysAdapterDeferredTransmissions => '1.3.6.1.4.1.232.18.2.3.1.1.24',
+ cpqNicIfPhysAdapterLateCollisions => '1.3.6.1.4.1.232.18.2.3.1.1.25',
+ cpqNicIfPhysAdapterExcessiveCollisions => '1.3.6.1.4.1.232.18.2.3.1.1.26',
+ cpqNicIfPhysAdapterInternalMacTransmitErrors => '1.3.6.1.4.1.232.18.2.3.1.1.27',
+ cpqNicIfPhysAdapterCarrierSenseErrors => '1.3.6.1.4.1.232.18.2.3.1.1.28',
+ cpqNicIfPhysAdapterFrameTooLongs => '1.3.6.1.4.1.232.18.2.3.1.1.29',
+ cpqNicIfPhysAdapterInternalMacReceiveErrors => '1.3.6.1.4.1.232.18.2.3.1.1.30',
+ cpqNicIfPhysAdapterHwLocation => '1.3.6.1.4.1.232.18.2.3.1.1.31',
+ cpqNicIfPhysAdapterPartNumber => '1.3.6.1.4.1.232.18.2.3.1.1.32',
+ cpqNicIfPhysAdapterRoleValue => {
+ 1 => "unknown",
+ 2 => "primary",
+ 3 => "secondary",
+ 4 => "member",
+ 5 => "txRx",
+ 6 => "tx",
+ 7 => "standby",
+ 8 => "none",
+ 255 => "notApplicable",
+ },
+ cpqNicIfPhysAdapterDuplexStateValue => {
+ 1 => "unknown",
+ 2 => "half",
+ 3 => "full",
+ },
+ cpqNicIfPhysAdapterConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqNicIfPhysAdapterStateValue => {
+ 1 => "unknown",
+ 2 => "ok",
+ 3 => "standby",
+ 4 => "failed",
+ },
+ cpqNicIfPhysAdapterStatusValue => {
+ 1 => "unknown",
+ 2 => "ok",
+ 3 => "generalFailure",
+ 4 => "linkFailure",
+ },
+
+ };
+ # INDEX { cpqNicIfPhysAdapterIndex }
+ foreach ($self->get_entries($oids, 'cpqNicIfPhysAdapterEntry')) {
+ push(@{$self->{physical_nics}},
+ HP::Proliant::Component::NicSubsystem::PhysicalNic->new(%{$_}));
+ }
+
+}
+
+
+package HP::Proliant::Component::NicSubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ logical_nics => [],
+ physical_nics => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ return HP::Proliant::Component::NicSubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ return HP::Proliant::Component::NicSubsystem::CLI->new(%params);
+ } else {
+ die "unknown method";
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking nic teams');
+ if (scalar (@{$self->{logical_nics}}) == 0) {
+ $self->add_info('no logical nics found');
+ $self->overall_check();
+ } else {
+ foreach (@{$self->{logical_nics}}) {
+ $_->check();
+ }
+ }
+ if (scalar (@{$self->{physical_nics}}) == 0) {
+ $self->add_info('no physical nics found. do you connect with slip?');
+ } else {
+ foreach (@{$self->{physical_nics}}) {
+ $_->check();
+ }
+ }
+}
+
+sub num_logical_nics {
+ my $self = shift;
+ return scalar @{$self->{logical_nics}};
+}
+
+sub num_physical_nics {
+ my $self = shift;
+ return scalar @{$self->{physical_nics}};
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{logical_nics}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{physical_nics}}) {
+ $_->dump();
+ }
+}
+
+sub overall_check {
+ my $self = shift;
+ if ($self->{lognicstatus} ne "ok") {
+ $self->add_info(sprintf 'overall logical nic status is %s',
+ $self->{lognicstatus});
+ }
+}
+
+
+package HP::Proliant::Component::NicSubsystem::LogicalNic;
+our @ISA = qw(HP::Proliant::Component::NicSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ foreach (qw(cpqNicIfLogMapIndex cpqNicIfLogMapIfNumber cpqNicIfLogMapDescription cpqNicIfLogMapGroupType cpqNicIfLogMapAdapterCount cpqNicIfLogMapAdapterOKCount cpqNicIfLogMapPhysicalAdapters cpqNicIfLogMapSwitchoverMode cpqNicIfLogMapCondition cpqNicIfLogMapStatus cpqNicIfLogMapNumSwitchovers cpqNicIfLogMapHwLocation cpqNicIfLogMapSpeed cpqNicIfLogMapVlanCount cpqNicIfLogMapVlans)) {
+ $self->{$_} = $params{$_};
+ }
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('lni', $self->{cpqNicIfLogMapIndex});
+ if ($self->{cpqNicIfLogMapAdapterCount} > 0) {
+ if ($self->{cpqNicIfLogMapCondition} eq "other") {
+ # simply ignore this. if there is a physical nic
+ # it is usually unknown/other/scheissegal
+ $self->add_info(sprintf "logical nic %d (%s) is %s",
+ $self->{cpqNicIfLogMapIndex}, $self->{cpqNicIfLogMapDescription},
+ $self->{cpqNicIfLogMapCondition});
+ } elsif ($self->{cpqNicIfLogMapCondition} ne "ok") {
+ $self->add_info(sprintf "logical nic %d (%s) is %s (%s)",
+ $self->{cpqNicIfLogMapIndex}, $self->{cpqNicIfLogMapDescription},
+ $self->{cpqNicIfLogMapCondition}, $self->{cpqNicIfLogMapStatus});
+ $self->add_message(CRITICAL, $self->{info});
+ } else {
+ $self->add_info(sprintf "logical nic %d (%s) is %s",
+ $self->{cpqNicIfLogMapIndex}, $self->{cpqNicIfLogMapDescription},
+ $self->{cpqNicIfLogMapCondition});
+ }
+ } else {
+ $self->add_info(sprintf "logical nic %d (%s) has 0 physical nics",
+ $self->{cpqNicIfLogMapIndex}, $self->{cpqNicIfLogMapDescription});
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[LNIC_%s]\n", $self->{cpqNicIfLogMapIndex};
+ foreach (qw(cpqNicIfLogMapIndex cpqNicIfLogMapIfNumber cpqNicIfLogMapDescription cpqNicIfLogMapAdapterCount cpqNicIfLogMapGroupType cpqNicIfLogMapSwitchoverMode cpqNicIfLogMapCondition cpqNicIfLogMapStatus cpqNicIfLogMapNumSwitchovers cpqNicIfLogMapHwLocation cpqNicIfLogMapSpeed)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::NicSubsystem::PhysicalNic;
+our @ISA = qw(HP::Proliant::Component::NicSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ foreach (qw(cpqNicIfPhysAdapterIndex cpqNicIfPhysAdapterIfNumber cpqNicIfPhysAdapterRole cpqNicIfPhysAdapterDuplexState cpqNicIfPhysAdapterCondition cpqNicIfPhysAdapterState cpqNicIfPhysAdapterStatus cpqNicIfPhysAdapterBadTransmits cpqNicIfPhysAdapterBadReceives)) {
+ $self->{$_} = $params{$_};
+ }
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('pni', $self->{cpqNicIfPhysAdapterIndex});
+ if ($self->{cpqNicIfPhysAdapterCondition} eq "other") {
+ # hp doesnt output a clear status. i am optimistic, unknown/other
+ # means "dont care"
+ $self->add_info(sprintf "physical nic %d (%s) is %s",
+ $self->{cpqNicIfPhysAdapterIndex}, $self->{cpqNicIfPhysAdapterRole},
+ $self->{cpqNicIfPhysAdapterCondition});
+ } elsif ($self->{cpqNicIfPhysAdapterCondition} ne "ok") {
+ $self->add_info(sprintf "physical nic %d (%s) is %s (%s,%s)",
+ $self->{cpqNicIfPhysAdapterIndex}, $self->{cpqNicIfPhysAdapterRole},
+ $self->{cpqNicIfPhysAdapterCondition},
+ $self->{cpqNicIfPhysAdapterState}, $self->{cpqNicIfPhysAdapterStatus});
+ $self->add_message(CRITICAL, $self->{info});
+ } else {
+ if ($self->{cpqNicIfPhysAdapterDuplexState} ne "full") {
+ $self->add_info(sprintf "physical nic %d (%s) is %s duplex",
+ $self->{cpqNicIfPhysAdapterIndex}, $self->{cpqNicIfPhysAdapterRole},
+ $self->{cpqNicIfPhysAdapterDuplexState});
+ } else {
+ $self->add_info(sprintf "physical nic %d (%s) is %s",
+ $self->{cpqNicIfPhysAdapterIndex}, $self->{cpqNicIfPhysAdapterRole},
+ $self->{cpqNicIfPhysAdapterCondition});
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[PNIC_%s]\n", $self->{cpqNicIfPhysAdapterIndex};
+ foreach (qw(cpqNicIfPhysAdapterIndex cpqNicIfPhysAdapterIfNumber cpqNicIfPhysAdapterRole cpqNicIfPhysAdapterDuplexState cpqNicIfPhysAdapterCondition cpqNicIfPhysAdapterState cpqNicIfPhysAdapterStatus cpqNicIfPhysAdapterBadTransmits cpqNicIfPhysAdapterBadReceives)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::AsrSubsystem::CLI;
+our @ISA = qw(HP::Proliant::Component::AsrSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init(%params);
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+}
+
+sub overall_check {
+ my $self = shift;
+ my %params = @_;
+}
+
+
+package HP::Proliant::Component::AsrSubsystem::SNMP;
+our @ISA = qw(HP::Proliant::Component::AsrSubsystem
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->overall_init(%params);
+ return $self;
+}
+
+sub overall_init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $params{rawdata};
+ my $cpqHeAsrStatus = "1.3.6.1.4.1.232.6.2.5.1.0";
+ my $cpqHeAsrStatusValue = {
+ 1 => "other",
+ 2 => "notAvailable",
+ 3 => "disabled",
+ 4 => "enabled",
+ };
+ my $cpqHeAsrCondition = "1.3.6.1.4.1.232.6.2.5.17.0";
+ my $cpqHeAsrConditionValue = {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ };
+ $self->{asrcondition} = lc SNMP::Utils::get_object_value(
+ $snmpwalk, $cpqHeAsrCondition,
+ $cpqHeAsrConditionValue);
+ $self->{asrstatus} = lc SNMP::Utils::get_object_value(
+ $snmpwalk, $cpqHeAsrStatus,
+ $cpqHeAsrStatusValue);
+}
+
+sub overall_check {
+ my $self = shift;
+ my $result = 0;
+ $self->blacklist('asr', '');
+ if ($self->{asrstatus} and $self->{asrstatus} eq "enabled") {
+ my $info = sprintf 'ASR overall condition is %s', $self->{asrcondition};
+ if ($self->{asrcondition} eq "degraded") {
+ $self->add_message(WARNING, $info);
+ } elsif ($self->{asrcondition} eq "failed") {
+ $self->add_message(CRITICAL, $info);
+ }
+ $self->add_info($info);
+ } else {
+ $self->add_info('This system does not have ASR.');
+ }
+}
+
+
+package HP::Proliant::Component::AsrSubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ temperatures => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ return HP::Proliant::Component::AsrSubsystem::SNMP->new(%params);
+ } elsif ($self->{method} eq 'cli') {
+ return HP::Proliant::Component::AsrSubsystem::CLI->new(%params);
+ } else {
+ die "unknown method";
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ $self->add_info('checking ASR');
+ $self->overall_check();
+}
+
+sub dump {
+ my $self = shift;
+}
+
+
+
+
+package HP::Proliant::Component::SNMP;
+
+sub get_entries {
+ my $self = shift;
+ my $oids = shift;
+ my $entry = shift;
+ my $snmpwalk = $self->{rawdata};
+ my @params = ();
+ my @indices = SNMP::Utils::get_indices($snmpwalk, $oids->{$entry});
+ foreach (@indices) {
+ my @idx = @{$_};
+ my %params = (
+ runtime => $self->{runtime},
+ );
+ my $maxdimension = scalar(@idx) - 1;
+ foreach my $idxnr (1..scalar(@idx)) {
+ $params{'index'.$idxnr} = $_->[$idxnr - 1];
+ }
+ foreach my $oid (keys %{$oids}) {
+ next if $oid =~ /Entry$/;
+ next if $oid =~ /Value$/;
+ if (exists $oids->{$oid.'Value'}) {
+ $params{$oid} = SNMP::Utils::get_object_value(
+ $snmpwalk, $oids->{$oid}, $oids->{$oid.'Value'}, @idx);
+ if (! defined $params{$oid}) {
+ my $numerical_value = SNMP::Utils::get_object(
+ $snmpwalk, $oids->{$oid}, @idx);
+ if (! defined $numerical_value) {
+ # maschine liefert schrott
+ $params{$oid} = 'value_unknown';
+ } else {
+ $params{$oid} = 'value_'.SNMP::Utils::get_object(
+ $snmpwalk, $oids->{$oid}, @idx);
+ }
+ }
+ } else {
+ $params{$oid} = SNMP::Utils::get_object(
+ $snmpwalk, $oids->{$oid}, @idx);
+ }
+ }
+ push(@params, \%params);
+ }
+ return @params;
+}
+
+sub mib {
+ my $self = shift;
+ my $mib = shift;
+ my $condition = {
+ 0 => 'other',
+ 1 => 'ok',
+ 2 => 'degraded',
+ 3 => 'failed',
+ };
+ my $MibRevMajor = $mib.'.1.0';
+ my $MibRevMinor = $mib.'.2.0';
+ my $MibRevCondition = $mib.'.3.0';
+ return (
+ $self->SNMP::Utils::get_object($self->{rawdata},
+ $MibRevMajor),
+ $self->SNMP::Utils::get_object($self->{rawdata},
+ $MibRevMinor),
+ $self->SNMP::Utils::get_object_value($self->{rawdata},
+ $MibRevCondition, $condition));
+};
+
+
+package HP::Proliant::Component::DiskSubsystem::Da::CLI;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Da);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $hpacucli = $self->{rawdata};
+ my $slot = 0;
+ my $type = "unkn";
+ my @lines = ();
+ my $thistype = 0;
+ my $tmpcntl = {};
+ my $tmpaccel = {};
+ my $tmpld = {};
+ my $tmppd = {};
+ my $cntlindex = 0;
+ my $ldriveindex = 0;
+ my $pdriveindex = 0;
+ my $incontroller = 0;
+ foreach (split(/\n/, $hpacucli)) {
+ next unless /^status/;
+ next if /^status\s*$/;
+ s/^status\s*//;
+ if (/([\s\w]+) in Slot\s+(\d+)/) {
+ $incontroller = 1;
+ $slot = $2;
+ $cntlindex++;
+ $tmpcntl->{$slot}->{cpqDaCntlrIndex} = $cntlindex;
+ $tmpcntl->{$slot}->{cpqDaCntlrModel} = $1;
+ $tmpcntl->{$slot}->{cpqDaCntlrSlot} = $slot;
+ } elsif (/(MSA[\s\w]+)\s+in\s+(\w+)/) {
+ $incontroller = 1;
+ $slot = $2;
+ $cntlindex++;
+ $tmpcntl->{$slot}->{cpqDaCntlrIndex} = $cntlindex;
+ $tmpcntl->{$slot}->{cpqDaCntlrModel} = $1;
+ $tmpcntl->{$slot}->{cpqDaCntlrSlot} = $slot;
+ } elsif (/Controller Status: (\w+)/) {
+ $tmpcntl->{$slot}->{cpqDaCntlrBoardCondition} = lc $1;
+ $tmpcntl->{$slot}->{cpqDaCntlrCondition} = lc $1;
+ } elsif (/Cache Status: ([\w\s]+\s*$)/) {
+ # Cache Status: OK
+ # Cache Status: Not Configured
+ # Cache Status: Temporarily Disabled
+ $tmpaccel->{$slot}->{cpqDaAccelCntlrIndex} = $cntlindex;
+ $tmpaccel->{$slot}->{cpqDaAccelSlot} = $slot;
+ #condition: other,ok,degraded,failed
+ #status: other,invalid,enabled,tmpDisabled,permDisabled
+ $tmpaccel->{$slot}->{cpqDaAccelCondition} = lc $1;
+ if ($tmpaccel->{$slot}->{cpqDaAccelCondition} eq 'ok') {
+ $tmpaccel->{$slot}->{cpqDaAccelStatus} = 'enabled';
+ } elsif ($tmpaccel->{$slot}->{cpqDaAccelCondition} eq 'not configured') {
+ $tmpaccel->{$slot}->{cpqDaAccelCondition} = 'ok';
+ $tmpaccel->{$slot}->{cpqDaAccelStatus} = 'enabled';
+ } elsif ($tmpaccel->{$slot}->{cpqDaAccelCondition} eq 'temporarily disabled') {
+ $tmpaccel->{$slot}->{cpqDaAccelCondition} = 'ok';
+ $tmpaccel->{$slot}->{cpqDaAccelStatus} = 'tmpDisabled';
+ } elsif ($tmpaccel->{$slot}->{cpqDaAccelCondition} eq 'permanently disabled') {
+ $tmpaccel->{$slot}->{cpqDaAccelCondition} = 'ok';
+ $tmpaccel->{$slot}->{cpqDaAccelStatus} = 'permDisabled';
+ } else {
+ $tmpaccel->{$slot}->{cpqDaAccelStatus} = 'enabled';
+ }
+ } elsif (/Battery.* Status: (\w+)/) {
+ # sowas gibts auch Battery/Capacitor Status: OK
+ $tmpaccel->{$slot}->{cpqDaAccelBattery} = lc $1;
+ } elsif (/^\s*$/) {
+ }
+ }
+ $cntlindex = 0;
+ $ldriveindex = 0;
+ $pdriveindex = 0;
+ foreach (split(/\n/, $hpacucli)) {
+ next unless /^config/;
+ next if /^config\s*$/;
+ s/^config\s*//;
+ if (/([\s\w]+) in Slot\s+(\d+)/) {
+ $slot = $2;
+ $cntlindex++;
+ $pdriveindex = 1;
+ } elsif (/(MSA[\s\w]+)\s+in\s+(\w+)/) {
+ $slot = $2;
+ $cntlindex++;
+ $pdriveindex = 1;
+ } elsif (/logicaldrive\s+(.+?)\s+\((.*)\)/) {
+ # logicaldrive 1 (683.5 GB, RAID 5, OK)
+ # logicaldrive 1 (683.5 GB, RAID 5, OK)
+ # logicaldrive 2 (442 MB, RAID 1+0, OK)
+ $ldriveindex = $1;
+ $tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvCntlrIndex} = $cntlindex;
+ $tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvIndex} = $ldriveindex;
+ ($tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvSize},
+ $tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvFaultTol},
+ $tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvCondition}) =
+ map { lc $_ } split(/,\s*/, $2);
+ $tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvStatus} =
+ $tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvCondition};
+ $tmpld->{$slot}->{$ldriveindex}->{cpqDaLogDrvPhyDrvIDs} = 'unknown';
+ } elsif (/physicaldrive\s+(.+?)\s+\((.*)\)/) {
+ # physicaldrive 2:0 (port 2:id 0 , Parallel SCSI, 36.4 GB, OK)
+ # physicaldrive 2I:1:6 (port 2I:box 1:bay 6, SAS, 146 GB, OK)
+ # physicaldrive 1:1 (box 1:bay 1, Parallel SCSI, 146 GB, OK)
+ my $name = $1;
+ my($location, $type, $size, $status) = split(/,/, $2);
+ $status =~ s/^\s+//g;
+ $status =~ s/\s+$//g;
+ $status = lc $status;
+ my %location = ();
+ foreach (split(/:/, $location)) {
+ $location{$1} = $2 if /(\w+)\s+(\w+)/;
+ }
+ $location{box} ||= 0;
+ $location{id} ||= $pdriveindex;
+ $location{bay} ||= $location{id};
+ $location{port} ||= $location{bay};
+ $tmppd->{$slot}->{$name}->{name} = lc $name;
+ $tmppd->{$slot}->{$name}->{cpqDaPhyDrvCntlrIndex} = $cntlindex;
+ $tmppd->{$slot}->{$name}->{cpqDaPhyDrvIndex} = $location{id};
+ $tmppd->{$slot}->{$name}->{cpqDaPhyDrvBay} = $location{bay};
+ $tmppd->{$slot}->{$name}->{cpqDaPhyDrvBusNumber} = $location{port};
+ $tmppd->{$slot}->{$name}->{cpqDaPhyDrvSize} = $size;
+ $tmppd->{$slot}->{$name}->{cpqDaPhyDrvStatus} = $status;
+ $tmppd->{$slot}->{$name}->{cpqDaPhyDrvCondition} = $status;
+ $tmppd->{$slot}->{$name}->{ldriveindex} = $ldriveindex || -1;
+ foreach (keys %{$tmppd->{$slot}->{$name}}) {
+ $tmppd->{$slot}->{$name}->{$_} =~ s/^\s+//g;
+ $tmppd->{$slot}->{$name}->{$_} =~ s/\s+$//g;
+ $tmppd->{$slot}->{$name}->{$_} = lc $tmppd->{$slot}->{$name}->{$_};
+ }
+ $pdriveindex++;
+ }
+ }
+
+ foreach my $slot (keys %{$tmpcntl}) {
+ if (exists $tmpcntl->{$slot}->{cpqDaCntlrModel} &&
+ ! $self->identified($tmpcntl->{$slot}->{cpqDaCntlrModel})) {
+ delete $tmpcntl->{$slot};
+ delete $tmpaccel->{$slot};
+ delete $tmpld->{$slot};
+ delete $tmppd->{$slot};
+ }
+ }
+
+#printf "%s\n", Data::Dumper::Dumper($tmpcntl);
+#printf "%s\n", Data::Dumper::Dumper($tmpaccel);
+#printf "%s\n", Data::Dumper::Dumper($tmpld);
+#printf "%s\n", Data::Dumper::Dumper($tmppd);
+ foreach my $slot (sort {
+ $tmpcntl->{$a}->{cpqDaCntlrIndex} <=> $tmpcntl->{$b}->{cpqDaCntlrIndex}
+ }keys %{$tmpcntl}) {
+ $tmpcntl->{$slot}->{runtime} = $self->{runtime};
+ push(@{$self->{controllers}},
+ HP::Proliant::Component::DiskSubsystem::Da::Controller->new(
+ %{$tmpcntl->{$slot}}));
+ }
+ foreach my $slot (sort {
+ $tmpaccel->{$a}->{cpqDaAccelCntlrIndex} <=> $tmpaccel->{$b}->{cpqDaAccelCntlrIndex}
+ } keys %{$tmpaccel}) {
+ $tmpaccel->{$slot}->{runtime} = $self->{runtime};
+ push(@{$self->{accelerators}},
+ HP::Proliant::Component::DiskSubsystem::Da::Accelerator->new(
+ %{$tmpaccel->{$slot}}));
+ }
+ foreach my $slot (keys %{$tmpld}) {
+ foreach my $ldriveindex (keys %{$tmpld->{$slot}}) {
+ $tmpld->{$slot}->{$ldriveindex}->{runtime} = $self->{runtime};
+ push(@{$self->{logical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Da::LogicalDrive->new(
+ %{$tmpld->{$slot}->{$ldriveindex}}));
+ }
+ foreach my $pdriveindex (sort {
+ (split ':', $a, 2)[0] cmp (split ':', $b, 2)[0] ||
+ (split ':', $a, 2)[1] cmp (split ':', $b, 2)[1] ||
+ (split ':', $a, 2)[2] <=> (split ':', $b, 2)[2]
+ } keys %{$tmppd->{$slot}}) {
+ $tmppd->{$slot}->{$pdriveindex}->{runtime} = $self->{runtime};
+ push(@{$self->{physical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Da::PhysicalDrive->new(
+ %{$tmppd->{$slot}->{$pdriveindex}}));
+ }
+ }
+}
+
+sub identified {
+ my $self = shift;
+ my $info = shift;
+ return 1 if $info =~ /Parallel SCSI/;
+ return 1 if $info =~ /Smart Array/; # Trond: works fine on E200i, P400, E400
+ return 1 if $info =~ /MSA500/;
+ #return 1 if $info =~ /Smart Array (5|6)/;
+ #return 1 if $info =~ /Smart Array P400i/; # snmp sagt Da, trotz SAS in cli
+ #return 1 if $info =~ /Smart Array P410i/; # dto
+ return 0;
+}
+package HP::Proliant::Component::DiskSubsystem::Da::SNMP;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Da
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+
+ # CPQIDA-MIB
+ my $oids = {
+ cpqDaCntlrEntry => "1.3.6.1.4.1.232.3.2.2.1.1",
+ cpqDaCntlrIndex => "1.3.6.1.4.1.232.3.2.2.1.1.1",
+ cpqDaCntlrModel => "1.3.6.1.4.1.232.3.2.2.1.1.2",
+ cpqDaCntlrSlot => "1.3.6.1.4.1.232.3.2.2.1.1.5",
+ cpqDaCntlrCondition => "1.3.6.1.4.1.232.3.2.2.1.1.6",
+ cpqDaCntlrBoardCondition => "1.3.6.1.4.1.232.3.2.2.1.1.12",
+ cpqDaCntlrModelValue => {
+ 1 => 'other',
+ 2 => 'ida',
+ 3 => 'idaExpansion',
+ 4 => 'ida-2',
+ 5 => 'smart',
+ 6 => 'smart-2e',
+ 7 => 'smart-2p',
+ 8 => 'smart-2sl',
+ 9 => 'smart-3100es',
+ 10 => 'smart-3200',
+ 11 => 'smart-2dh',
+ 12 => 'smart-221',
+ 13 => 'sa-4250es',
+ 14 => 'sa-4200',
+ 15 => 'sa-integrated',
+ 16 => 'sa-431',
+ 17 => 'sa-5300',
+ 18 => 'raidLc2',
+ 19 => 'sa-5i',
+ 20 => 'sa-532',
+ 21 => 'sa-5312',
+ 22 => 'sa-641',
+ 23 => 'sa-642',
+ 24 => 'sa-6400',
+ 25 => 'sa-6400em',
+ 26 => 'sa-6i',
+ },
+ cpqDaCntlrConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqDaCntlrBoardConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ };
+
+ # INDEX { cpqDaCntlrIndex }
+ foreach ($self->get_entries($oids, 'cpqDaCntlrEntry')) {
+ push(@{$self->{controllers}},
+ HP::Proliant::Component::DiskSubsystem::Da::Controller->new(%{$_}));
+ }
+
+ $oids = {
+ cpqDaAccelEntry => "1.3.6.1.4.1.232.3.2.2.2.1",
+ cpqDaAccelCntlrIndex => "1.3.6.1.4.1.232.3.2.2.2.1.1",
+ cpqDaAccelStatus => "1.3.6.1.4.1.232.3.2.2.2.1.2",
+ cpqDaAccelSlot => "1.3.6.1.4.1.232.3.2.2.2.1.5",
+ cpqDaAccelBattery => "1.3.6.1.4.1.232.3.2.2.2.1.6",
+ cpqDaAccelCondition => "1.3.6.1.4.1.232.3.2.2.2.1.9",
+ cpqDaAccelBatteryValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'recharging',
+ 4 => 'failed',
+ 5 => 'degraded',
+ 6 => 'notPresent',
+ },
+ cpqDaAccelConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqDaAccelStatusValue => {
+ 1 => "other",
+ 2 => "invalid",
+ 3 => "enabled",
+ 4 => "tmpDisabled",
+ 5 => "permDisabled",
+ }
+ };
+
+ # INDEX { cpqDaAccelCntlrIndex }
+ foreach ($self->get_entries($oids, 'cpqDaAccelEntry')) {
+ push(@{$self->{accelerators}},
+ HP::Proliant::Component::DiskSubsystem::Da::Accelerator->new(%{$_}));
+ }
+
+ $oids = {
+ cpqDaLogDrvEntry => "1.3.6.1.4.1.232.3.2.3.1.1",
+ cpqDaLogDrvCntlrIndex => "1.3.6.1.4.1.232.3.2.3.1.1.1",
+ cpqDaLogDrvIndex => "1.3.6.1.4.1.232.3.2.3.1.1.2",
+ cpqDaLogDrvFaultTol => "1.3.6.1.4.1.232.3.2.3.1.1.3",
+ cpqDaLogDrvStatus => "1.3.6.1.4.1.232.3.2.3.1.1.4",
+ cpqDaLogDrvSize => "1.3.6.1.4.1.232.3.2.3.1.1.9",
+ cpqDaLogDrvPhyDrvIDs => "1.3.6.1.4.1.232.3.2.3.1.1.10",
+ cpqDaLogDrvCondition => "1.3.6.1.4.1.232.3.2.3.1.1.11",
+ cpqDaLogDrvPercentRebuild => "1.3.6.1.4.1.232.3.2.3.1.1.12",
+ cpqDaLogDrvFaultTolValue => {
+ 1 => "other",
+ 2 => "none",
+ 3 => "mirroring",
+ 4 => "dataGuard",
+ 5 => "distribDataGuard",
+ 7 => "advancedDataGuard",
+ },
+ cpqDaLogDrvConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqDaLogDrvStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ 4 => "unconfigured",
+ 5 => "recovering",
+ 6 => "readyForRebuild",
+ 7 => "rebuilding",
+ 8 => "wrongDrive",
+ 9 => "badConnect",
+ 10 => "overheating",
+ 11 => "shutdown",
+ 12 => "expanding",
+ 13 => "notAvailable",
+ 14 => "queuedForExpansion",
+ },
+ };
+
+ # INDEX { cpqDaLogDrvCntlrIndex, cpqDaLogDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqDaLogDrvEntry')) {
+ $_->{cpqDaLogDrvPhyDrvIDs} ||= 'empty';
+ push(@{$self->{logical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Da::LogicalDrive->new(%{$_}));
+ }
+
+ $oids = {
+ cpqDaPhyDrvEntry => "1.3.6.1.4.1.232.3.2.5.1.1",
+ cpqDaPhyDrvCntlrIndex => "1.3.6.1.4.1.232.3.2.5.1.1.1",
+ cpqDaPhyDrvIndex => "1.3.6.1.4.1.232.3.2.5.1.1.2",
+ cpqDaPhyDrvBay => "1.3.6.1.4.1.232.3.2.5.1.1.5",
+ cpqDaPhyDrvStatus => "1.3.6.1.4.1.232.3.2.5.1.1.6",
+ cpqDaPhyDrvSize => "1.3.6.1.4.1.232.3.2.5.1.1.9",
+ cpqDaPhyDrvCondition => "1.3.6.1.4.1.232.3.2.5.1.1.37",
+ cpqDaPhyDrvBusNumber => "1.3.6.1.4.1.232.3.2.5.1.1.50",
+ cpqDaPhyDrvConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqDaPhyDrvStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ 4 => "predictiveFailure",
+ },
+ };
+
+ # INDEX { cpqDaPhyDrvCntlrIndex, cpqDaPhyDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqDaPhyDrvEntry')) {
+ push(@{$self->{physical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Da::PhysicalDrive->new(%{$_}));
+ }
+
+}
+package HP::Proliant::Component::DiskSubsystem::Da;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ condition => undef,
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Da::SNMP';
+ } else {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Da::CLI';
+ }
+ $self->init();
+ $self->assemble();
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->dump();
+ }
+}
+
+package HP::Proliant::Component::DiskSubsystem::Da::Controller;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Da);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqDaCntlrIndex => $params{cpqDaCntlrIndex},
+ cpqDaCntlrSlot => $params{cpqDaCntlrSlot},
+ cpqDaCntlrModel => $params{cpqDaCntlrModel},
+ cpqDaCntlrCondition => $params{cpqDaCntlrCondition},
+ cpqDaCntlrBoardCondition => $params{cpqDaCntlrBoardCondition},
+ blacklisted => 0,
+ };
+ $self->{name} = $params{name} || $self->{cpqDaCntlrSlot};
+ $self->{controllerindex} = $self->{cpqDaCntlrIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+#$self->dumper($self);
+ $self->blacklist('daco', $self->{cpqDaCntlrIndex});
+ foreach (@{$self->{accelerators}}) {
+ $_->check();
+ }
+ foreach (@{$self->{logical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->check();
+ }
+ if ($self->{cpqDaCntlrCondition} eq 'other') {
+ if (scalar(@{$self->{physical_drives}})) {
+ $self->add_message(CRITICAL,
+ sprintf 'da controller %s in slot %s needs attention',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ $self->add_info(sprintf 'da controller %s in slot %s needs attention',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ } else {
+ $self->add_info(sprintf 'da controller %s in slot %s is ok and unused',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ $self->{blacklisted} = 1;
+ }
+ } elsif ($self->{cpqDaCntlrCondition} eq 'degraded') {
+ # maybe only the battery has failed and is disabled, no problem
+ if (scalar(grep {
+ $_->has_failed() && $_->is_disabled()
+ } @{$self->{accelerators}})) {
+ # message was already written in the accel code
+ } else {
+ $self->add_message(CRITICAL,
+ sprintf 'da controller %s in slot %s needs attention',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ $self->add_info(sprintf 'da controller %s in slot %s needs attention',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ }
+ } elsif ($self->{cpqDaCntlrCondition} ne 'ok') {
+ $self->add_message(CRITICAL,
+ sprintf 'da controller %s in slot %s needs attention',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ $self->add_info(sprintf 'da controller %s in slot %s needs attention',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ } else {
+ $self->add_info(sprintf 'da controller %s in slot %s is ok',
+ $self->{cpqDaCntlrIndex}, $self->{cpqDaCntlrSlot});
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[DA_CONTROLLER_%s]\n", $self->{name};
+ foreach (qw(cpqDaCntlrSlot cpqDaCntlrIndex cpqDaCntlrCondition
+ cpqDaCntlrModel)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+ foreach (@{$self->{accelerators}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{logical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Da::Accelerator;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Da);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqDaAccelCntlrIndex => $params{cpqDaAccelCntlrIndex},
+ cpqDaAccelBattery => $params{cpqDaAccelBattery} || 'notPresent',
+ cpqDaAccelCondition => $params{cpqDaAccelCondition},
+ cpqDaAccelStatus => $params{cpqDaAccelStatus},
+ blacklisted => 0,
+ failed => 0,
+ };
+ $self->{controllerindex} = $self->{cpqDaAccelCntlrIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('daac', $self->{cpqDaAccelCntlrIndex});
+ $self->add_info(sprintf 'controller accelerator is %s',
+ $self->{cpqDaAccelCondition});
+ if ($self->{cpqDaAccelStatus} ne "enabled") {
+ } elsif ($self->{cpqDaAccelCondition} ne "ok") {
+ if ($self->{cpqDaAccelBattery} eq "failed" &&
+ $self->{cpqDaAccelStatus} eq "tmpDisabled") {
+ # handled later
+ } else {
+ $self->add_message(CRITICAL, "controller accelerator needs attention");
+ }
+ }
+ $self->blacklist('daacb', $self->{cpqDaAccelCntlrIndex});
+ $self->add_info(sprintf 'controller accelerator battery is %s',
+ $self->{cpqDaAccelBattery});
+ if ($self->{cpqDaAccelBattery} eq "notPresent") {
+ } elsif ($self->{cpqDaAccelBattery} eq "recharging") {
+ $self->add_message(WARNING, "controller accelerator battery recharging");
+ } elsif ($self->{cpqDaAccelBattery} eq "failed" &&
+ $self->{cpqDaAccelStatus} eq "tmpDisabled") {
+ $self->add_message(WARNING, "controller accelerator battery needs attention");
+ } elsif ($self->{cpqDaAccelBattery} ne "ok") {
+ # (other) failed degraded
+ $self->add_message(CRITICAL, "controller accelerator battery needs attention");
+ }
+}
+
+sub has_failed {
+ my $self = shift;
+ return $self->{cpqDaAccelStatus} =~ /Disabled/ ? 1 : 0;
+}
+
+sub is_disabled {
+ my $self = shift;
+ return $self->{cpqDaAccelStatus} =~ /Disabled/ ? 1 : 0;
+}
+
+sub dump {
+ my $self = shift;
+ printf "[ACCELERATOR]\n";
+ foreach (qw(cpqDaAccelCntlrIndex cpqDaAccelBattery
+ cpqDaAccelStatus cpqDaAccelCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Da::LogicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Da);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqDaLogDrvIndex => $params{cpqDaLogDrvIndex},
+ cpqDaLogDrvCntlrIndex => $params{cpqDaLogDrvCntlrIndex},
+ cpqDaLogDrvSize => $params{cpqDaLogDrvSize},
+ cpqDaLogDrvFaultTol => $params{cpqDaLogDrvFaultTol},
+ cpqDaLogDrvPercentRebuild => $params{cpqDaLogDrvPercentRebuild},
+ cpqDaLogDrvStatus => $params{cpqDaLogDrvStatus},
+ cpqDaLogDrvCondition => $params{cpqDaLogDrvCondition},
+ cpqDaLogDrvPhyDrvIDs => $params{cpqDaLogDrvPhyDrvIDs},
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ $self->{name} = $params{name} ||
+ $self->{cpqDaLogDrvCntlrIndex}.':'.$self->{cpqDaLogDrvIndex}; ##vorerst
+ $self->{controllerindex} = $self->{cpqDaLogDrvCntlrIndex};
+ if (! $self->{cpqDaLogDrvPercentRebuild} ||
+ $self->{cpqDaLogDrvPercentRebuild} == 4294967295) {
+ $self->{cpqDaLogDrvPercentRebuild} = 100;
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('dald', $self->{name});
+ $self->add_info(sprintf "logical drive %s is %s (%s)",
+ $self->{name}, $self->{cpqDaLogDrvStatus},
+ $self->{cpqDaLogDrvFaultTol});
+ if ($self->{cpqDaLogDrvCondition} ne "ok") {
+ if ($self->{cpqDaLogDrvStatus} =~
+ /rebuild|recovering|expanding|queued/) {
+ $self->add_message(WARNING,
+ sprintf "logical drive %s is %s",
+ $self->{name}, $self->{cpqDaLogDrvStatus});
+ } else {
+ $self->add_message(CRITICAL,
+ sprintf "logical drive %s is %s",
+ $self->{name}, $self->{cpqDaLogDrvStatus});
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[LOGICAL_DRIVE]\n";
+ foreach (qw(cpqDaLogDrvCntlrIndex cpqDaLogDrvIndex cpqDaLogDrvSize
+ cpqDaLogDrvFaultTol cpqDaLogDrvStatus cpqDaLogDrvCondition
+ cpqDaLogDrvPercentRebuild cpqDaLogDrvPhyDrvIDs)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Da::PhysicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Da);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ name => $params{name},
+ cpqDaPhyDrvCntlrIndex => $params{cpqDaPhyDrvCntlrIndex},
+ cpqDaPhyDrvIndex => $params{cpqDaPhyDrvIndex},
+ cpqDaPhyDrvBay => $params{cpqDaPhyDrvBay},
+ cpqDaPhyDrvBusNumber => $params{cpqDaPhyDrvBusNumber},
+ cpqDaPhyDrvSize => $params{cpqDaPhyDrvSize},
+ cpqDaPhyDrvStatus => $params{cpqDaPhyDrvStatus},
+ cpqDaPhyDrvCondition => $params{cpqDaPhyDrvCondition},
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ $self->{name} = $params{name} ||
+ $self->{cpqDaPhyDrvCntlrIndex}.':'.$self->{cpqDaPhyDrvIndex}; ##vorerst
+ $self->{controllerindex} = $self->{cpqDaPhyDrvCntlrIndex};
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('dapd', $self->{name});
+ $self->add_info(
+ sprintf "physical drive %s is %s",
+ $self->{name}, $self->{cpqDaPhyDrvCondition});
+ if ($self->{cpqDaPhyDrvCondition} ne 'ok') {
+ $self->add_message(CRITICAL,
+ sprintf "physical drive %s is %s",
+ $self->{name}, $self->{cpqDaPhyDrvCondition});
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[PHYSICAL_DRIVE]\n";
+ foreach (qw(cpqDaPhyDrvCntlrIndex cpqDaPhyDrvIndex cpqDaPhyDrvBay
+ cpqDaPhyDrvBusNumber cpqDaPhyDrvSize cpqDaPhyDrvStatus
+ cpqDaPhyDrvCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Da::SpareDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Da);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub dump {
+ my $self = shift;
+ printf "[LOGICAL_DRIVE]\n";
+ foreach (qw(cntrlcpqDaCntlrIndex cpqDaCntlrIndex size level status condition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+
+package HP::Proliant::Component::DiskSubsystem::Sas::CLI;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Sas);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Sas::SNMP;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Sas
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+
+ # CPQSCSI-MIB
+ my $oids = {
+ cpqSasHbaEntry => "1.3.6.1.4.1.232.5.5.1.1.1",
+ cpqSasHbaIndex => "1.3.6.1.4.1.232.5.5.1.1.1.1",
+ cpqSasHbaLocation => "1.3.6.1.4.1.232.5.5.1.1.1.2",
+ cpqSasHbaSlot => "1.3.6.1.4.1.232.5.5.1.1.1.6",
+ cpqSasHbaStatus => "1.3.6.1.4.1.232.5.5.1.1.1.4",
+ cpqSasHbaStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ },
+ cpqSasHbaCondition => "1.3.6.1.4.1.232.5.5.1.1.1.5",
+ cpqSasHbaConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ };
+
+ # INDEX { cpqSasHbaIndex }
+ foreach ($self->get_entries($oids, 'cpqSasHbaEntry')) {
+ push(@{$self->{controllers}},
+ HP::Proliant::Component::DiskSubsystem::Sas::Controller->new(%{$_}));
+ }
+
+ $oids = {
+ cpqSasLogDrvEntry => "1.3.6.1.4.1.232.5.5.3.1.1",
+ cpqSasLogDrvHbaIndex => "1.3.6.1.4.1.232.5.5.3.1.1.1",
+ cpqSasLogDrvIndex => "1.3.6.1.4.1.232.5.5.3.1.1.2",
+ cpqSasLogDrvStatus => "1.3.6.1.4.1.232.5.5.3.1.1.4",
+ cpqSasLogDrvCondition => "1.3.6.1.4.1.232.5.5.3.1.1.5",
+ cpqSasLogDrvRebuildingPercent => "1.3.6.1.4.1.232.5.5.3.1.1.12",
+ cpqSasLogDrvRaidLevel => "1.3.6.1.4.1.232.5.5.3.1.1.3",
+ cpqSasLogDrvRaidLevelValue => {
+ 1 => "other",
+ 2 => "raid0",
+ 3 => "raid1",
+ 4 => "raid0plus1",
+ 5 => "raid5",
+ 6 => "raid15",
+ 7 => "volume",
+ },
+ cpqSasLogDrvConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqSasLogDrvStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "rebuilding",
+ 5 => "failed",
+ 6 => "offline",
+ }
+ };
+ # INDEX { cpqSasLogDrvCntlrIndex, cpqSasLogDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqSasLogDrvEntry')) {
+ push(@{$self->{logical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Sas::LogicalDrive->new(%{$_}));
+ }
+
+ $oids = {
+ cpqSasPhyDrvEntry => "1.3.6.1.4.1.232.5.5.2.1.1",
+ cpqSasPhyDrvHbaIndex => "1.3.6.1.4.1.232.5.5.2.1.1.1",
+ cpqSasPhyDrvIndex => "1.3.6.1.4.1.232.5.5.2.1.1.2",
+ cpqSasPhyDrvLocationString => "1.3.6.1.4.1.232.5.5.2.1.1.3",
+ cpqSasPhyDrvStatus => "1.3.6.1.4.1.232.5.5.2.1.1.5",
+ cpqSasPhyDrvSize => "1.3.6.1.4.1.232.5.5.2.1.1.8",
+ cpqSasPhyDrvCondition => "1.3.6.1.4.1.232.5.5.2.1.1.6",
+ cpqSasPhyDrvConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqSasPhyDrvStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "predictiveFailure",
+ 4 => "offline",
+ 5 => "failed",
+ 6 => "missingWasOk",
+ 7 => "missingWasPredictiveFailure",
+ 8 => "missingWasOffline",
+ 9 => "missingWasFailed",
+ },
+ };
+
+ # INDEX { cpqPhyLogDrvCntlrIndex, cpqSasPhyDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqSasPhyDrvEntry')) {
+ push(@{$self->{physical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Sas::PhysicalDrive->new(%{$_}));
+ }
+
+}
+package HP::Proliant::Component::DiskSubsystem::Sas;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ controllers => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ condition => undef,
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Sas::SNMP';
+ } else {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Sas::CLI';
+ }
+ $self->init();
+ $self->assemble();
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->dump();
+ }
+}
+
+package HP::Proliant::Component::DiskSubsystem::Sas::Controller;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Sas);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqSasHbaIndex => $params{cpqSasHbaIndex},
+ cpqSasHbaLocation => $params{cpqSasHbaLocation},
+ cpqSasHbaSlot => $params{cpqSasHbaSlot},
+ cpqSasHbaStatus => $params{cpqSasHbaStatus},
+ cpqSasHbaCondition => $params{cpqSasHbaCondition},
+ blacklisted => 0,
+ };
+ $self->{name} = $params{name} || $self->{cpqSasHbaSlot};
+ $self->{controllerindex} = $self->{cpqSasHbaIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('saco', $self->{cpqSasHbaSlot});
+ if ($self->{cpqSasHbaCondition} eq 'other') {
+ if (scalar(@{$self->{physical_drives}})) {
+ $self->add_message(CRITICAL,
+ sprintf 'sas controller in slot %s needs attention',
+ $self->{cpqSasHbaSlot});
+ $self->add_info(sprintf 'sas controller in slot %s needs attention',
+ $self->{cpqSasHbaSlot});
+ } else {
+ $self->add_info(sprintf 'sas controller in slot %s is ok and unused',
+ $self->{cpqSasHbaSlot});
+ $self->{blacklisted} = 1;
+ }
+ } elsif ($self->{cpqSasHbaCondition} ne 'ok') {
+ $self->add_message(CRITICAL,
+ sprintf 'sas controller in slot %s needs attention',
+ $self->{cpqSasHbaSlot});
+ $self->add_info(sprintf 'sas controller in slot %s needs attention',
+ $self->{cpqSasHbaSlot});
+ } else {
+ $self->add_info(sprintf 'sas controller in slot %s is ok',
+ $self->{cpqSasHbaSlot});
+ }
+ foreach (@{$self->{logical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[SAS_HBA%s]\n", $self->{name};
+ foreach (qw(cpqSasHbaSlot cpqSasHbaIndex cpqSasHbaCondition
+ cpqSasHbaStatus cpqSasHbaLocation)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+ foreach (@{$self->{logical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Sas::LogicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Sas);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqSasLogDrvHbaIndex => $params{cpqSasLogDrvHbaIndex},
+ cpqSasLogDrvIndex => $params{cpqSasLogDrvIndex},
+ cpqSasLogDrvStatus => $params{cpqSasLogDrvStatus},
+ cpqSasLogDrvCondition => $params{cpqSasLogDrvCondition},
+ cpqSasLogDrvRebuildingPercent => $params{cpqSasLogDrvRebuildingPercent},
+ cpqSasLogDrvRaidLevel => $params{cpqSasLogDrvRaidLevel},
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ $self->{name} = $params{name} ||
+ $self->{cpqSasLogDrvHbaIndex}.':'.$self->{cpqSasLogDrvIndex}; ####vorerst
+ $self->{controllerindex} = $self->{cpqSasLogDrvHbaIndex};
+ if (! $self->{cpqSasLogDrvRebuildingPercent} ||
+ $self->{cpqSasLogDrvRebuildingPercent} == 4294967295) {
+ $self->{cpqSasLogDrvRebuildingPercent} = 100;
+ }
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('sald', $self->{name});
+ if ($self->{cpqSasLogDrvCondition} ne "ok") {
+ if ($self->{cpqSasLogDrvStatus} =~
+ /rebuild|recovering|expanding|queued/) {
+ $self->add_message(WARNING,
+ sprintf "logical drive %s is %s",
+ $self->{name}, $self->{cpqSasLogDrvStatus});
+ } else {
+ $self->add_message(CRITICAL,
+ sprintf "logical drive %s is %s",
+ $self->{name}, $self->{cpqSasLogDrvStatus});
+ }
+ }
+ $self->add_info(
+ sprintf "logical drive %s is %s (%s)", $self->{name},
+ $self->{cpqSasLogDrvStatus}, $self->{cpqSasLogDrvRaidLevel});
+}
+
+sub dump {
+ my $self = shift;
+ printf "[LOGICAL_DRIVE]\n";
+ foreach (qw(cpqSasLogDrvHbaIndex cpqSasLogDrvIndex cpqSasLogDrvRaidLevel
+ cpqSasLogDrvStatus cpqSasLogDrvCondition
+ cpqSasLogDrvRebuildingPercent)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Sas::PhysicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Sas);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqSasPhyDrvHbaIndex => $params{cpqSasPhyDrvHbaIndex},
+ cpqSasPhyDrvIndex => $params{cpqSasPhyDrvIndex},
+ cpqSasPhyDrvLocationString => $params{cpqSasPhyDrvLocationString},
+ cpqSasPhyDrvStatus => $params{cpqSasPhyDrvStatus},
+ cpqSasPhyDrvSize => $params{cpqSasPhyDrvSize},
+ cpqSasPhyDrvCondition => $params{cpqSasPhyDrvCondition},
+ blacklisted => 0,
+ };
+ $self->{name} = $params{name} ||
+ $self->{cpqSasPhyDrvHbaIndex}.':'.$self->{cpqSasPhyDrvIndex}; ####vorerst
+ $self->{controllerindex} = $self->{cpqSasPhyDrvHbaIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('sapd', $self->{name});
+ if ($self->{cpqSasPhyDrvCondition} ne 'ok') {
+ $self->add_message(CRITICAL,
+ sprintf "physical drive %s is %s",
+ $self->{name}, $self->{cpqSasPhyDrvCondition});
+ }
+ $self->add_info(
+ sprintf "physical drive %s is %s",
+ $self->{name}, $self->{cpqSasPhyDrvCondition});
+}
+
+sub dump {
+ my $self = shift;
+ printf "[PHYSICAL_DRIVE]\n";
+ foreach (qw(cpqSasPhyDrvHbaIndex cpqSasPhyDrvIndex cpqSasPhyDrvLocationString
+ cpqSasPhyDrvSize cpqSasPhyDrvStatus cpqSasPhyDrvCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Sas::SpareDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Sas);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub dump {
+ my $self = shift;
+ printf "[SPARE_DRIVE]\n";
+}
+
+
+
+package HP::Proliant::Component::DiskSubsystem::Scsi::CLI;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Scsi);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Scsi::SNMP;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Scsi
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+
+ # CPQSCSI-MIB
+ my $oids = {
+ cpqScsiCntlrEntry => '1.3.6.1.4.1.232.5.2.2.1.1',
+ cpqScsiCntlrIndex => '1.3.6.1.4.1.232.5.2.2.1.1.1',
+ cpqScsiCntlrBusIndex => '1.3.6.1.4.1.232.5.2.2.1.1.2',
+ cpqScsiCntlrSlot => '1.3.6.1.4.1.232.5.2.2.1.1.6',
+ cpqScsiCntlrStatus => '1.3.6.1.4.1.232.5.2.2.1.1.7',
+ cpqScsiCntlrCondition => '1.3.6.1.4.1.232.5.2.2.1.1.12',
+ cpqScsiCntlrHwLocation => '1.3.6.1.4.1.232.5.2.2.1.1.16',
+ cpqScsiCntlrStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ },
+ cpqScsiCntlrConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ }
+ };
+
+ # INDEX { cpqScsiCntlrIndex, cpqScsiCntlrBusIndex }
+ foreach ($self->get_entries($oids, 'cpqScsiCntlrEntry')) {
+ push(@{$self->{controllers}},
+ HP::Proliant::Component::DiskSubsystem::Scsi::Controller->new(%{$_}));
+ }
+
+ $oids = {
+ cpqScsiLogDrvEntry => '1.3.6.1.4.1.232.5.2.3.1.1',
+ cpqScsiLogDrvCntlrIndex => '1.3.6.1.4.1.232.5.2.3.1.1.1',
+ cpqScsiLogDrvBusIndex => '1.3.6.1.4.1.232.5.2.3.1.1.2',
+ cpqScsiLogDrvIndex => '1.3.6.1.4.1.232.5.2.3.1.1.3',
+ cpqScsiLogDrvFaultTol => '1.3.6.1.4.1.232.5.2.3.1.1.4',
+ cpqScsiLogDrvStatus => '1.3.6.1.4.1.232.5.2.3.1.1.5',
+ cpqScsiLogDrvSize => '1.3.6.1.4.1.232.5.2.3.1.1.6',
+ cpqScsiLogDrvPhyDrvIDs => '1.3.6.1.4.1.232.5.2.3.1.1.7',
+ cpqScsiLogDrvCondition => '1.3.6.1.4.1.232.5.2.3.1.1.8',
+ cpqScsiLogDrvStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ 4 => "unconfigured",
+ 5 => "recovering",
+ 6 => "readyForRebuild",
+ 7 => "rebuilding",
+ 8 => "wrongDrive",
+ 9 => "badConnect",
+ },
+ cpqScsiLogDrvConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqScsiLogDrvFaultTolValue => {
+ 1 => "other",
+ 2 => "none",
+ 3 => "mirroring",
+ 4 => "dataGuard",
+ 5 => "distribDataGuard",
+ },
+
+ };
+ # INDEX { cpqScsiLogDrvCntlrIndex, cpqScsiLogDrvBusIndex, cpqScsiLogDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqScsiLogDrvEntry')) {
+ push(@{$self->{logical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Scsi::LogicalDrive->new(%{$_}));
+ }
+
+ $oids = {
+ cpqScsiPhyDrvEntry => '1.3.6.1.4.1.232.5.2.4.1.1',
+ cpqScsiPhyDrvCntlrIndex => '1.3.6.1.4.1.232.5.2.4.1.1.1',
+ cpqScsiPhyDrvBusIndex => '1.3.6.1.4.1.232.5.2.4.1.1.2',
+ cpqScsiPhyDrvIndex => '1.3.6.1.4.1.232.5.2.4.1.1.3',
+ cpqScsiPhyDrvStatus => '1.3.6.1.4.1.232.5.2.4.1.1.9',
+ cpqScsiPhyDrvSize => '1.3.6.1.4.1.232.5.2.4.1.1.7',
+ cpqScsiPhyDrvCondition => '1.3.6.1.4.1.232.5.2.4.1.1.26',
+ cpqScsiPhyDrvConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqScsiPhyDrvStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ 4 => "notConfigured",
+ 5 => "badCable",
+ 6 => "missingWasOk",
+ 7 => "missingWasFailed",
+ 8 => "predictiveFailure",
+ 9 => "missingWasPredictiveFailure",
+ 10 => "offline",
+ 11 => "missingWasOffline",
+ 12 => "hardError",
+ },
+ };
+
+ # INDEX { cpqScsiPhyDrvCntlrIndex, cpqScsiPhyDrvBusIndex, cpqScsiPhyDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqScsiPhyDrvEntry')) {
+ push(@{$self->{physical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Scsi::PhysicalDrive->new(%{$_}));
+ }
+
+}
+package HP::Proliant::Component::DiskSubsystem::Scsi;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ controllers => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ condition => undef,
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Scsi::SNMP';
+ } else {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Scsi::CLI';
+ }
+ $self->init();
+ $self->assemble();
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->dump();
+ }
+}
+
+package HP::Proliant::Component::DiskSubsystem::Scsi::Controller;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Scsi);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqScsiCntlr/, keys %params;
+ $self->{name} = $params{name} || $params{cpqScsiCntlrIndex}.':'.$params{cpqScsiCntlrBusIndex};
+ $self->{controllerindex} = $self->{cpqScsiCntlrIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('scco', $self->{name});
+ my $info = sprintf 'scsi controller %s in slot %s is %s',
+ $self->{name}, $self->{cpqScsiCntlrSlot}, $self->{cpqScsiCntlrCondition};
+ if ($self->{cpqScsiCntlrCondition} eq 'other') {
+ if (scalar(@{$self->{physical_drives}})) {
+ $info .= ' and needs attention';
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } else {
+ $info .= ' and unused';
+ $self->add_info($info);
+ $self->{blacklisted} = 1;
+ }
+ } elsif ($self->{cpqScsiCntlrCondition} ne 'ok') {
+ $info .= ' and needs attention';
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } else {
+ $self->add_info($info);
+ }
+ foreach (@{$self->{logical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[SCSI_CONTROLLER_%s]\n", $self->{name};
+ foreach (qw(cpqScsiCntlrIndex cpqScsiCntlrBusIndex cpqScsiCntlrSlot
+ cpqScsiCntlrStatus cpqScsiCntlrCondition cpqScsiCntlrHwLocation)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+ foreach (@{$self->{logical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Scsi::LogicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Scsi);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqScsiLogDrv/, keys %params;
+ $self->{name} = $params{name} || $params{cpqScsiLogDrvCntlrIndex}.':'.$params{cpqScsiLogDrvBusIndex}.':'.$params{cpqScsiLogDrvIndex};
+ bless $self, $class;
+ $self->{controllerindex} = $self->{cpqScsiLogDrvCntlrIndex};
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('scld', $self->{name});
+ my $info = sprintf 'logical drive %s is %s', $self->{name}, $self->{cpqScsiLogDrvStatus};
+ if ($self->{cpqScsiLogDrvCondition} ne "ok") {
+ if ($self->{cpqScsiLogDrvStatus} =~
+ /rebuild|recovering/) {
+ $self->add_message(WARNING, $info);
+ } else {
+ $self->add_message(CRITICAL, $info);
+ }
+ }
+ $self->add_info($info);
+}
+
+sub dump {
+ my $self = shift;
+ printf "[LOGICAL_DRIVE_%s]\n", $self->{name};
+ foreach (qw(cpqScsiLogDrvCntlrIndex cpqScsiLogDrvBusIndex cpqScsiLogDrvIndex
+ cpqScsiLogDrvFaultTol cpqScsiLogDrvStatus cpqScsiLogDrvSize
+ cpqScsiLogDrvPhyDrvIDs cpqScsiLogDrvCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Scsi::PhysicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Scsi);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqScsiPhyDrv/, keys %params;
+ $self->{name} = $params{name} ||
+ $self->{cpqScsiPhyDrvCntlrIndex}.':'.$self->{cpqScsiPhyDrvBusIndex}.':'.$self->{cpqScsiPhyDrvIndex};
+ $self->{controllerindex} = $self->{cpqScsiPhyDrvCntlrIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('scpd', $self->{name});
+ my $info = sprintf 'physical drive %s is %s', $self->{name}, $self->{cpqScsiPhyDrvCondition};
+ if ($self->{cpqScsiPhyDrvCondition} ne 'ok') {
+ $self->add_message(CRITICAL, $info);
+ }
+ $self->add_info($info);
+}
+
+sub dump {
+ my $self = shift;
+ printf "[PHYSICAL_DRIVE_%s]\n", $self->{name};
+ foreach (qw(cpqScsiPhyDrvCntlrIndex cpqScsiPhyDrvBusIndex cpqScsiPhyDrvIndex
+ cpqScsiPhyDrvStatus cpqScsiPhyDrvSize cpqScsiPhyDrvCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Scsi::SpareDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Scsi);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub dump {
+ my $self = shift;
+ printf "[SPARE_DRIVE]\n";
+}
+
+
+
+package HP::Proliant::Component::DiskSubsystem::Ide::CLI;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Ide);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Ide::SNMP;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Ide
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+
+ # CPQIDE-MIB
+ my $oids = {
+ cpqIdeControllerEntry => '1.3.6.1.4.1.232.14.2.3.1.1',
+ cpqIdeControllerIndex => '1.3.6.1.4.1.232.14.2.3.1.1.1',
+ cpqIdeControllerOverallCondition => '1.3.6.1.4.1.232.14.2.3.1.1.2',
+ cpqIdeControllerModel => '1.3.6.1.4.1.232.14.2.3.1.1.3',
+ cpqIdeControllerSlot => '1.3.6.1.4.1.232.14.2.3.1.1.5',
+ cpqIdeControllerOverallConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ };
+
+ # INDEX { cpqIdeControllerIndex }
+ foreach ($self->get_entries($oids, 'cpqIdeControllerEntry')) {
+ push(@{$self->{controllers}},
+ HP::Proliant::Component::DiskSubsystem::Ide::Controller->new(%{$_}));
+ }
+
+ $oids = {
+ cpqIdeLogicalDriveEntry => '1.3.6.1.4.1.232.14.2.6.1.1',
+ cpqIdeLogicalDriveControllerIndex => '1.3.6.1.4.1.232.14.2.6.1.1.1',
+ cpqIdeLogicalDriveIndex => '1.3.6.1.4.1.232.14.2.6.1.1.2',
+ cpqIdeLogicalDriveRaidLevel => '1.3.6.1.4.1.232.14.2.6.1.1.3',
+ cpqIdeLogicalDriveCapacity => '1.3.6.1.4.1.232.14.2.6.1.1.4',
+ cpqIdeLogicalDriveStatus => '1.3.6.1.4.1.232.14.2.6.1.1.5',
+ cpqIdeLogicalDriveCondition => '1.3.6.1.4.1.232.14.2.6.1.1.6',
+ cpqIdeLogicalDriveDiskIds => '1.3.6.1.4.1.232.14.2.6.1.1.7',
+ cpqIdeLogicalDriveSpareIds => '1.3.6.1.4.1.232.14.2.6.1.1.9',
+ cpqIdeLogicalDriveRebuildingDisk => '1.3.6.1.4.1.232.14.2.6.1.1.10',
+ cpqIdeLogicalDriveRaidLevelValue => {
+ 1 => "other",
+ 2 => "raid0",
+ 3 => "raid1",
+ 4 => "raid0plus1",
+ },
+ cpqIdeLogicalDriveStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "rebuilding",
+ 5 => "failed",
+ },
+ cpqIdeLogicalDriveConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ };
+ # INDEX { cpqIdeLogicalDriveControllerIndex, cpqIdeLogicalDriveIndex }
+ foreach ($self->get_entries($oids, 'cpqIdeLogicalDriveEntry')) {
+ push(@{$self->{logical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Ide::LogicalDrive->new(%{$_}));
+ }
+
+ $oids = {
+ cpqIdeAtaDiskEntry => '1.3.6.1.4.1.232.14.2.4.1.1',
+ cpqIdeAtaDiskControllerIndex => '1.3.6.1.4.1.232.14.2.4.1.1.1',
+ cpqIdeAtaDiskIndex => '1.3.6.1.4.1.232.14.2.4.1.1.2',
+ cpqIdeAtaDiskModel => '1.3.6.1.4.1.232.14.2.4.1.1.3',
+ cpqIdeAtaDiskStatus => '1.3.6.1.4.1.232.14.2.4.1.1.6',
+ cpqIdeAtaDiskCondition => '1.3.6.1.4.1.232.14.2.4.1.1.7',
+ cpqIdeAtaDiskCapacity => '1.3.6.1.4.1.232.14.2.4.1.1.8',
+ cpqIdeAtaDiskLogicalDriveMember => '1.3.6.1.4.1.232.14.2.4.1.1.13',
+ cpqIdeAtaDiskIsSpare => '1.3.6.1.4.1.232.14.2.4.1.1.14',
+ cpqIdeAtaDiskStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "smartError",
+ 4 => "failed",
+ },
+ cpqIdeAtaDiskConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ };
+ # INDEX { cpqIdeAtaDiskControllerIndex, cpqIdeAtaDiskIndex }
+ foreach ($self->get_entries($oids, 'cpqIdeAtaDiskEntry')) {
+ push(@{$self->{physical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Ide::PhysicalDrive->new(%{$_}));
+ }
+
+}
+package HP::Proliant::Component::DiskSubsystem::Ide;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ controllers => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ condition => undef,
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Ide::SNMP';
+ } else {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Ide::CLI';
+ }
+ $self->init();
+ $self->assemble();
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{controllers}}) {
+ $_->dump();
+ }
+}
+
+package HP::Proliant::Component::DiskSubsystem::Ide::Controller;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Ide);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqIdeControllerIndex => $params{cpqIdeControllerIndex},
+ cpqIdeControllerOverallCondition => $params{cpqIdeControllerOverallCondition},
+ cpqIdeControllerModel => $params{cpqIdeControllerModel},
+ cpqIdeControllerSlot => $params{cpqIdeControllerSlot}, # -1 ist sysboard?
+ blacklisted => 0,
+ };
+ $self->{name} = $params{name} || $self->{cpqIdeControllerIndex};
+ $self->{controllerindex} = $self->{cpqIdeControllerIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ if ($self->{cpqIdeControllerOverallCondition} eq 'other') {
+ if (scalar(@{$self->{physical_drives}})) {
+ $self->add_message(CRITICAL,
+ sprintf 'ide controller %s in slot %s needs attention',
+ $self->{cpqIdeControllerIndex}, $self->{cpqIdeControllerSlot});
+ $self->add_info(sprintf 'ide controller %s in slot %s needs attention',
+ $self->{cpqIdeControllerIndex}, $self->{cpqIdeControllerSlot});
+ } else {
+ $self->add_info(sprintf 'ide controller %s in slot %s is ok and unused',
+ $self->{cpqIdeControllerIndex}, $self->{cpqIdeControllerSlot});
+ $self->{blacklisted} = 1;
+ }
+ } elsif ($self->{cpqIdeControllerOverallCondition} ne 'ok') {
+ $self->add_message(CRITICAL,
+ sprintf 'ide controller %s in slot %s needs attention',
+ $self->{cpqIdeControllerIndex}, $self->{cpqIdeControllerSlot});
+ $self->add_info(sprintf 'ide controller %s in slot %s needs attention',
+ $self->{cpqIdeControllerIndex}, $self->{cpqIdeControllerSlot});
+ } else {
+ $self->add_info(sprintf 'ide controller %s in slot %s is ok',
+ $self->{cpqIdeControllerIndex}, $self->{cpqIdeControllerSlot});
+ }
+ foreach (@{$self->{logical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[IDE_CONTROLLER_%s]\n", $self->{name};
+ foreach (qw(cpqIdeControllerIndex cpqIdeControllerSlot
+ cpqIdeControllerModel cpqIdeControllerOverallCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+ foreach (@{$self->{logical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{spare_drives}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Ide::LogicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Ide);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqIdeLogicalDriveControllerIndex => $params{cpqIdeLogicalDriveControllerIndex},
+ cpqIdeLogicalDriveIndex => $params{cpqIdeLogicalDriveIndex},
+ cpqIdeLogicalDriveRaidLevel => $params{cpqIdeLogicalDriveRaidLevel},
+ cpqIdeLogicalDriveCapacity => $params{cpqIdeLogicalDriveCapacity},
+ cpqIdeLogicalDriveStatus => $params{cpqIdeLogicalDriveStatus},
+ cpqIdeLogicalDriveCondition => $params{cpqIdeLogicalDriveCondition},
+ cpqIdeLogicalDriveDiskIds => $params{cpqIdeLogicalDriveDiskIds},
+ cpqIdeLogicalDriveSpareIds => $params{cpqIdeLogicalDriveSpareIds},
+ cpqIdeLogicalDriveRebuildingDisk => $params{cpqIdeLogicalDriveRebuildingDisk},
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ $self->{name} = $params{name} ||
+ $self->{cpqIdeLogicalDriveControllerIndex}.':'.
+ $self->{cpqIdeLogicalDriveIndex};
+ $self->{controllerindex} = $self->{cpqIdeLogicalDriveControllerIndex};
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ if ($self->{cpqIdeLogicalDriveCondition} ne "ok") {
+ if ($self->{cpqIdeLogicalDriveStatus} =~
+ /rebuild/) {
+ $self->add_message(WARNING,
+ sprintf "logical drive %s is %s",
+ $self->{name}, $self->{cpqIdeLogicalDriveStatus});
+ } else {
+ $self->add_message(CRITICAL,
+ sprintf "logical drive %s is %s",
+ $self->{name}, $self->{cpqIdeLogicalDriveStatus});
+ }
+ }
+ $self->add_info(
+ sprintf "logical drive %s is %s", $self->{name},
+ $self->{cpqIdeLogicalDriveStatus});
+}
+
+sub dump {
+ my $self = shift;
+ printf "[LOGICAL_DRIVE]\n";
+ foreach (qw(cpqIdeLogicalDriveControllerIndex cpqIdeLogicalDriveIndex
+ cpqIdeLogicalDriveRaidLevel cpqIdeLogicalDriveCapacity
+ cpqIdeLogicalDriveDiskIds cpqIdeLogicalDriveSpareIds
+ cpqIdeLogicalDriveRebuildingDisk cpqIdeLogicalDriveStatus
+ cpqIdeLogicalDriveCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Ide::PhysicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Ide);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqIdeAtaDiskControllerIndex => $params{cpqIdeAtaDiskControllerIndex},
+ cpqIdeAtaDiskIndex => $params{cpqIdeAtaDiskIndex},
+ cpqIdeAtaDiskModel => $params{cpqIdeAtaDiskModel},
+ cpqIdeAtaDiskStatus => $params{cpqIdeAtaDiskStatus},
+ cpqIdeAtaDiskCondition => $params{cpqIdeAtaDiskCondition},
+ cpqIdeAtaDiskCapacity => $params{cpqIdeAtaDiskCapacity},
+ cpqIdeAtaDiskLogicalDriveMember => $params{cpqIdeAtaDiskLogicalDriveMember},
+ cpqIdeAtaDiskIsSpare => $params{cpqIdeAtaDiskIsSpare},
+ blacklisted => 0,
+ };
+ $self->{name} = $params{name} ||
+ $self->{cpqIdeAtaDiskControllerIndex}.':'.
+ $self->{cpqIdeAtaDiskIndex}; ####vorerst
+ $self->{controllerindex} = $self->{cpqIdeAtaDiskControllerIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ if ($self->{cpqIdeAtaDiskCondition} ne 'ok') {
+ $self->add_message(CRITICAL,
+ sprintf "physical drive %s is %s",
+ $self->{name}, $self->{cpqIdeAtaDiskCondition});
+ }
+ $self->add_info(
+ sprintf "physical drive %s is %s",
+ $self->{name}, $self->{cpqIdeAtaDiskCondition});
+}
+
+sub dump {
+ my $self = shift;
+ printf "[PHYSICAL_DRIVE]\n";
+ foreach (qw(cpqIdeAtaDiskControllerIndex cpqIdeAtaDiskIndex
+ cpqIdeAtaDiskModel cpqIdeAtaDiskCapacity cpqIdeAtaDiskLogicalDriveMember
+ cpqIdeAtaDiskStatus cpqIdeAtaDiskCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Ide::SpareDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Ide);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub dump {
+ my $self = shift;
+ printf "[SPARE_DRIVE]\n";
+}
+
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::CLI;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ # .....
+ $self->{global_status} =
+ HP::Proliant::Component::DiskSubsystem::Fca::GlobalStatus->new(
+ runtime => $self->{runtime},
+ cpqFcaMibCondition => 'n/a',
+ );
+
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::SNMP;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca
+ HP::Proliant::Component::SNMP);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+
+ # CPQFCA-MIB
+ my $oids = {
+ cpqFcaHostCntlrEntry => '1.3.6.1.4.1.232.16.2.7.1.1',
+ cpqFcaHostCntlrIndex => '1.3.6.1.4.1.232.16.2.7.1.1.1',
+ cpqFcaHostCntlrSlot => '1.3.6.1.4.1.232.16.2.7.1.1.2',
+ cpqFcaHostCntlrModel => '1.3.6.1.4.1.232.16.2.7.1.1.3',
+ cpqFcaHostCntlrStatus => '1.3.6.1.4.1.232.16.2.7.1.1.4',
+ cpqFcaHostCntlrCondition => '1.3.6.1.4.1.232.16.2.7.1.1.5',
+ cpqFcaHostCntlrOverallCondition => '1.3.6.1.4.1.232.16.2.7.1.1.8',
+ cpqFcaHostCntlrModelValue => {
+ 1 => "other",
+ 2 => "fchc-p",
+ 3 => "fchc-e",
+ 4 => "fchc64",
+ 5 => "sa-sam",
+ 6 => "fca-2101",
+ 7 => "sw64-33",
+ 8 => "fca-221x",
+ 9 => "dpfcmc",
+ },
+ cpqFcaHostCntlrStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ 4 => "shutdown",
+ 5 => "loopDegraded",
+ 6 => "loopFailed",
+ },
+ cpqFcaHostCntlrConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ cpqFcaHostCntlrOverallConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ }, # cntrl + alle associated storage boxes
+ };
+
+ # INDEX { cpqFcaHostCntlrIndex }
+ foreach ($self->get_entries($oids, 'cpqFcaHostCntlrEntry')) {
+ push(@{$self->{host_controllers}},
+ HP::Proliant::Component::DiskSubsystem::Fca::HostController->new(%{$_}));
+ }
+
+ $oids = {
+ cpqFcaCntlrEntry => '1.3.6.1.4.1.232.16.2.2.1.1',
+ cpqFcaCntlrBoxIndex => '1.3.6.1.4.1.232.16.2.2.1.1.1',
+ cpqFcaCntlrBoxIoSlot => '1.3.6.1.4.1.232.16.2.2.1.1.2',
+ cpqFcaCntlrModel => '1.3.6.1.4.1.232.16.2.2.1.1.3',
+ cpqFcaCntlrStatus => '1.3.6.1.4.1.232.16.2.2.1.1.5',
+ cpqFcaCntlrCondition => '1.3.6.1.4.1.232.16.2.2.1.1.6',
+ cpqFcaCntlrModelValue => {
+ 1 => "other",
+ 2 => "fibreArray",
+ 3 => "msa1000",
+ 4 => "smartArrayClusterStorage",
+ 5 => "hsg80",
+ 6 => "hsv110",
+ 7 => "msa500g2",
+ 8 => "msa20",
+ },
+ cpqFcaCntlrStatusValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "failed",
+ 4 => "offline",
+ 4 => "redundantPathOffline",
+ },
+ cpqFcaCntlrConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ };
+
+ # INDEX { cpqFcaCntlrBoxIndex, cpqFcaCntlrBoxIoSlot }
+ foreach ($self->get_entries($oids, 'cpqFcaCntlrEntry')) {
+ push(@{$self->{controllers}},
+ HP::Proliant::Component::DiskSubsystem::Fca::Controller->new(%{$_}));
+ }
+
+ $oids = {
+ cpqFcaAccelEntry => '1.3.6.1.4.1.232.16.2.2.2.1',
+ cpqFcaAccelBoxIndex => '1.3.6.1.4.1.232.16.2.2.2.1.1',
+ cpqFcaAccelBoxIoSlot => '1.3.6.1.4.1.232.16.2.2.2.1.2',
+ cpqFcaAccelStatus => '1.3.6.1.4.1.232.16.2.2.2.1.3',
+ cpqFcaAccelErrCode => '1.3.6.1.4.1.232.16.2.2.2.1.5',
+ cpqFcaAccelBatteryStatus => '1.3.6.1.4.1.232.16.2.2.2.1.6',
+ cpqFcaAccelCondition => '1.3.6.1.4.1.232.16.2.2.2.1.9',
+ cpqFcaAccelStatusValue => {
+ 1 => "other",
+ 2 => "invalid",
+ 3 => "enabled",
+ 4 => "tmpDisabled",
+ 5 => "permDisabled",
+ },
+ cpqFcaAccelErrCodeValue => {
+ 1 => 'other',
+ 2 => 'invalid',
+ 3 => 'badConfig',
+ 4 => 'lowBattery',
+ 5 => 'disableCmd',
+ 6 => 'noResources',
+ 7 => 'notConnected',
+ 8 => 'badMirrorData',
+ 9 => 'readErr',
+ 10 => 'writeErr',
+ 11 => 'configCmd',
+ 12 => 'expandInProgress',
+ 13 => 'snapshotInProgress',
+ 14 => 'redundantLowBattery',
+ 15 => 'redundantSizeMismatch',
+ 16 => 'redundantCacheFailure',
+ 17 => 'excessiveEccErrors',
+ 19 => 'postEccErrors',
+ },
+ cpqFcaAccelBatteryStatusValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'recharging',
+ 4 => 'failed',
+ 5 => 'degraded',
+ 6 => 'notPresent',
+ },
+ cpqFcaAccelConditionValue => {
+ 1 => "other",
+ 2 => "ok",
+ 3 => "degraded",
+ 4 => "failed",
+ },
+ };
+
+ # INDEX { cpqFcaAccelBoxIndex, cpqFcaAccelBoxIoSlot }
+ foreach ($self->get_entries($oids, 'cpqFcaAccelEntry')) {
+ push(@{$self->{accelerators}},
+ HP::Proliant::Component::DiskSubsystem::Fca::Accelerator->new(%{$_}));
+ }
+
+ $oids = {
+ cpqFcaLogDrvEntry => '1.3.6.1.4.1.232.16.2.3.1.1',
+ cpqFcaLogDrvBoxIndex => '1.3.6.1.4.1.232.16.2.3.1.1.1',
+ cpqFcaLogDrvIndex => '1.3.6.1.4.1.232.16.2.3.1.1.2',
+ cpqFcaLogDrvFaultTol => '1.3.6.1.4.1.232.16.2.3.1.1.3',
+ cpqFcaLogDrvStatus => '1.3.6.1.4.1.232.16.2.3.1.1.4',
+ cpqFcaLogDrvPercentRebuild => '1.3.6.1.4.1.232.16.2.3.1.1.6',
+ cpqFcaLogDrvSize => '1.3.6.1.4.1.232.16.2.3.1.1.9',
+ cpqFcaLogDrvPhyDrvIDs => '1.3.6.1.4.1.232.16.2.3.1.1.10',
+ cpqFcaLogDrvCondition => '1.3.6.1.4.1.232.16.2.3.1.1.11',
+ cpqFcaLogDrvFaultTolValue => {
+ 1 => 'other',
+ 2 => 'none',
+ 3 => 'mirroring',
+ 4 => 'dataGuard',
+ 5 => 'distribDataGuard',
+ 7 => 'advancedDataGuard',
+ },
+ cpqFcaLogDrvStatusValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'failed',
+ 4 => 'unconfigured',
+ 5 => 'recovering',
+ 6 => 'readyForRebuild',
+ 7 => 'rebuilding',
+ 8 => 'wrongDrive',
+ 9 => 'badConnect',
+ 10 => 'overheating',
+ 11 => 'shutdown',
+ 12 => 'expanding',
+ 13 => 'notAvailable',
+ 14 => 'queuedForExpansion',
+ 15 => 'hardError',
+ },
+ cpqFcaLogDrvConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ },
+ };
+
+ # INDEX { cpqFcaLogDrvBoxIndex, cpqFcaLogDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqFcaLogDrvEntry')) {
+ push(@{$self->{logical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Fca::LogicalDrive->new(%{$_}));
+ }
+
+ $oids = {
+ cpqFcaPhyDrvEntry => '1.3.6.1.4.1.232.16.2.5.1.1',
+ cpqFcaPhyDrvBoxIndex => '1.3.6.1.4.1.232.16.2.5.1.1.1',
+ cpqFcaPhyDrvIndex => '1.3.6.1.4.1.232.16.2.5.1.1.2',
+ cpqFcaPhyDrvModel => '1.3.6.1.4.1.232.16.2.5.1.1.3',
+ cpqFcaPhyDrvBay => '1.3.6.1.4.1.232.16.2.5.1.1.5',
+ cpqFcaPhyDrvStatus => '1.3.6.1.4.1.232.16.2.5.1.1.6',
+ cpqFcaPhyDrvCondition => '1.3.6.1.4.1.232.16.2.5.1.1.31',
+ cpqFcaPhyDrvSize => '1.3.6.1.4.1.232.16.2.5.1.1.38',
+ cpqFcaPhyDrvBusNumber => '1.3.6.1.4.1.232.16.2.5.1.1.42',
+ cpqFcaPhyDrvStatusValue => {
+ 1 => 'other',
+ 2 => 'unconfigured',
+ 3 => 'ok',
+ 4 => 'threshExceeded',
+ 5 => 'predictiveFailure',
+ 6 => 'failed',
+ },
+ cpqFcaPhyDrvConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ },
+ };
+
+ # INDEX { cpqFcaPhyDrvBoxIndex, cpqFcaPhyDrvIndex }
+ foreach ($self->get_entries($oids, 'cpqFcaPhyDrvEntry')) {
+ push(@{$self->{physical_drives}},
+ HP::Proliant::Component::DiskSubsystem::Fca::PhysicalDrive->new(%{$_}));
+ }
+
+ $oids = {
+ cpqFcaMibRevMajor => '1.3.6.1.4.1.232.16.1.1.0',
+ cpqFcaMibRevMinor => '1.3.6.1.4.1.232.16.1.2.0',
+ cpqFcaMibCondition => '1.3.6.1.4.1.232.16.1.3.0',
+ cpqFcaMibConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ },
+ };
+ $self->{global_status} =
+ HP::Proliant::Component::DiskSubsystem::Fca::GlobalStatus->new(
+ runtime => $self->{runtime},
+ cpqFcaMibCondition =>
+ SNMP::Utils::get_object_value($snmpwalk,
+ $oids->{cpqFcaMibCondition}, $oids->{cpqFcaMibConditionValue})
+ );
+}
+package HP::Proliant::Component::DiskSubsystem::Fca;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ host_controllers => [],
+ controllers => [],
+ accelerators => [],
+ physical_drives => [],
+ logical_drives => [],
+ spare_drives => [],
+ global_status => undef,
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ if ($self->{method} eq 'snmp') {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Fca::SNMP';
+ } else {
+ bless $self, 'HP::Proliant::Component::DiskSubsystem::Fca::CLI';
+ }
+ $self->init();
+ $self->assemble();
+ return $self;
+}
+
+sub assemble {
+ my $self = shift;
+ $self->trace(3, sprintf "%s controllers und platten zusammenführen",
+ ref($self));
+ $self->trace(3, sprintf "has %d host controllers",
+ scalar(@{$self->{host_controllers}}));
+ $self->trace(3, sprintf "has %d controllers",
+ scalar(@{$self->{controllers}}));
+ $self->trace(3, sprintf "has %d physical_drives",
+ scalar(@{$self->{physical_drives}}));
+ $self->trace(3, sprintf "has %d logical_drives",
+ scalar(@{$self->{logical_drives}}));
+ $self->trace(3, sprintf "has %d spare_drives",
+ scalar(@{$self->{spare_drives}}));
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{host_controllers}}) {
+ $_->check();
+ }
+ foreach (@{$self->{controllers}}) {
+ $_->check();
+ }
+ foreach (@{$self->{accelerators}}) {
+ $_->check();
+ }
+ foreach (@{$self->{logical_drives}}) {
+ $_->check();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->check();
+ }
+ # wozu eigentlich?
+ #if (! $self->has_controllers()) {
+ #$self->{global_status}->check();
+ #}
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{host_controllers}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{controllers}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{accelerators}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{logical_drives}}) {
+ $_->dump();
+ }
+ foreach (@{$self->{physical_drives}}) {
+ $_->dump();
+ }
+ #$self->{global_status}->dump();
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::GlobalStatus;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ cpqFcaMibCondition => $params{cpqFcaMibCondition},
+ };
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ if ($self->{cpqFcaMibCondition} ne 'ok') {
+ $self->add_message(CRITICAL,
+ sprintf 'fcal overall condition is %s', $self->{cpqFcaMibCondition});
+ }
+ $self->{info} =
+ sprintf 'fcal overall condition is %s', $self->{cpqFcaMibCondition};
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FCAL]\n";
+ foreach (qw(cpqFcaMibCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::HostController;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqFcaHostCntlr/, keys %params;
+ $self->{name} = $params{name} || $self->{cpqFcaHostCntlrIndex};
+ $self->{controllerindex} = $self->{cpqFcaHostCntlrIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('fcahc', $self->{name});
+ my $info = sprintf 'fcal host controller %s in slot %s is %s',
+ $self->{name}, $self->{cpqFcaHostCntlrSlot}, $self->{cpqFcaHostCntlrCondition};
+ if ($self->{cpqFcaHostCntlrCondition} eq 'other') {
+ $info .= sprintf ' and needs attention (%s)', $self->{cpqFcaHostCntlrStatus};
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } elsif ($self->{cpqFcaHostCntlrCondition} ne 'ok') {
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } else {
+ $self->add_info($info);
+ }
+ $self->blacklist('fcahco', $self->{name});
+ $info = sprintf 'fcal host controller %s overall condition is %s',
+ $self->{name}, $self->{cpqFcaHostCntlrOverallCondition};
+ if ($self->{cpqFcaHostCntlrOverallCondition} ne 'ok') {
+ $self->add_message(WARNING, $info);
+ }
+ $self->add_info($info);
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FCAL_HOST_CONTROLLER_%s]\n", $self->{name};
+ foreach (qw(cpqFcaHostCntlrIndex cpqFcaHostCntlrSlot
+ cpqFcaHostCntlrModel cpqFcaHostCntlrStatus cpqFcaHostCntlrCondition
+ cpqFcaHostCntlrOverallCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::Controller;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqFcaCntlr/, keys %params;
+ $self->{name} = $params{name} ||
+ $self->{cpqFcaCntlrBoxIndex}.':'.$self->{cpqFcaCntlrBoxIoSlot};
+ $self->{controllerindex} = $self->{cpqFcaCntlrBoxIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('fcaco', $self->{name});
+ my $info = sprintf 'fcal controller %s in box %s/slot %s is %s',
+ $self->{name}, $self->{cpqFcaCntlrBoxIndex}, $self->{cpqFcaCntlrBoxIoSlot},
+ $self->{cpqFcaCntlrCondition};
+ if ($self->{cpqFcaCntlrCondition} eq 'other') {
+ if (1) { # was ist mit phys. drives?
+ $info .= ' needs attention';
+ $info .= sprintf(' (%s)', $self->{cpqFcaCntlrStatus}) unless $self->{cpqFcaCntlrStatus} eq 'ok';
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } else {
+ $self->add_info($info);
+ $self->{blacklisted} = 1;
+ }
+ } elsif ($self->{cpqFcaCntlrCondition} ne 'ok') {
+ $info .= ' needs attention';
+ $info .= sprintf(' (%s)', $self->{cpqFcaCntlrStatus}) unless $self->{cpqFcaCntlrStatus} eq 'ok';
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } else {
+ $self->add_info($info);
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FCAL_CONTROLLER_%s]\n", $self->{name};
+ foreach (qw(cpqFcaCntlrBoxIndex cpqFcaCntlrBoxIoSlot cpqFcaCntlrModel
+ cpqFcaCntlrStatus cpqFcaCntlrCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::Accelerator;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqFcaAccel/, keys %params;
+ $self->{name} = $params{name} ||
+ $self->{cpqFcaAccelBoxIndex}.':'.$self->{cpqFcaAccelBoxIoSlot};
+ $self->{controllerindex} = $self->{cpqFcaAccelBoxIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ # !!! cpqFcaAccelStatus
+ $self->blacklist('fcaac', $self->{name});
+ my $info = sprintf 'fcal accelerator %s in box %s/slot %s is ',
+ $self->{name}, $self->{cpqFcaAccelBoxIndex}, $self->{cpqFcaAccelBoxIoSlot};
+ if ($self->{cpqFcaAccelStatus} eq 'invalid') {
+ $info .= 'not installed';
+ $self->add_info($info);
+ } elsif ($self->{cpqFcaAccelStatus} eq 'tmpDisabled') {
+ $info .= 'temp disabled';
+ $self->add_info($info);
+ } elsif ($self->{cpqFcaAccelCondition} eq 'other') {
+ $info .= sprintf '%s and needs attention (%s)',
+ $self->{cpqFcaAccelCondition}, $self->{cpqFcaAccelErrCode};
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } elsif ($self->{cpqFcaAccelCondition} ne 'ok') {
+ $info .= sprintf '%s and needs attention (%s)',
+ $self->{cpqFcaAccelCondition}, $self->{cpqFcaAccelErrCode};
+ $self->add_message(CRITICAL, $info);
+ $self->add_info($info);
+ } else {
+ $info .= sprintf '%s', $self->{cpqFcaAccelCondition};
+ $self->add_info($info);
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FCAL_ACCELERATOR_%s]\n", $self->{name};
+ foreach (qw(cpqFcaAccelBoxIndex cpqFcaAccelBoxIoSlot cpqFcaAccelStatus
+ cpqFcaAccelErrCode cpqFcaAccelBatteryStatus cpqFcaAccelCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::LogicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqFcaLogDrv/, keys %params;
+ bless $self, $class;
+ $self->{name} = $params{name} ||
+ $self->{cpqFcaLogDrvBoxIndex}.':'.
+ $self->{cpqFcaLogDrvIndex};
+ $self->{controllerindex} = $self->{cpqFcaLogDrvBoxIndex};
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('fcald', $self->{name});
+ my $info = sprintf 'logical drive %s (%s) is %s',
+ $self->{name}, $self->{cpqFcaLogDrvFaultTol}, $self->{cpqFcaLogDrvCondition};
+ if ($self->{cpqFcaLogDrvCondition} ne "ok") {
+ $info .= sprintf ' (%s)', $self->{cpqFcaLogDrvStatus};
+ if ($self->{cpqFcaLogDrvStatus} =~
+ /rebuild|recovering|expand/) {
+ $info .= sprintf ' (%s)', $self->{cpqFcaLogDrvStatus};
+ $self->add_message(WARNING, $info);
+ } else {
+ $self->add_message(CRITICAL, $info);
+ }
+ }
+ $self->add_info($info);
+}
+
+sub dump {
+ my $self = shift;
+ printf "[LOGICAL_DRIVE_%s]\n", $self->{name};
+ foreach (qw(cpqFcaLogDrvBoxIndex cpqFcaLogDrvIndex cpqFcaLogDrvFaultTol
+ cpqFcaLogDrvStatus cpqFcaLogDrvPercentRebuild cpqFcaLogDrvSize
+ cpqFcaLogDrvPhyDrvIDs cpqFcaLogDrvCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::PhysicalDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqFcaPhyDrv/, keys %params;
+ $self->{name} = $params{name} ||
+ $self->{cpqFcaPhyDrvBoxIndex}.':'.$self->{cpqFcaPhyDrvIndex}; ####vorerst
+ $self->{controllerindex} = $self->{cpqScsiPhyDrvCntlrIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('fcapd', $self->{name});
+ my $info = sprintf "physical drive %s is %s",
+ $self->{name}, $self->{cpqFcaPhyDrvStatus};
+ if ($self->{cpqFcaPhyDrvStatus} eq 'unconfigured') {
+ # not part of a logical drive
+ # condition will surely be other
+ } elsif ($self->{cpqFcaPhyDrvCondition} ne 'ok') {
+ $self->add_message(CRITICAL, $info);
+ }
+ $self->add_info($info);
+}
+
+sub dump {
+ my $self = shift;
+ printf "[PHYSICAL_DRIVE_%s]\n", $self->{name};
+ foreach (qw(cpqFcaPhyDrvBoxIndex cpqFcaPhyDrvIndex cpqFcaPhyDrvModel
+ cpqFcaPhyDrvBay cpqFcaPhyDrvStatus cpqFcaPhyDrvCondition
+ cpqFcaPhyDrvSize cpqFcaPhyDrvBusNumber)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::Proliant::Component::DiskSubsystem::Fca::SpareDrive;
+our @ISA = qw(HP::Proliant::Component::DiskSubsystem::Fca);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub dump {
+ my $self = shift;
+ printf "[SPARE_DRIVE]\n";
+}
+
+
+
+package HP::Proliant::Component::DiskSubsystem;
+our @ISA = qw(HP::Proliant::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ da_subsystem => undef,
+ sas_da_subsystem => undef,
+ ide_da_subsystem => undef,
+ fca_da_subsystem => undef,
+ scsi_da_subsystem => undef,
+ condition => $params{condition},
+ blacklisted => 0,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ $self->{da_subsystem} = HP::Proliant::Component::DiskSubsystem::Da->new(
+ runtime => $self->{runtime},
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ );
+ $self->{sas_subsystem} = HP::Proliant::Component::DiskSubsystem::Sas->new(
+ runtime => $self->{runtime},
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ );
+ $self->{scsi_subsystem} = HP::Proliant::Component::DiskSubsystem::Scsi->new(
+ runtime => $self->{runtime},
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ );
+ $self->{ide_subsystem} = HP::Proliant::Component::DiskSubsystem::Ide->new(
+ runtime => $self->{runtime},
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ );
+ $self->{fca_subsystem} = HP::Proliant::Component::DiskSubsystem::Fca->new(
+ runtime => $self->{runtime},
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ );
+}
+
+sub check {
+ my $self = shift;
+ $self->add_info('checking disk subsystem');
+ $self->{da_subsystem}->check();
+ $self->{sas_subsystem}->check();
+ $self->{scsi_subsystem}->check();
+ $self->{ide_subsystem}->check();
+ $self->{fca_subsystem}->check();
+ $self->disk_summary();
+}
+
+sub dump {
+ my $self = shift;
+ $self->{da_subsystem}->dump();
+ $self->{sas_subsystem}->dump();
+ $self->{scsi_subsystem}->dump();
+ $self->{ide_subsystem}->dump();
+ $self->{fca_subsystem}->dump();
+}
+
+sub disk_summary {
+ my $self = shift;
+ foreach my $subsys (qw(da sas scsi ide fca)) {
+ if (my $pd = $self->{$subsys.'_subsystem'}->has_physical_drives()) {
+ my $ld = $self->{$subsys.'_subsystem'}->has_logical_drives();
+ $self->add_summary(sprintf '%s: %d logical drives, %d physical drives',
+ $subsys, $ld, $pd);
+ }
+ }
+}
+
+sub assemble {
+ my $self = shift;
+ $self->trace(3, sprintf "%s controllers und platten zusammenführen",
+ ref($self));
+ $self->trace(3, sprintf "has %d controllers",
+ scalar(@{$self->{controllers}}));
+ $self->trace(3, sprintf "has %d accelerators",
+ scalar(@{$self->{accelerators}})) if exists $self->{accelerators};
+ $self->trace(3, sprintf "has %d physical_drives",
+ scalar(@{$self->{physical_drives}}));
+ $self->trace(3, sprintf "has %d logical_drives",
+ scalar(@{$self->{logical_drives}}));
+ $self->trace(3, sprintf "has %d spare_drives",
+ scalar(@{$self->{spare_drives}}));
+ my $found = {
+ accelerators => {},
+ logical_drives => {},
+ physical_drives => {},
+ spare_drives => {},
+ };
+ # found->{komponente}->{controllerindex} ist ein array
+ # von teilen, die zu einem controller gehoeren
+ foreach my $item (qw(accelerators logical_drives physical_drives spare_drives)) {
+ foreach (@{$self->{$item}}) {
+ $found->{item}->{$_->{controllerindex}} = []
+ unless exists $found->{$item}->{$_->{controllerindex}};
+ push(@{$found->{$item}->{$_->{controllerindex}}}, $_);
+ }
+ }
+ foreach my $item (qw(accelerators logical_drives physical_drives spare_drives)) {
+ foreach (@{$self->{controllers}}) {
+ if (exists $found->{$item}->{$_->{controllerindex}}) {
+ $_->{$item} = $found->{$item}->{$_->{controllerindex}};
+ delete $found->{$item}->{$_->{controllerindex}};
+ } else {
+ $_->{$item} = []; # z.b. ein leerer controller: physical_drives = []
+ }
+ }
+ }
+ # was jetzt noch in $found uebrig ist, gehoert zu keinem controller
+ # d.h. komponenten mit ungueltigen cnrtlindex wurden gefunden
+}
+
+sub has_controllers {
+ my $self = shift;
+ return scalar(@{$self->{controllers}});
+}
+
+sub has_accelerators {
+ my $self = shift;
+ return exists $self->{accelerators} ? scalar(@{$self->{accelerators}}) : 0;
+}
+
+sub has_physical_drives {
+ my $self = shift;
+ return scalar(@{$self->{physical_drives}});
+}
+
+sub has_logical_drives {
+ my $self = shift;
+ return scalar(@{$self->{logical_drives}});
+}
+
+
+package HP::Proliant::Component;
+our @ISA = qw(HP::Proliant);
+
+
+
+package HP::Proliant;
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+use Data::Dumper;
+
+our @ISA = qw(HP::Server);
+
+sub init {
+ my $self = shift;
+ $self->{components} = {
+ powersupply_subsystem => undef,
+ fan_subsystem => undef,
+ temperature_subsystem => undef,
+ cpu_subsystem => undef,
+ memory_subsystem => undef,
+ nic_subsystem => undef,
+ disk_subsystem => undef,
+ asr_subsystem => undef,
+ event_subsystem => undef,
+ };
+ $self->{serial} = 'unknown';
+ $self->{product} = 'unknown';
+ $self->{romversion} = 'unknown';
+ $self->collect();
+ if (! $self->{runtime}->{plugin}->check_messages() &&
+ ! exists $self->{noinst_hint}) {
+ $self->set_serial();
+ $self->check_for_buggy_firmware();
+ $self->analyze_cpus();
+ $self->analyze_powersupplies();
+ $self->analyze_fan_subsystem();
+ $self->analyze_temperatures();
+ $self->analyze_memory_subsystem();
+ $self->analyze_nic_subsystem();
+ $self->analyze_disk_subsystem();
+ $self->analyze_asr_subsystem();
+ $self->analyze_event_subsystem();
+ $self->auto_blacklist();
+ $self->check_cpus();
+ $self->check_powersupplies();
+ $self->check_fan_subsystem();
+ $self->check_temperatures();
+ $self->check_memory_subsystem();
+ $self->check_nic_subsystem();
+ $self->check_disk_subsystem();
+ $self->check_asr_subsystem();
+ $self->check_event_subsystem();
+ }
+}
+
+sub identify {
+ my $self = shift;
+ return sprintf "System: '%s', S/N: '%s', ROM: '%s'",
+ $self->{product}, $self->{serial}, $self->{romversion};
+}
+
+sub check_for_buggy_firmware {
+ my $self = shift;
+ my @buggyfirmwares = (
+ "P24 12/11/2001",
+ "P24 11/15/2002",
+ "D13 06/03/2003",
+ "D13 09/15/2004",
+ "P20 12/17/2002"
+ );
+ $self->{runtime}->{options}->{buggy_firmware} =
+ grep /^$self->{romversion}/, @buggyfirmwares;
+}
+
+sub dump {
+ my $self = shift;
+ printf STDERR "serial %s\n", $self->{serial};
+ printf STDERR "product %s\n", $self->{product};
+ printf STDERR "romversion %s\n", $self->{romversion};
+ printf STDERR "%s\n", Data::Dumper::Dumper($self->{components});
+}
+
+sub analyze_powersupplies {
+ my $self = shift;
+ $self->{components}->{powersupply_subsystem} =
+ HP::Proliant::Component::PowersupplySubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_fan_subsystem {
+ my $self = shift;
+ $self->{components}->{fan_subsystem} =
+ HP::Proliant::Component::FanSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_temperatures {
+ my $self = shift;
+ $self->{components}->{temperature_subsystem} =
+ HP::Proliant::Component::TemperatureSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_cpus {
+ my $self = shift;
+ $self->{components}->{cpu_subsystem} =
+ HP::Proliant::Component::CpuSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_memory_subsystem {
+ my $self = shift;
+ $self->{components}->{memory_subsystem} =
+ HP::Proliant::Component::MemorySubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_nic_subsystem {
+ my $self = shift;
+ return if $self->{method} ne "snmp";
+ $self->{components}->{nic_subsystem} =
+ HP::Proliant::Component::NicSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_disk_subsystem {
+ my $self = shift;
+ $self->{components}->{disk_subsystem} =
+ HP::Proliant::Component::DiskSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_asr_subsystem {
+ my $self = shift;
+ $self->{components}->{asr_subsystem} =
+ HP::Proliant::Component::AsrSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_event_subsystem {
+ my $self = shift;
+ $self->{components}->{event_subsystem} =
+ HP::Proliant::Component::EventSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub check_cpus {
+ my $self = shift;
+ $self->{components}->{cpu_subsystem}->check();
+ $self->{components}->{cpu_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_powersupplies {
+ my $self = shift;
+ $self->{components}->{powersupply_subsystem}->check();
+ $self->{components}->{powersupply_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_fan_subsystem {
+ my $self = shift;
+ $self->{components}->{fan_subsystem}->check();
+ $self->{components}->{fan_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_temperatures {
+ my $self = shift;
+ $self->{components}->{temperature_subsystem}->check();
+ $self->{components}->{temperature_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_memory_subsystem {
+ my $self = shift;
+ $self->{components}->{memory_subsystem}->check();
+ $self->{components}->{memory_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_nic_subsystem {
+ my $self = shift;
+ return if $self->{method} ne "snmp";
+ if ($self->{runtime}->{plugin}->{opts}->get('eval-nics')) {
+ $self->{components}->{nic_subsystem}->check();
+ $self->{components}->{nic_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+ }
+}
+sub check_disk_subsystem {
+ my $self = shift;
+ $self->{components}->{disk_subsystem}->check();
+ $self->{components}->{disk_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+ # zum anhaengen an die normale ausgabe... da: 2 logical drives, 5 physical...
+ $self->{runtime}->{plugin}->add_message(OK,
+ $self->{components}->{disk_subsystem}->{summary})
+ if $self->{components}->{disk_subsystem}->{summary};
+}
+
+sub check_asr_subsystem {
+ my $self = shift;
+ $self->{components}->{asr_subsystem}->check();
+ $self->{components}->{asr_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_event_subsystem {
+ my $self = shift;
+ $self->{components}->{event_subsystem}->check();
+ $self->{components}->{event_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub auto_blacklist() {
+ my $self = shift;
+ if ($self->{product} =~ /380 g6/) {
+ # http://bizsupport1.austin.hp.com/bc/docs/support/SupportManual/c01723408/c01723408.pdf seite 19
+ if ($self->{components}->{cpu_subsystem}->num_cpus() == 1) {
+ $self->add_blacklist('ff/f:5,6');
+ }
+ } elsif ($self->{product} =~ /380 g6/) {
+ # http://bizsupport1.austin.hp.com/bc/docs/support/SupportManual/c01704762/c01704762.pdf Fan 2 is only required when processor 2 is installed in the server.
+ }
+}
+
+
+package HP::Proliant::CLI;
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+our @ISA = qw(HP::Proliant);
+
+sub collect {
+ my $self = shift;
+ my $hpasmcli = undef;
+ if (($self->{runtime}->{plugin}->opts->hpasmcli) &&
+ (-f $self->{runtime}->{plugin}->opts->hpasmcli) &&
+ (! -x $self->{runtime}->{plugin}->opts->hpasmcli)) {
+ no strict 'refs';
+ open(BIRK, $self->{runtime}->{plugin}->opts->hpasmcli);
+ # all output in one file prefixed with server|powersupply|fans|temp|dimm
+ while(<BIRK>) {
+ chomp;
+ $self->{rawdata} .= $_."\n";
+ }
+ close BIRK;
+ # If you run this script and redirect it's output to a file
+ # you can use it for testing purposes with
+ # --hpasmcli <output>
+ # It must not be executable. (chmod 644)
+ my $diag = <<'EOEO';
+ hpasmcli=$(which hpasmcli)
+ hpacucli=$(which hpacucli)
+ for i in server powersupply fans temp dimm
+ do
+ $hpasmcli -s "show $i" | while read line
+ do
+ printf "%s %s\n" $i "$line"
+ done
+ done
+ if [ -x "$hpacucli" ]; then
+ for i in config status
+ do
+ $hpacucli ctrl all show $i | while read line
+ do
+ printf "%s %s\n" $i "$line"
+ done
+ done
+ fi
+EOEO
+ } else {
+ #die "exec hpasmcli";
+ # alles einsammeln und in rawdata stecken
+ my $hpasmcli = undef;
+ $hpasmcli = $self->{runtime}->{plugin}->opts->hpasmcli ?
+ $self->{runtime}->{plugin}->opts->hpasmcli : '/sbin/hpasmcli';
+# check if this exists at all
+# descend the directory
+ if ($self->{runtime}->{plugin}->opts->hpasmcli &&
+ -e $self->{runtime}->{plugin}->opts->hpasmcli) {
+ $hpasmcli = $self->{runtime}->{plugin}->opts->hpasmcli;
+ } elsif (-e '/sbin/hpasmcli') {
+ $hpasmcli = '/sbin/hpasmcli';
+ } else {
+ $hpasmcli = undef;
+ }
+ if ($hpasmcli) {
+ if ($< != 0) {
+ close STDIN;
+ $hpasmcli = "sudo -S ".$hpasmcli;
+ }
+ $self->trace(2, sprintf "calling %s\n", $hpasmcli);
+ $self->check_daemon();
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ $self->check_hpasm_client($hpasmcli);
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ foreach my $component (qw(server fans temp dimm powersupply iml)) {
+ if (open HPASMCLI, "$hpasmcli -s \"show $component\"|") {
+ my @output = <HPASMCLI>;
+ close HPASMCLI;
+ $self->{rawdata} .= join("\n", map {
+ $component.' '.$_;
+ } @output);
+ }
+ }
+ if ($self->{runtime}->{options}->{hpacucli}) {
+ #1 oder 0. pfad selber finden
+ my $hpacucli = undef;
+ if (-e '/usr/sbin/hpacucli') {
+ $hpacucli = '/usr/sbin/hpacucli';
+ } elsif (-e '/usr/local/sbin/hpacucli') {
+ $hpacucli = '/usr/local/sbin/hpacucli';
+ } else {
+ $hpacucli = $hpasmcli;
+ $hpacucli =~ s/^sudo\s*//;
+ $hpacucli =~ s/hpasmcli/hpacucli/;
+ $hpacucli = -e $hpacucli ? $hpacucli : undef;
+ }
+ if ($hpacucli) {
+ if ($< != 0) {
+ close STDIN;
+ $hpacucli = "sudo -S ".$hpacucli;
+ }
+ $self->trace(2, sprintf "calling %s\n", $hpacucli);
+ $self->check_hpacu_client($hpacucli);
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ if (open HPACUCLI, "$hpacucli ctrl all show config 2>&1|") {
+ my @output = <HPACUCLI>;
+ close HPACUCLI;
+ $self->{rawdata} .= join("\n", map {
+ 'config '.$_;
+ } @output);
+ }
+ if (open HPACUCLI, "$hpacucli ctrl all show status 2>&1|") {
+ my @output = <HPACUCLI>;
+ close HPACUCLI;
+ $self->{rawdata} .= join("\n", map {
+ 'status '.$_;
+ } @output);
+ }
+ } elsif ($self->{runtime}->{options}->{hpacucli} == 2) {
+ # we probably don't have sudo-privileges, but we were compiled with
+ # --enable-hpacucli=maybe
+ # so we cover it up in silence
+ $self->remove_message(UNKNOWN);
+ $self->trace(2, sprintf "calling %s seems to have failed, but nobody cares\n", $hpacucli);
+ }
+ } else {
+ if ($self->{runtime}->{options}->{noinstlevel} eq 'ok') {
+ $self->add_message(OK,
+ 'hpacucli is not installed. let\'s hope the best...');
+ } else {
+ $self->add_message(
+ uc $self->{runtime}->{options}->{noinstlevel},
+ 'hpacucli is not installed.');
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if ($self->{runtime}->{options}->{noinstlevel} eq 'ok') {
+ $self->add_message(OK,
+ 'hpasm is not installed, i can only guess');
+ $self->{noinst_hint} = 1;
+ } else {
+ $self->add_message(
+ uc $self->{runtime}->{options}->{noinstlevel},
+ 'hpasmcli is not installed.');
+ }
+ }
+ }
+}
+
+
+sub check_daemon {
+ my $self = shift;
+ my $multiproc_os_signatures_files = {
+ '/etc/SuSE-release' => 'VERSION\s*=\s*8',
+ '/etc/trustix-release' => '.*',
+ '/etc/redhat-release' => '.*Pensacola.*',
+ '/etc/debian_version' => '3\.1',
+ '/etc/issue' => '.*Kernel 2\.4\.9-vmnix2.*', # VMware ESX Server 2.5.4
+ };
+ if (open PS, "/bin/ps -e -ocmd|") {
+ my $numprocs = 0;
+ my $numcliprocs = 0;
+ my @procs = <PS>;
+ close PS;
+ $numprocs = grep /hpasm.*d$/, map { (split /\s+/, $_)[0] } @procs;
+ $numcliprocs = grep /hpasmcli/, grep !/check_hpasm/, @procs;
+ if (! $numprocs ) {
+ $self->add_message(CRITICAL, 'hpasmd needs to be restarted');
+ } elsif ($numprocs > 1) {
+ my $known = 0;
+ foreach my $osfile (keys %{$multiproc_os_signatures_files}) {
+ if (-f $osfile) {
+ open OSSIG, $osfile;
+ if (grep /$multiproc_os_signatures_files->{$osfile}/, <OSSIG>) {
+ $known = 1;
+ }
+ close OSSIG;
+ }
+ }
+ if (! $known) {
+ $self->add_message(UNKNOWN, 'multiple hpasmd procs');
+ }
+ }
+ if ($numcliprocs == 1) {
+ $self->add_message(UNKNOWN, 'another hpasmcli is running');
+ } elsif ($numcliprocs > 1) {
+ $self->add_message(UNKNOWN, 'hanging hpasmcli processes');
+ }
+ }
+}
+
+sub check_hpasm_client {
+ my $self = shift;
+ my $hpasmcli = shift;
+ if (open HPASMCLI, "$hpasmcli -s help 2>&1 |") {
+ my @output = <HPASMCLI>;
+ close HPASMCLI;
+ if (grep /Could not communicate with hpasmd/, @output) {
+ $self->add_message(CRITICAL, 'hpasmd needs to be restarted');
+ } elsif (grep /(asswor[dt]:)|(You must be root)/, @output) {
+ $self->add_message(UNKNOWN,
+ sprintf "insufficient rights to call %s", $hpasmcli);
+ } elsif (grep /must have a tty/, @output) {
+ $self->add_message(CRITICAL,
+ 'sudo must be configured with requiretty=no (man sudo)');
+ } elsif (! grep /CLEAR/, @output) {
+ $self->add_message(UNKNOWN,
+ sprintf "insufficient rights to call %s", $hpasmcli);
+ }
+ } else {
+ $self->add_message(UNKNOWN,
+ sprintf "insufficient rights to call %s", $hpasmcli);
+ }
+}
+
+sub check_hpacu_client {
+ my $self = shift;
+ my $hpacucli = shift;
+ if (open HPACUCLI, "$hpacucli help 2>&1 |") {
+ my @output = <HPACUCLI>;
+ close HPACUCLI;
+ if (grep /Another instance of hpacucli is running/, @output) {
+ $self->add_message(UNKNOWN, 'another hpacucli is running');
+ } elsif (grep /You need to have administrator rights/, @output) {
+ $self->add_message(UNKNOWN,
+ sprintf "insufficient rights to call %s", $hpacucli);
+ } elsif (grep /(asswor[dt]:)|(You must be root)/, @output) {
+ $self->add_message(UNKNOWN,
+ sprintf "insufficient rights to call %s", $hpacucli);
+ } elsif (! grep /CLI Syntax/, @output) {
+ $self->add_message(UNKNOWN,
+ sprintf "insufficient rights to call %s", $hpacucli);
+ }
+ } else {
+ $self->add_message(UNKNOWN,
+ sprintf "insufficient rights to call %s", $hpacucli);
+ }
+}
+
+sub set_serial {
+ my $self = shift;
+ foreach (grep(/^server/, split(/\n/, $self->{rawdata}))) {
+ if (/System\s+:\s+(.*[^\s])/) {
+ $self->{product} = lc $1;
+ } elsif (/Serial No\.\s+:\s+(\w+)/) {
+ $self->{serial} = $1;
+ } elsif (/ROM version\s+:\s+(.*[^\s])/) {
+ $self->{romversion} = $1;
+ }
+ }
+ $self->{serial} = $self->{serial};
+ $self->{product} = lc $self->{product};
+ $self->{romversion} = $self->{romversion};
+}
+
+
+package HP::Proliant::SNMP;
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+our @ISA = qw(HP::Proliant);
+
+sub collect {
+ my $self = shift;
+ if ($self->{runtime}->{plugin}->opts->snmpwalk) {
+ my $cpqSeMibCondition = '1.3.6.1.4.1.232.1.1.3.0'; # 2=ok
+ my $cpqHeMibCondition = '1.3.6.1.4.1.232.6.1.3.0'; # hat nicht jeder
+ if ($self->{productname} =~ /4LEE/) {
+ # rindsarsch!
+ $self->{rawdata}->{$cpqHeMibCondition} = 0;
+ }
+ if (! exists $self->{rawdata}->{$cpqHeMibCondition} &&
+ ! exists $self->{rawdata}->{$cpqSeMibCondition}) { # vlt. geht doch was
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no health data (cpqhlth-mib)');
+ }
+ } else {
+ my $net_snmp_version = Net::SNMP->VERSION(); # 5.002000 or 6.000000
+ #$params{'-translate'} = [
+ # -all => 0x0
+ #];
+ my ($session, $error) =
+ Net::SNMP->session(%{$self->{runtime}->{snmpparams}});
+ if (! defined $session) {
+ $self->{plugin}->add_message(CRITICAL, 'cannot create session object');
+ $self->trace(1, Data::Dumper::Dumper($self->{runtime}->{snmpparams}));
+ } else {
+ # revMajor is often used for discovery of hp devices
+ my $cpqHeMibRev = '1.3.6.1.4.1.232.6.1';
+ my $cpqHeMibRevMajor = '1.3.6.1.4.1.232.6.1.1.0';
+ my $cpqHeMibCondition = '1.3.6.1.4.1.232.6.1.3.0';
+ my $result = $session->get_request(
+ -varbindlist => [$cpqHeMibCondition]
+ );
+ if ($self->{productname} =~ /4LEE/) {
+ # rindsarsch!
+ $result->{$cpqHeMibCondition} = 0;
+ }
+ if (!defined($result) ||
+ $result->{$cpqHeMibCondition} eq 'noSuchInstance' ||
+ $result->{$cpqHeMibCondition} eq 'noSuchObject' ||
+ $result->{$cpqHeMibCondition} eq 'endOfMibView') {
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no health data (cpqhlth-mib)');
+ $session->close;
+ } else {
+ # this is not reliable. many agents return 4=failed
+ #if ($result->{$cpqHeMibCondition} != 2) {
+ # $obstacle = "cmapeerstart";
+ #}
+ }
+ }
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ # snmp peer is alive
+ $self->trace(2, sprintf "Protocol is %s",
+ $self->{runtime}->{snmpparams}->{'-version'});
+ my $cpqStdEquipment = "1.3.6.1.4.1.232";
+ my $cpqSeProcessor = "1.3.6.1.4.1.232.1.2.2";
+ my $cpqSeRom = "1.3.6.1.4.1.232.1.2.6";
+ my $cpqHeComponent = "1.3.6.1.4.1.232.6.2";
+ my $cpqHePWSComponent = "1.3.6.1.4.1.232.6.2.9";
+ my $cpqHeThermal = "1.3.6.1.4.1.232.6.2.6";
+ #my $cpqHeFComponent = "1.3.6.1.4.1.232.6.2.6.7";
+ #my $cpqHeTComponent = "1.3.6.1.4.1.232.6.2.6.8";
+ my $cpqHeMComponent = "1.3.6.1.4.1.232.6.2.14";
+ my $cpqDaComponent = "1.3.6.1.4.1.232.3.2";
+ my $cpqSasComponent = "1.3.6.1.4.1.232.5";
+ my $cpqIdeComponent = "1.3.6.1.4.1.232.14";
+ my $cpqFcaComponent = "1.3.6.1.4.1.232.16.2";
+ my $cpqSiComponent = "1.3.6.1.4.1.232.2.2";
+ my $cpqHeAsr = "1.3.6.1.4.1.232.6.2.5";
+ my $cpqNic = "1.3.6.1.4.1.232.18.2";
+ $session->translate;
+ my $response = {}; #break the walk up in smaller pieces
+ my $tic = time; my $tac = $tic;
+ my $response1 = $session->get_table(
+ -baseoid => $cpqSeProcessor);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqSeProcessor (%d oids)",
+ $tac - $tic, scalar(keys %{$response1}));
+ # Walk for PowerSupply
+ $tic = time;
+ my $response2p = $session->get_table(
+ -maxrepetitions => 1,
+ -baseoid => $cpqHePWSComponent);
+ if (scalar (keys %{$response2p}) == 0) {
+ $self->trace(2, sprintf "maxrepetitions failed. fallback");
+ $response2p = $session->get_table(
+ -baseoid => $cpqHePWSComponent);
+ }
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqHePWSComponent (%d oids)",
+ $tac - $tic, scalar(keys %{$response2p}));
+
+ # Walk for Fans/Temp/Overall
+ $tic = time;
+ my $response2f = $session->get_table(
+ -maxrepetitions => 1,
+ -baseoid => $cpqHeThermal);
+ if (scalar (keys %{$response2f}) == 0) {
+ $self->trace(2, sprintf "maxrepetitions failed. fallback");
+ $response2f = $session->get_table(
+ -baseoid => $cpqHeThermal);
+ }
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqHeThermal (%d oids)",
+ $tac - $tic, scalar(keys %{$response2f}));
+
+# # Walk for Fans
+# $tic = time;
+# my $response2f = $session->get_table(
+# -maxrepetitions => 1,
+# -baseoid => $cpqHeFComponent);
+# if (scalar (keys %{$response2f}) == 0) {
+# $self->trace(2, sprintf "maxrepetitions failed. fallback");
+# $response2f = $session->get_table(
+# -baseoid => $cpqHeFComponent);
+# }
+# $tac = time;
+# $self->trace(2, sprintf "%03d seconds for walk cpqHeFComponent (%d oids)",
+# $tac - $tic, scalar(keys %{$response2f}));
+# # Walk for Temp
+# $tic = time;
+# my $response2t = $session->get_table(
+# -maxrepetitions => 1,
+# -baseoid => $cpqHeTComponent);
+# if (scalar (keys %{$response2t}) == 0) {
+# $self->trace(2, sprintf "maxrepetitions failed. fallback");
+# $response2t = $session->get_table(
+# -baseoid => $cpqHeTComponent);
+# }
+# $tac = time;
+# $self->trace(2, sprintf "%03d seconds for walk cpqHeTComponent (%d oids)",
+# $tac - $tic, scalar(keys %{$response2t}));
+ # Walk for Mem
+ $tic = time;
+ my $response2m = $session->get_table(
+ -maxrepetitions => 1,
+ -baseoid => $cpqHeMComponent);
+ if (scalar (keys %{$response2m}) == 0) {
+ $self->trace(2, sprintf "maxrepetitions failed. fallback");
+ $response2m = $session->get_table(
+ -baseoid => $cpqHeMComponent);
+ }
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqHeMComponent (%d oids)",
+ $tac - $tic, scalar(keys %{$response2m}));
+ #
+ $tic = time;
+ my $response3 = $session->get_table(
+ -baseoid => $cpqDaComponent);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqDaComponent (%d oids)",
+ $tac - $tic, scalar(keys %{$response3}));
+ $tic = time;
+ my $response4 = $session->get_table(
+ -baseoid => $cpqSiComponent);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqSiComponent (%d oids)",
+ $tac - $tic, scalar(keys %{$response4}));
+ $tic = time;
+ my $response5 = $session->get_table(
+ -baseoid => $cpqSeRom);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqSeRom (%d oids)",
+ $tac - $tic, scalar(keys %{$response5}));
+ $tic = time;
+ my $response6 = $session->get_table(
+ -baseoid => $cpqSasComponent);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqSasComponent (%d oids)",
+ $tac - $tic, scalar(keys %{$response6}));
+ $tic = time;
+ my $response7 = $session->get_table(
+ -baseoid => $cpqIdeComponent);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqIdeComponent (%d oids)",
+ $tac - $tic, scalar(keys %{$response7}));
+ $tic = time;
+ my $response8 = $session->get_table(
+ -baseoid => $cpqFcaComponent);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqFcaComponent (%d oids)",
+ $tac - $tic, scalar(keys %{$response8}));
+ $tic = time;
+
+ # Walk for ASR
+ $tic = time;
+ my $response9 = $session->get_table(
+ -maxrepetitions => 1,
+ -baseoid => $cpqHeAsr);
+ if (scalar (keys %{$response9}) == 0) {
+ $self->trace(2, sprintf "maxrepetitions failed. fallback");
+ $response9 = $session->get_table(
+ -baseoid => $cpqHeAsr);
+ }
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk $cpqHeAsr (%d oids)",
+ $tac - $tic, scalar(keys %{$response9}));
+ $tic = time;
+ my $response10 = $session->get_table(
+ -baseoid => $cpqNic);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqNic (%d oids)",
+ $tac - $tic, scalar(keys %{$response10}));
+ $session->close();
+
+ map { $response->{$_} = $response1->{$_} } keys %{$response1};
+ map { $response->{$_} = $response2p->{$_} } keys %{$response2p};
+ map { $response->{$_} = $response2f->{$_} } keys %{$response2f};
+# map { $response->{$_} = $response2t->{$_} } keys %{$response2t};
+ map { $response->{$_} = $response2m->{$_} } keys %{$response2m};
+ map { $response->{$_} = $response3->{$_} } keys %{$response3};
+ map { $response->{$_} = $response4->{$_} } keys %{$response4};
+ map { $response->{$_} = $response5->{$_} } keys %{$response5};
+ map { $response->{$_} = $response6->{$_} } keys %{$response6};
+ map { $response->{$_} = $response7->{$_} } keys %{$response7};
+ map { $response->{$_} = $response8->{$_} } keys %{$response8};
+ map { $response->{$_} = $response9->{$_} } keys %{$response9};
+ map { $response->{$_} = $response10->{$_} } keys %{$response10};
+ map { $response->{$_} =~ s/^\s+//; $response->{$_} =~ s/\s+$//; }
+ keys %$response;
+ $self->{rawdata} = $response;
+ }
+ }
+ return $self->{runtime}->{plugin}->check_messages();
+}
+
+sub set_serial {
+ my $self = shift;
+
+ my $cpqSiSysSerialNum = "1.3.6.1.4.1.232.2.2.2.1.0";
+ my $cpqSiProductName = "1.3.6.1.4.1.232.2.2.4.2.0";
+ my $cpqSeSysRomVer = "1.3.6.1.4.1.232.1.2.6.1.0";
+
+ $self->{serial} =
+ SNMP::Utils::get_object($self->{rawdata}, $cpqSiSysSerialNum);
+ $self->{product} =
+ SNMP::Utils::get_object($self->{rawdata}, $cpqSiProductName);
+ $self->{romversion} =
+ SNMP::Utils::get_object($self->{rawdata}, $cpqSeSysRomVer);
+ if ($self->{romversion} && $self->{romversion} =~
+ #/(\d{2}\/\d{2}\/\d{4}).*?([ADP]{1}\d{2}).*/) {
+ /(\d{2}\/\d{2}\/\d{4}).*?Family.*?([A-Z]{1})(\d+).*/) {
+ $self->{romversion} = sprintf("%s%02d %s", $2, $3, $1);
+ } elsif ($self->{romversion} && $self->{romversion} =~
+ /([ADP]{1}\d{2})\-(\d{2}\/\d{2}\/\d{4})/) {
+ $self->{romversion} = sprintf("%s %s", $1, $2);
+ }
+ if (!$self->{serial} && $self->{romversion}) {
+ # this probably is a very, very old server.
+ $self->{serial} = "METHUSALEM";
+ $self->{runtime}->{scrapiron} = 1;
+ }
+ $self->{serial} = $self->{serial};
+ $self->{product} = lc $self->{product};
+ $self->{romversion} = $self->{romversion};
+ $self->{runtime}->{product} = $self->{product};
+}
+
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem;
+our @ISA = qw(HP::BladeSystem::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ common_enclosures => [],
+ common_enclosure_temp_subsys => undef,
+ common_enclosure_fan_subsys => undef,
+ common_enclosure_fuse_subsys => undef,
+ common_enclosure_manager_subsys => undef,
+ common_enclosure_frus => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ # jeweils ein block fuer
+ # enclosures, temps, fans, fuses
+ # loop ueber oids und entspr. new
+ my $oids = {
+ cpqRackCommonEnclosureEntry => '1.3.6.1.4.1.232.22.2.3.1.1.1',
+ cpqRackCommonEnclosureRack => '1.3.6.1.4.1.232.22.2.3.1.1.1.1',
+ cpqRackCommonEnclosureIndex => '1.3.6.1.4.1.232.22.2.3.1.1.1.2',
+ cpqRackCommonEnclosureModel => '1.3.6.1.4.1.232.22.2.3.1.1.1.3',
+ cpqRackCommonEnclosureSparePartNumber => '1.3.6.1.4.1.232.22.2.3.1.1.1.6',
+ cpqRackCommonEnclosureSerialNum => '1.3.6.1.4.1.232.22.2.3.1.1.1.7',
+ cpqRackCommonEnclosureFWRev => '1.3.6.1.4.1.232.22.2.3.1.1.1.8',
+ cpqRackCommonEnclosureName => '1.3.6.1.4.1.232.22.2.3.1.1.1.9',
+ cpqRackCommonEnclosureCondition => '1.3.6.1.4.1.232.22.2.3.1.1.1.16',
+ cpqRackCommonEnclosureHasServerBlades => '1.3.6.1.4.1.232.22.2.3.1.1.1.17',
+ cpqRackCommonEnclosureHasPowerBlades => '1.3.6.1.4.1.232.22.2.3.1.1.1.18',
+ cpqRackCommonEnclosureHasNetConnectors => '1.3.6.1.4.1.232.22.2.3.1.1.1.19',
+ cpqRackCommonEnclosureHasTempSensors => '1.3.6.1.4.1.232.22.2.3.1.1.1.20',
+ cpqRackCommonEnclosureHasFans => '1.3.6.1.4.1.232.22.2.3.1.1.1.21',
+ cpqRackCommonEnclosureHasFuses => '1.3.6.1.4.1.232.22.2.3.1.1.1.22',
+ cpqRackCommonEnclosureConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ },
+ cpqRackCommonEnclosureHasServerBladesValue => {
+ 1 => 'false',
+ 2 => 'true',
+ },
+ };
+ $oids->{cpqRackCommonEnclosureHasPowerBladesValue} =
+ $oids->{cpqRackCommonEnclosureHasServerBladesValue};
+ $oids->{cpqRackCommonEnclosureHasNetConnectorsValue} =
+ $oids->{cpqRackCommonEnclosureHasServerBladesValue};
+ $oids->{cpqRackCommonEnclosureHasTempSensorsValue} =
+ $oids->{cpqRackCommonEnclosureHasServerBladesValue};
+ $oids->{cpqRackCommonEnclosureHasFansValue} =
+ $oids->{cpqRackCommonEnclosureHasServerBladesValue};
+ $oids->{cpqRackCommonEnclosureHasServerBladesValue} =
+ $oids->{cpqRackCommonEnclosureHasServerBladesValue};
+ # INDEX { cpqRackCommonEnclosureRack cpqRackCommonEnclosureIndex }
+ foreach ($self->get_entries($oids, 'cpqRackCommonEnclosureEntry')) {
+ push(@{$self->{common_enclosures}},
+ HP::BladeSystem::Component::CommonEnclosureSubsystem::CommonEnclosure->new(%{$_}));
+ }
+
+ $self->{common_enclosure_fan_subsys} = HP::BladeSystem::Component::CommonEnclosureSubsystem::FanSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+ $self->{common_enclosure_temp_subsys} = HP::BladeSystem::Component::CommonEnclosureSubsystem::TempSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+ $self->{common_enclosure_fuse_subsys} = HP::BladeSystem::Component::CommonEnclosureSubsystem::FuseSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+ $self->{common_enclosure_manager_subsys} = HP::BladeSystem::Component::CommonEnclosureSubsystem::ManagerSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{common_enclosures}}) {
+ $_->check();
+ }
+ $self->{common_enclosure_fan_subsys}->check();
+ $self->{common_enclosure_temp_subsys}->check();
+ $self->{common_enclosure_fuse_subsys}->check();
+ $self->{common_enclosure_manager_subsys}->check();
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{common_enclosures}}) {
+ $_->dump();
+ }
+ $self->{common_enclosure_fan_subsys}->dump();
+ $self->{common_enclosure_temp_subsys}->dump();
+ $self->{common_enclosure_fuse_subsys}->dump();
+ $self->{common_enclosure_manager_subsys}->dump();
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::CommonEnclosure;
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackCommonEnclosure/, keys %params;
+ $self->{name} = $self->{cpqRackCommonEnclosureRack}.':'.$self->{cpqRackCommonEnclosureIndex};
+ $self->{serfw} = sprintf "Ser: %s, FW: %s", $self->{cpqRackCommonEnclosureSerialNum},
+ $self->{cpqRackCommonEnclosureFWRev};
+ bless $self, $class;
+ return $self;
+}
+
+
+sub check {
+ my $self = shift;
+ $self->blacklist('ce', $self->{cpqRackCommonEnclosureName});
+ my $info = sprintf 'common enclosure %s condition is %s (%s)',
+ $self->{cpqRackCommonEnclosureName}, $self->{cpqRackCommonEnclosureCondition}, $self->{serfw};
+ $self->add_info($info);
+ if ($self->{cpqRackCommonEnclosureCondition} eq 'failed') {
+ $info .= sprintf " (SparePartNum %s)", $self->{cpqRackCommonEnclosureSparePartNumber};
+ $self->add_message(CRITICAL, $info);
+ } elsif ($self->{cpqRackCommonEnclosureCondition} eq 'degraded') {
+ $info .= sprintf " (SparePartNum %s)", $self->{cpqRackCommonEnclosureSparePartNumber};
+ $self->add_message(WARNING, $info);
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[COMMON_ENCLOSURE_%s]\n", $self->{cpqRackCommonEnclosureName};
+ foreach (qw(cpqRackCommonEnclosureRack cpqRackCommonEnclosureIndex cpqRackCommonEnclosureModel
+ cpqRackCommonEnclosureSerialNum cpqRackCommonEnclosureFWRev cpqRackCommonEnclosureFWRev
+ cpqRackCommonEnclosureName
+ cpqRackCommonEnclosureCondition cpqRackCommonEnclosureHasServerBlades
+ cpqRackCommonEnclosureHasPowerBlades cpqRackCommonEnclosureHasNetConnectors
+ cpqRackCommonEnclosureHasTempSensors cpqRackCommonEnclosureHasFans cpqRackCommonEnclosureHasFuses)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::FanSubsystem;
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ fans => [],
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $oids = {
+ cpqRackCommonEnclosureFanEntry => '1.3.6.1.4.1.232.22.2.3.1.3.1',
+ cpqRackCommonEnclosureFanRack => '1.3.6.1.4.1.232.22.2.3.1.3.1.1',
+ cpqRackCommonEnclosureFanChassis => '1.3.6.1.4.1.232.22.2.3.1.3.1.2',
+ cpqRackCommonEnclosureFanIndex => '1.3.6.1.4.1.232.22.2.3.1.3.1.3',
+ cpqRackCommonEnclosureFanEnclosureName => '1.3.6.1.4.1.232.22.2.3.1.3.1.4',
+ cpqRackCommonEnclosureFanLocation => '1.3.6.1.4.1.232.22.2.3.1.3.1.5',
+ cpqRackCommonEnclosureFanPartNumber => '1.3.6.1.4.1.232.22.2.3.1.3.1.6',
+ cpqRackCommonEnclosureFanSparePartNumber => '1.3.6.1.4.1.232.22.2.3.1.3.1.7',
+ cpqRackCommonEnclosureFanPresent => '1.3.6.1.4.1.232.22.2.3.1.3.1.8',
+ cpqRackCommonEnclosureFanRedundant => '1.3.6.1.4.1.232.22.2.3.1.3.1.9',
+ cpqRackCommonEnclosureFanRedundantGroupId => '1.3.6.1.4.1.232.22.2.3.1.3.1.10',
+ cpqRackCommonEnclosureFanCondition => '1.3.6.1.4.1.232.22.2.3.1.3.1.11',
+ cpqRackCommonEnclosureFanEnclosureSerialNum => '1.3.6.1.4.1.232.22.2.3.1.3.1.12',
+ cpqRackCommonEnclosureFanPresentValue => {
+ 1 => 'other',
+ 2 => 'absent',
+ 3 => 'present',
+ },
+ cpqRackCommonEnclosureFanRedundantValue => {
+ 0 => 'other', # meiner phantasie entsprungen, da sich hp nicht aeussert
+ 1 => 'other',
+ 2 => 'notRedundant',
+ 3 => 'redundant',
+ },
+ cpqRackCommonEnclosureFanConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ }
+ };
+ # INDEX { cpqRackCommonEnclosureFanRack, cpqRackCommonEnclosureFanChassis, cpqRackCommonEnclosureFanIndex }
+ foreach ($self->get_entries($oids, 'cpqRackCommonEnclosureFanEntry')) {
+ push(@{$self->{fans}},
+ HP::BladeSystem::Component::CommonEnclosureSubsystem::FanSubsystem::Fan->new(%{$_}));
+ }
+
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{fans}}) {
+ $_->check() if $_->{cpqRackCommonEnclosureFanPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{fans}}) {
+ $_->dump() if $_->{cpqRackCommonEnclosureFanPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::FanSubsystem::Fan;
+
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem::FanSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackCommonEnclosureFan/, keys %params;
+ $self->{name} = $self->{cpqRackCommonEnclosureFanRack}.':'.$self->{cpqRackCommonEnclosureFanChassis}.':'.$self->{cpqRackCommonEnclosureFanIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('f', $self->{name});
+ $self->add_info(sprintf 'fan %s is %s, location is %s, redundance is %s, condition is %s',
+ $self->{name}, $self->{cpqRackCommonEnclosureFanPresent},
+ $self->{cpqRackCommonEnclosureFanLocation},
+ $self->{cpqRackCommonEnclosureFanRedundant},
+ $self->{cpqRackCommonEnclosureFanCondition});
+ if ($self->{cpqRackCommonEnclosureFanCondition} eq 'degraded') {
+ $self->{info} .= sprintf ", (SparePartNum: %s)", $self->{cpqRackCommonEnclosureFanSparePartNumber};
+ $self->add_message(WARNING, $self->{info});
+ } elsif ($self->{cpqRackCommonEnclosureFanCondition} eq 'failed') {
+ $self->{info} .= sprintf ", (SparePartNum: %s)", $self->{cpqRackCommonEnclosureFanSparePartNumber};
+ $self->add_message(CRITICAL, $self->{info});
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FAN_%s]\n", $self->{name};
+ foreach (qw(cpqRackCommonEnclosureFanRack cpqRackCommonEnclosureFanChassis
+ cpqRackCommonEnclosureFanIndex cpqRackCommonEnclosureFanEnclosureName
+ cpqRackCommonEnclosureFanLocation cpqRackCommonEnclosureFanPartNumber
+ cpqRackCommonEnclosureFanSparePartNumber cpqRackCommonEnclosureFanPresent
+ cpqRackCommonEnclosureFanRedundant cpqRackCommonEnclosureFanRedundantGroupId
+ cpqRackCommonEnclosureFanCondition cpqRackCommonEnclosureFanEnclosureSerialNum)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::TempSubsystem;
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ condition => $params{condition},
+ status => $params{status},
+ temperatures => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ if ($params{runtime}->{options}->{customthresholds}) {
+ if (-f $params{runtime}->{options}->{customthresholds}) {
+ open CT, $params{runtime}->{options}->{customthresholds};
+ $params{runtime}->{options}->{customthresholds} = <CT>;
+ close CT;
+ }
+ foreach my $ct_items
+ (split(/\//, $params{runtime}->{options}->{customthresholds})) {
+ if ($ct_items =~ /^(\d+):(\d+)$/) {
+ my $temp = $2;
+ $params{runtime}->{options}->{thresholds}->{$1} = $temp;
+ } else {
+ die sprintf "invalid threshold %s", $ct_items;
+ }
+ }
+ }
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my %params = @_;
+ my $snmpwalk = $self->{rawdata};
+ my $oids = {
+ cpqRackCommonEnclosureTempEntry => '1.3.6.1.4.1.232.22.2.3.1.2.1',
+ cpqRackCommonEnclosureTempRack => '1.3.6.1.4.1.232.22.2.3.1.2.1.1',
+ cpqRackCommonEnclosureTempChassis => '1.3.6.1.4.1.232.22.2.3.1.2.1.2',
+ cpqRackCommonEnclosureTempSensorIndex => '1.3.6.1.4.1.232.22.2.3.1.2.1.3',
+ cpqRackCommonEnclosureTempSensorEnclosureName => '1.3.6.1.4.1.232.22.2.3.1.2.1.4',
+ cpqRackCommonEnclosureTempLocation => '1.3.6.1.4.1.232.22.2.3.1.2.1.5',
+ cpqRackCommonEnclosureTempCurrent => '1.3.6.1.4.1.232.22.2.3.2.1.6',
+ cpqRackCommonEnclosureTempThreshold => '1.3.6.1.4.1.232.22.2.3.1.2.1.7',
+ cpqRackCommonEnclosureTempCondition => '1.3.6.1.4.1.232.22.2.3.1.2.1.8',
+ cpqRackCommonEnclosureTempType => '1.3.6.1.4.1.232.22.2.3.1.2.1.9',
+ cpqRackCommonEnclosureTempConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ },
+ cpqRackCommonEnclosureTempTypeValue => {
+ 1 => 'other',
+ 5 => 'blowout',
+ 9 => 'caution',
+ 15 => 'critical',
+ },
+ };
+ # INDEX { cpqRackCommonEnclosureTempRack cpqRackCommonEnclosureTempChassis
+ # cpqRackCommonEnclosureTempSensorIndex }
+ foreach ($self->get_entries($oids, 'cpqRackCommonEnclosureTempEntry')) {
+ push(@{$self->{temperatures}},
+ HP::BladeSystem::Component::CommonEnclosureSubsystem::TemperatureSubsystem::Temperature->new(%{$_}));
+ }
+
+}
+
+
+sub check {
+ my $self = shift;
+ my $errorfound = 0;
+ if (scalar (@{$self->{temperatures}}) == 0) {
+ #$self->overall_check();
+ } else {
+ foreach (@{$self->{temperatures}}) {
+ $_->check();
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{temperatures}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::TempSubsystem::Temp;
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem::TempSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackCommonEnclosureTemp/, keys %params;
+ $self->{name} = $params{cpqRackCommonEnclosureTempRack}.':'.
+ $params{cpqRackCommonEnclosureTempChassis}.':'.
+ $params{cpqRackCommonEnclosureTempSensorIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('t', $self->{name});
+ if ($self->{cpqRackCommonEnclosureTempCurrent} > $self->{cpqRackCommonEnclosureTempThreshold}) {
+ $self->add_info(sprintf "%s temperature too high (%d%s)",
+ $self->{cpqRackCommonEnclosureTempLocation}, $self->{cpqRackCommonEnclosureTempCurrent},
+ $self->{runtime}->{options}->{celsius} ? "C" : "F");
+ $self->add_message(CRITICAL, $self->{info});
+ } else {
+ $self->add_info(sprintf "%d %s temperature is %d (%d max)",
+ $self->{name}, $self->{ cpqRackCommonEnclosureTempLocation},
+ $self->{cpqRackCommonEnclosureTempCurrent}, $self->{cpqRackCommonEnclosureTempThreshold});
+ }
+ if ($self->{runtime}->{options}->{perfdata} == 2) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('temp_%s', $self->{name}),
+ value => $self->{cpqRackCommonEnclosureTempCurrent},
+ warning => $self->{cpqRackCommonEnclosureTempThreshold},
+ critical => $self->{cpqRackCommonEnclosureTempThreshold}
+ );
+ } elsif ($self->{runtime}->{options}->{perfdata} == 1) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('temp_%s_%s', $self->{name}, $self->{location}),
+ value => $self->{degrees},
+ warning => $self->{threshold},
+ critical => $self->{threshold}
+ );
+ }
+ $self->add_extendedinfo(sprintf "temp_%s=%d",
+ $self->{name}, $self->{cpqRackCommonEnclosureTempCurrent});
+
+}
+
+
+sub dump {
+ my $self = shift;
+ printf "[TEMP_%s]\n", $self->{name};
+ foreach (qw(cpqRackCommonEnclosureTempRack cpqRackCommonEnclosureTempChassis
+ cpqRackCommonEnclosureTempSensorIndex cpqRackCommonEnclosureTempSensorEnclosureName
+ cpqRackCommonEnclosureTempLocation
+ cpqRackCommonEnclosureTempCurrent cpqRackCommonEnclosureTempThreshold
+ cpqRackCommonEnclosureTempCondition cpqRackCommonEnclosureTempType)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n\n", $self->{info};
+}
+
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::FuseSubsystem;
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ fuses => [],
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $oids = {
+ cpqRackCommonEnclosureFuseEntry => '1.3.6.1.4.1.232.22.2.3.1.4.1',
+ cpqRackCommonEnclosureFuseRack => '1.3.6.1.4.1.232.22.2.3.1.4.1.1',
+ cpqRackCommonEnclosureFuseChassis => '1.3.6.1.4.1.232.22.2.3.1.4.1.2',
+ cpqRackCommonEnclosureFuseIndex => '1.3.6.1.4.1.232.22.2.3.1.4.1.3',
+ cpqRackCommonEnclosureFuseEnclosureName => '1.3.6.1.4.1.232.22.2.3.1.4.1.4',
+ cpqRackCommonEnclosureFuseLocation => '1.3.6.1.4.1.232.22.2.3.1.4.1.5',
+ cpqRackCommonEnclosureFusePresent => '1.3.6.1.4.1.232.22.2.3.1.4.1.8',
+ cpqRackCommonEnclosureFuseCondition => '1.3.6.1.4.1.232.22.2.3.1.4.1.11',
+ cpqRackCommonEnclosureFusePresentValue => {
+ 1 => 'other',
+ 2 => 'absent',
+ 3 => 'present',
+ },
+ cpqRackCommonEnclosureFuseConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 4 => 'failed',
+ }
+ };
+ # INDEX { cpqRackCommonEnclosureFuseRack, cpqRackCommonEnclosureFuseChassis, cpqRackCommonEnclosureFuseIndex }
+ foreach ($self->get_entries($oids, 'cpqRackCommonEnclosureFuseEntry')) {
+ push(@{$self->{fuses}},
+ HP::BladeSystem::Component::CommonEnclosureSubsystem::FuseSubsystem::Fuse->new(%{$_}));
+ }
+
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{fuses}}) {
+ $_->check() if $_->{cpqRackCommonEnclosureFusePresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{fuses}}) {
+ $_->dump() if $_->{cpqRackCommonEnclosureFusePresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::FuseSubsystem::Fuse;
+
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem::FuseSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackCommonEnclosureFuse/, keys %params;
+ $self->{name} = $self->{cpqRackCommonEnclosureFuseRack}.':'.$self->{cpqRackCommonEnclosureFuseChassis}.':'.$self->{cpqRackCommonEnclosureFuseIndex};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('fu', $self->{name});
+ $self->add_info(sprintf 'fuse %s is %s, location is %s, condition is %s',
+ $self->{name}, $self->{cpqRackCommonEnclosureFusePresent},
+ $self->{cpqRackCommonEnclosureFuseLocation}, $self->{cpqRackCommonEnclosureFuseCondition});
+ if ($self->{cpqRackCommonEnclosureFuseCondition} eq 'failed') {
+ $self->add_message(CRITICAL, $self->{info});
+ } elsif ($self->{cpqRackCommonEnclosureFuseCondition} ne 'ok') {
+ $self->add_message(WARNING, $self->{info});
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[FUSE_%s]\n", $self->{name};
+ foreach (qw(cpqRackCommonEnclosureFuseRack cpqRackCommonEnclosureFuseChassis
+ cpqRackCommonEnclosureFuseIndex cpqRackCommonEnclosureFuseEnclosureName
+ cpqRackCommonEnclosureFuseLocation cpqRackCommonEnclosureFusePresent
+ cpqRackCommonEnclosureFuseCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::ManagerSubsystem;
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ managers => [],
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $oids = {
+ cpqRackCommonEnclosureManagerEntry => '1.3.6.1.4.1.232.22.2.3.1.6.1',
+ cpqRackCommonEnclosureManagerRack => '1.3.6.1.4.1.232.22.2.3.1.6.1.1',
+ cpqRackCommonEnclosureManagerChassis => '1.3.6.1.4.1.232.22.2.3.1.6.1.2',
+ cpqRackCommonEnclosureManagerIndex => '1.3.6.1.4.1.232.22.2.3.1.6.1.3',
+ cpqRackCommonEnclosureManagerEnclosureName => '1.3.6.1.4.1.232.22.2.3.1.6.1.4',
+ cpqRackCommonEnclosureManagerLocation => '1.3.6.1.4.1.232.22.2.3.1.6.1.5',
+ cpqRackCommonEnclosureManagerPartNumber => '1.3.6.1.4.1.232.22.2.3.1.6.1.6',
+ cpqRackCommonEnclosureManagerSparePartNumber => '1.3.6.1.4.1.232.22.2.3.1.6.1.7',
+ cpqRackCommonEnclosureManagerSerialNum => '1.3.6.1.4.1.232.22.2.3.1.6.1.8',
+ cpqRackCommonEnclosureManagerRole => '1.3.6.1.4.1.232.22.2.3.1.6.1.9',
+ cpqRackCommonEnclosureManagerPresent => '1.3.6.1.4.1.232.22.2.3.1.6.1.10',
+ cpqRackCommonEnclosureManagerRedundant => '1.3.6.1.4.1.232.22.2.3.1.6.1.11',
+ cpqRackCommonEnclosureManagerCondition => '1.3.6.1.4.1.232.22.2.3.1.6.1.12',
+ cpqRackCommonEnclosureManagerFWRev => '1.3.6.1.4.1.232.22.2.3.1.6.1.15',
+ cpqRackCommonEnclosureManagerRoleValue => {
+ 1 => 'standby',
+ 2 => 'active',
+ },
+ cpqRackCommonEnclosureManagerPresentValue => {
+ 1 => 'other',
+ 2 => 'absent', # mit vorsicht zu geniessen!
+ 3 => 'present',
+ },
+ cpqRackCommonEnclosureManagerRedundantValue => {
+ 0 => 'other', # meiner phantasie entsprungen, da sich hp nicht aeussert
+ 1 => 'other',
+ 2 => 'notRedundant',
+ 3 => 'redundant',
+ },
+ cpqRackCommonEnclosureManagerConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ }
+ };
+ # INDEX { cpqRackCommonEnclosureManagerRack, cpqRackCommonEnclosureManagerChassis, cpqRackCommonEnclosureManagerIndex }
+ foreach ($self->get_entries($oids, 'cpqRackCommonEnclosureManagerEntry')) {
+ push(@{$self->{managers}},
+ HP::BladeSystem::Component::CommonEnclosureSubsystem::ManagerSubsystem::Manager->new(%{$_}));
+ }
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{managers}}) {
+ $_->check() if $_->{cpqRackCommonEnclosureManagerPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{managers}}) {
+ $_->dump() if $_->{cpqRackCommonEnclosureManagerPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+
+package HP::BladeSystem::Component::CommonEnclosureSubsystem::ManagerSubsystem::Manager;
+
+our @ISA = qw(HP::BladeSystem::Component::CommonEnclosureSubsystem::ManagerSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackCommonEnclosureManager/, keys %params;
+ $self->{name} = $self->{cpqRackCommonEnclosureManagerRack}.
+ ':'.$self->{cpqRackCommonEnclosureManagerChassis}.
+ ':'.$self->{cpqRackCommonEnclosureManagerIndex};
+ if ($self->{cpqRackCommonEnclosureManagerPresent} eq "absent" &&
+ defined $self->{cpqRackCommonEnclosureManagerEnclosureName}) {
+ $self->{cpqRackCommonEnclosureManagerPresent} = "present";
+ }
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('em', $self->{name});
+ my $info = sprintf 'manager %s is %s, location is %s, redundance is %s, condition is %s, role is %s',
+ $self->{name}, $self->{cpqRackCommonEnclosureManagerPresent},
+ $self->{cpqRackCommonEnclosureManagerLocation},
+ $self->{cpqRackCommonEnclosureManagerRedundant},
+ $self->{cpqRackCommonEnclosureManagerCondition},
+ $self->{cpqRackCommonEnclosureManagerRole};
+ $self->add_info($info) if $self->{cpqRackCommonEnclosureManagerPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent managers nur bei -vvv
+ if ($self->{cpqRackCommonEnclosureManagerCondition} eq 'degraded') {
+ $self->{info} .= sprintf ' (SparePartNum: %s)',
+ $self->{cpqRackCommonEnclosureManagerSparePartNumber};
+ $self->add_message(WARNING, $self->{info});
+ } elsif ($self->{cpqRackCommonEnclosureManagerCondition} eq 'failed') {
+ $self->{info} .= sprintf ' (SparePartNum: %s)',
+ $self->{cpqRackCommonEnclosureManagerSparePartNumber};
+ $self->add_message(CRITICAL, $self->{info});
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[ENCLOSURE_MANAGER_%s]\n", $self->{name};
+ foreach (qw(cpqRackCommonEnclosureManagerRack cpqRackCommonEnclosureManagerChassis
+ cpqRackCommonEnclosureManagerIndex cpqRackCommonEnclosureManagerEnclosureName
+ cpqRackCommonEnclosureManagerLocation cpqRackCommonEnclosureManagerPartNumber
+ cpqRackCommonEnclosureManagerSparePartNumber cpqRackCommonEnclosureManagerPresent
+ cpqRackCommonEnclosureManagerRedundant
+ cpqRackCommonEnclosureManagerCondition cpqRackCommonEnclosureManagerFWRev)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "info: %s\n", $self->{info};
+ printf "\n";
+}
+
+
+package HP::BladeSystem::Component::PowerEnclosureSubsystem;
+our @ISA = qw(HP::BladeSystem::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ power_enclosures => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+
+# cpqRackPowerEnclosureTable
+ my $oids = {
+ cpqRackPowerEnclosureEntry => '1.3.6.1.4.1.232.22.2.3.3.1.1',
+ cpqRackPowerEnclosureRack => '1.3.6.1.4.1.232.22.2.3.3.1.1.1',
+ cpqRackPowerEnclosureIndex => '1.3.6.1.4.1.232.22.2.3.3.1.1.2',
+ cpqRackPowerEnclosureName => '1.3.6.1.4.1.232.22.2.3.3.1.1.3',
+ cpqRackPowerEnclosureMgmgtBoardSerialNum => '1.3.6.1.4.1.232.22.2.3.3.1.1.4',
+ cpqRackPowerEnclosureRedundant => '1.3.6.1.4.1.232.22.2.3.3.1.1.5',
+ cpqRackPowerEnclosureLoadBalanced => '1.3.6.1.4.1.232.22.2.3.3.1.1.6',
+ cpqRackPowerEnclosureInputPwrType => '1.3.6.1.4.1.232.22.2.3.3.1.1.7',
+ cpqRackPowerEnclosurePwrFeedMax => '1.3.6.1.4.1.232.22.2.3.3.1.1.8',
+ cpqRackPowerEnclosureCondition => '1.3.6.1.4.1.232.22.2.3.3.1.1.9',
+ cpqRackPowerEnclosureRedundantValue => {
+ 1 => 'other',
+ 2 => 'notRedundant',
+ 3 => 'redundant',
+ },
+ cpqRackPowerEnclosureLoadBalancedValue => {
+ 0 => 'aechz',
+ 1 => 'other',
+ 2 => 'notLoadBalanced',
+ 3 => 'loadBalanced',
+ },
+ cpqRackPowerEnclosureInputPwrTypeValue => {
+ 1 => 'other',
+ 2 => 'singlePhase',
+ 3 => 'threePhase',
+ 4 => 'directCurrent',
+ },
+ cpqRackPowerEnclosureConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ },
+ };
+
+
+ # INDEX { cpqRackPowerEnclosureRack, cpqRackPowerEnclosureIndex }
+ # dreckada dreck, dreckada
+ foreach ($self->get_entries($oids, 'cpqRackPowerEnclosureEntry')) {
+ push(@{$self->{power_enclosures}},
+ HP::BladeSystem::Component::PowerEnclosureSubsystem::PowerEnclosure->new(%{$_}));
+ }
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{power_enclosures}}) {
+ $_->check();
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{power_enclosures}}) {
+ $_->dump();
+ }
+}
+
+
+package HP::BladeSystem::Component::PowerEnclosureSubsystem::PowerEnclosure;
+our @ISA = qw(HP::BladeSystem::Component::PowerEnclosureSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackPowerEnclosure/, keys %params;
+ $self->{name} = $self->{cpqRackPowerEnclosureRack}.':'.$self->{cpqRackPowerEnclosureIndex};
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('pe', $self->{name});
+ my $info = sprintf 'power enclosure %s \'%s\' condition is %s',
+ $self->{name}, $self->{cpqRackPowerEnclosureName}, $self->{cpqRackPowerEnclosureCondition};
+ $self->add_info($info);
+ if ($self->{cpqRackPowerEnclosureCondition} eq 'degraded') {
+ $self->add_message(WARNING, $info);
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[POWER_ENCLOSURE_%s]\n", $self->{cpqRackPowerEnclosureName};
+ foreach (qw(cpqRackPowerEnclosureRack cpqRackPowerEnclosureIndex
+ cpqRackPowerEnclosureName cpqRackPowerEnclosureMgmgtBoardSerialNum
+ cpqRackPowerEnclosureRedundant cpqRackPowerEnclosureLoadBalanced
+ cpqRackPowerEnclosureInputPwrType cpqRackPowerEnclosurePwrFeedMax
+ cpqRackPowerEnclosureCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+
+package HP::BladeSystem::Component::PowerSupplySubsystem;
+our @ISA = qw(HP::BladeSystem::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ power_supplies => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $oids = {
+ cpqRackPowerSupplyEntry => '1.3.6.1.4.1.232.22.2.5.1.1.1',
+ cpqRackPowerSupplyRack => '1.3.6.1.4.1.232.22.2.5.1.1.1.1',
+ cpqRackPowerSupplyChassis => '1.3.6.1.4.1.232.22.2.5.1.1.1.2',
+ cpqRackPowerSupplyIndex => '1.3.6.1.4.1.232.22.2.5.1.1.1.3',
+ cpqRackPowerSupplyEnclosureName => '1.3.6.1.4.1.232.22.2.5.1.1.1.4',
+ cpqRackPowerSupplySerialNum => '1.3.6.1.4.1.232.22.2.5.1.1.1.5',
+ cpqRackPowerSupplySparePartNumber => '1.3.6.1.4.1.232.22.2.5.1.1.1.7',
+ cpqRackPowerSupplyFWRev => '1.3.6.1.4.1.232.22.2.5.1.1.1.8',
+ cpqRackPowerSupplyMaxPwrOutput => '1.3.6.1.4.1.232.22.2.5.1.1.1.9',
+ cpqRackPowerSupplyCurPwrOutput => '1.3.6.1.4.1.232.22.2.5.1.1.1.10',
+ cpqRackPowerSupplyIntakeTemp => '1.3.6.1.4.1.232.22.2.5.1.1.1.12',
+ cpqRackPowerSupplyExhaustTemp => '1.3.6.1.4.1.232.22.2.5.1.1.1.13',
+ cpqRackPowerSupplyStatus => '1.3.6.1.4.1.232.22.2.5.1.1.1.14',
+ cpqRackPowerSupplySupplyInputLineStatus => '1.3.6.1.4.1.232.22.2.5.1.1.1.15',
+ cpqRackPowerSupplyPresent => '1.3.6.1.4.1.232.22.2.5.1.1.1.16',
+ cpqRackPowerSupplyCondition => '1.3.6.1.4.1.232.22.2.5.1.1.1.17',
+ cpqRackPowerSupplySupplyInputLineStatusValue => {
+ 1 => 'noError',
+ 2 => 'lineOverVoltage',
+ 3 => 'lineUnderVoltage',
+ 4 => 'lineHit',
+ 5 => 'brownOut',
+ 6 => 'linePowerLoss',
+ },
+ cpqRackPowerSupplyStatusValue => {
+ 1 => 'noError',
+ 2 => 'generalFailure',
+ 3 => 'bistFailure',
+ 4 => 'fanFailure',
+ 5 => 'tempFailure',
+ 6 => 'interlockOpen',
+ 7 => 'epromFailed',
+ 8 => 'vrefFailed',
+ 9 => 'dacFailed',
+ 10 => 'ramTestFailed',
+ 11 => 'voltageChannelFailed',
+ 12 => 'orringdiodeFailed',
+ 13 => 'brownOut',
+ 14 => 'giveupOnStartup',
+ 15 => 'nvramInvalid',
+ 16 => 'calibrationTableInvalid',
+ },
+ cpqRackPowerSupplyPresentValue => {
+ 1 => 'other',
+ 2 => 'absent',
+ 3 => 'present',
+ },
+ cpqRackPowerSupplyConditionValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ },
+ };
+
+
+ # INDEX { cpqRackPowerSupplyRack, cpqRackPowerSupplyChassis, cpqRackPowerSupplyIndex }
+ foreach ($self->get_entries($oids, 'cpqRackPowerSupplyEntry')) {
+ push(@{$self->{power_supplies}},
+ HP::BladeSystem::Component::PowerSupplySubsystem::PowerSupply->new(%{$_}));
+ }
+}
+
+sub check {
+ my $self = shift;
+ my $total_current_watt = 0;
+ my $total_max_watt = 0;
+ my $total_in_temp = 0;
+ my $total_out_temp = 0;
+ my $num_ps = 0;
+ foreach (@{$self->{power_supplies}}) {
+ $_->check() if $_->{cpqRackPowerSupplyPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ if ($_->{cpqRackPowerSupplyPresent} eq 'present') {
+ $total_max_watt += $_->{cpqRackPowerSupplyMaxPwrOutput};
+ $total_current_watt += $_->{cpqRackPowerSupplyCurPwrOutput};
+ $total_in_temp += $_->{cpqRackPowerSupplyIntakeTemp}
+ if $_->{cpqRackPowerSupplyIntakeTemp} != -1;
+ $total_out_temp += $_->{cpqRackPowerSupplyExhaustTemp}
+ if $_->{cpqRackPowerSupplyExhaustTemp} != -1;
+ $num_ps++;
+ }
+ }
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => 'watt_total',
+ value => $total_current_watt,
+ warning => $total_max_watt,
+ critical => $total_max_watt,
+ );
+ #$self->{runtime}->{plugin}->add_perfdata(
+ # label => 'watt_total_pct',
+ # value => ($total_current_watt == 0 ? 0 :
+ # sprintf("%.2f",
+ # ($total_current_watt / $total_max_watt * 100))),
+ # warning => 100,
+ # critical => 100,
+ # uom => '%',
+ #);
+ if ($total_in_temp) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => 'in_temp',
+ value => $total_in_temp / $num_ps,
+ );
+ }
+ if ($total_out_temp) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => 'out_temp',
+ value => $total_out_temp / $num_ps,
+ );
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{power_supplies}}) {
+ $_->dump() if $_->{cpqRackPowerSupplyPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+
+package HP::BladeSystem::Component::PowerSupplySubsystem::PowerSupply;
+our @ISA = qw(HP::BladeSystem::Component::PowerSupplySubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackPowerSupply/, keys %params;
+ $self->{name} = $params{cpqRackPowerSupplyRack}.
+ ':'.$params{cpqRackPowerSupplyChassis}.
+ ':'.$params{cpqRackPowerSupplyIndex};
+ $self->{serfw} = sprintf "Ser: %s, FW: %s", $self->{cpqRackPowerSupplySerialNum}, $self->{cpqRackPowerSupplyFWRev};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('ps', $self->{name});
+ my $info = sprintf 'power supply %s is %s, condition is %s (%s)',
+ $self->{name}, $self->{cpqRackPowerSupplyPresent},
+ $self->{cpqRackPowerSupplyCondition}, $self->{serfw};
+ $self->add_info($info);
+ if ($self->{cpqRackPowerSupplyPresent} eq 'present') {
+ if ($self->{cpqRackPowerSupplyCondition} eq 'degraded') {
+ $info .= sprintf " (SparePartNum %s)", $self->{cpqRackPowerSupplySparePartNumber};
+ $self->add_message(WARNING, $info);
+ $self->add_info(sprintf 'power supply %s status is %s, inp.line status is %s',
+ $self->{name}, $self->{cpqRackPowerSupplyStatus},
+ $self->{cpqRackPowerSupplySupplyInputLineStatus});
+ } elsif ($self->{cpqRackPowerSupplyCondition} eq 'failed') {
+ $info .= sprintf " (SparePartNum %s)", $self->{cpqRackPowerSupplySparePartNumber};
+ $self->add_message(CRITICAL, $info);
+ $self->add_info(sprintf 'power supply %s status is %s, inp.line status is %s',
+ $self->{name}, $self->{cpqRackPowerSupplyStatus},
+ $self->{cpqRackPowerSupplySupplyInputLineStatus});
+ }
+ if ($self->{runtime}->{options}->{perfdata} != 2) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('watt_%s', $self->{name}),
+ value => $self->{cpqRackPowerSupplyCurPwrOutput},
+ warning => $self->{cpqRackPowerSupplyMaxPwrOutput},
+ critical => $self->{cpqRackPowerSupplyMaxPwrOutput}
+ );
+ #$self->{runtime}->{plugin}->add_perfdata(
+ # label => sprintf('watt_pct_%s', $self->{name}),
+ # value => ($self->{cpqRackPowerSupplyCurPwrOutput} == 0 ? 0 :
+ # sprintf ("%.2f",
+ # ($self->{cpqRackPowerSupplyCurPwrOutput} /
+ # $self->{cpqRackPowerSupplyMaxPwrOutput} * 100))),
+ # warning => 100,
+ # critical => 100,
+ # uom => '%',
+ #);
+ if ($self->{cpqRackPowerSupplyIntakeTemp} != -1) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('in_temp_%s', $self->{name}),
+ value => $self->{cpqRackPowerSupplyIntakeTemp},
+ );
+ }
+ if ($self->{cpqRackPowerSupplyExhaustTemp} != -1) {
+ $self->{runtime}->{plugin}->add_perfdata(
+ label => sprintf('out_temp_%s', $self->{name}),
+ value => $self->{cpqRackPowerSupplyExhaustTemp},
+ );
+ }
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[POWER_SUPPLY%s]\n", $self->{name};
+ foreach (qw(cpqRackPowerSupplyRack cpqRackPowerSupplyChassis cpqRackPowerSupplyIndex cpqRackPowerSupplyEnclosureName cpqRackPowerSupplySerialNum cpqRackPowerSupplySparePartNumber cpqRackPowerSupplyFWRev cpqRackPowerSupplyMaxPwrOutput cpqRackPowerSupplyCurPwrOutput cpqRackPowerSupplyIntakeTemp cpqRackPowerSupplyExhaustTemp cpqRackPowerSupplyStatus cpqRackPowerSupplySupplyInputLineStatus cpqRackPowerSupplyPresent cpqRackPowerSupplyCondition)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+
+package HP::BladeSystem::Component::NetConnectorSubsystem;
+our @ISA = qw(HP::BladeSystem::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ net_connectors => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $oids = {
+ cpqRackNetConnectorEntry => '1.3.6.1.4.1.232.22.2.6.1.1.1',
+ cpqRackNetConnectorRack => '1.3.6.1.4.1.232.22.2.6.1.1.1.1',
+ cpqRackNetConnectorChassis => '1.3.6.1.4.1.232.22.2.6.1.1.1.2',
+ cpqRackNetConnectorIndex => '1.3.6.1.4.1.232.22.2.6.1.1.1.3',
+ cpqRackNetConnectorEnclosureName => '1.3.6.1.4.1.232.22.2.6.1.1.1.4',
+ cpqRackNetConnectorName => '1.3.6.1.4.1.232.22.2.6.1.1.1.5',
+ cpqRackNetConnectorModel => '1.3.6.1.4.1.232.22.2.6.1.1.1.6',
+ cpqRackNetConnectorSerialNum => '1.3.6.1.4.1.232.22.2.6.1.1.1.7',
+ cpqRackNetConnectorPartNumber => '1.3.6.1.4.1.232.22.2.6.1.1.1.8',
+ cpqRackNetConnectorSparePartNumber => '1.3.6.1.4.1.232.22.2.6.1.1.1.9',
+ cpqRackNetConnectorFWRev => '1.3.6.1.4.1.232.22.2.6.1.1.1.10',
+ cpqRackNetConnectorType => '1.3.6.1.4.1.232.22.2.6.1.1.1.11',
+ cpqRackNetConnectorLocation => '1.3.6.1.4.1.232.22.2.6.1.1.1.12',
+ cpqRackNetConnectorPresent => '1.3.6.1.4.1.232.22.2.6.1.1.1.13',
+ cpqRackNetConnectorHasFuses => '1.3.6.1.4.1.232.22.2.6.1.1.1.14',
+ cpqRackNetConnectorEnclosureSerialNum => '1.3.6.1.4.1.232.22.2.6.1.1.1.15',
+ cpqRackNetConnectorTypeValue => {
+ 0 => 'other', # undefined
+ 1 => 'other',
+ 2 => 'active',
+ 3 => 'passive',
+ },
+ cpqRackNetConnectorPresentValue => {
+ 1 => 'other',
+ 2 => 'absent',
+ 3 => 'present',
+ },
+ cpqRackNetConnectorHasFusesValue => {
+ -1 => 'false', # wird geliefert, also vermute ich false
+ 1 => 'false',
+ 2 => 'true',
+ },
+ };
+
+
+ # INDEX { cpqRackNetConnectorRack, cpqRackNetConnectorChassis, cpqRackNetConnectorIndex }
+ # dreckada dreck, dreckada
+ foreach ($self->get_entries($oids, 'cpqRackNetConnectorEntry')) {
+ push(@{$self->{net_connectors}},
+ HP::BladeSystem::Component::NetConnectorSubsystem::NetConnector->new(%{$_}));
+ }
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{net_connectors}}) {
+ $_->check() if $_->{cpqRackNetConnectorPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{net_connectors}}) {
+ $_->dump() if $_->{cpqRackNetConnectorPresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent nur bei -vvv
+ }
+}
+
+
+package HP::BladeSystem::Component::NetConnectorSubsystem::NetConnector;
+our @ISA = qw(HP::BladeSystem::Component::NetConnectorSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackNetConnector/, keys %params;
+ $self->{name} = $params{cpqRackNetConnectorRack}.
+ ':'.$params{cpqRackNetConnectorChassis}.
+ ':'.$params{cpqRackNetConnectorIndex};
+ $self->{serfw} = sprintf "Ser: %s, FW: %s", $self->{cpqRackNetConnectorSerialNum}, $self->{cpqRackNetConnectorFWRev};
+ bless $self, $class;
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('nc', $self->{name});
+ my $info = sprintf 'net connector %s is %s, model is %s (%s)',
+ $self->{name}.($self->{cpqRackNetConnectorName} ? ' \''.$self->{cpqRackNetConnectorName}.'\'' : ''),
+ $self->{cpqRackNetConnectorPresent}, $self->{cpqRackNetConnectorModel}, $self->{serfw};
+ $self->add_info($info);
+ # hat weder status noch condition, vielleicht spaeter mal
+ $info .= sprintf " (SparePartNum %s)", $self->{cpqRackNetConnectorSparePartNumber};
+}
+
+sub dump {
+ my $self = shift;
+ printf "[NET_CONNECTOR_%s]\n", $self->{cpqRackNetConnectorName};
+ foreach (qw(cpqRackNetConnectorRack cpqRackNetConnectorChassis cpqRackNetConnectorIndex cpqRackNetConnectorEnclosureName cpqRackNetConnectorName cpqRackNetConnectorModel cpqRackNetConnectorSerialNum cpqRackNetConnectorPartNumber cpqRackNetConnectorSparePartNumber cpqRackNetConnectorFWRev cpqRackNetConnectorType cpqRackNetConnectorLocation cpqRackNetConnectorPresent cpqRackNetConnectorHasFuses cpqRackNetConnectorEnclosureSerialNum)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+
+package HP::BladeSystem::Component::ServerBladeSubsystem;
+our @ISA = qw(HP::BladeSystem::Component);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ server_blades => [],
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub init {
+ my $self = shift;
+ my $oids = {
+ cpqRackServerBladeEntry => '1.3.6.1.4.1.232.22.2.4.1.1.1',
+ cpqRackServerBladeRack => '1.3.6.1.4.1.232.22.2.4.1.1.1.1',
+ cpqRackServerBladeChassis => '1.3.6.1.4.1.232.22.2.4.1.1.1.2',
+ cpqRackServerBladeIndex => '1.3.6.1.4.1.232.22.2.4.1.1.1.3',
+ cpqRackServerBladeName => '1.3.6.1.4.1.232.22.2.4.1.1.1.4',
+ cpqRackServerBladeEnclosureName => '1.3.6.1.4.1.232.22.2.4.1.1.1.5',
+ cpqRackServerBladePartNumber => '1.3.6.1.4.1.232.22.2.4.1.1.1.6',
+ cpqRackServerBladeSparePartNumber => '1.3.6.1.4.1.232.22.2.4.1.1.1.7',
+ cpqRackServerBladePosition => '1.3.6.1.4.1.232.22.2.4.1.1.1.8',
+ cpqRackServerBladeHeight => '1.3.6.1.4.1.232.22.2.4.1.1.1.9',
+ cpqRackServerBladeWidth => '1.3.6.1.4.1.232.22.2.4.1.1.1.10',
+ cpqRackServerBladeDepth => '1.3.6.1.4.1.232.22.2.4.1.1.1.11',
+ cpqRackServerBladePresent => '1.3.6.1.4.1.232.22.2.4.1.1.1.12',
+ cpqRackServerBladeHasFuses => '1.3.6.1.4.1.232.22.2.4.1.1.1.13',
+ cpqRackServerBladeEnclosureSerialNum => '1.3.6.1.4.1.232.22.2.4.1.1.1.14',
+ cpqRackServerBladeSlotsUsed => '1.3.6.1.4.1.232.22.2.4.1.1.1.15',
+ cpqRackServerBladeStatus => '1.3.6.1.4.1.232.22.2.4.1.1.1.21',
+ cpqRackServerBladeDiagnosticString => '1.3.6.1.4.1.232.22.2.4.1.1.1.24',
+ cpqRackServerBladePowered => '1.3.6.1.4.1.232.22.2.4.1.1.1.25',
+ cpqRackServerBladePOSTStatus => '1.3.6.1.4.1.232.22.2.4.1.1.1.35',
+ cpqRackServerBladePresentValue => {
+ 1 => 'other',
+ 2 => 'absent',
+ 3 => 'present',
+ },
+ cpqRackServerBladeStatusValue => {
+ 1 => 'other',
+ 2 => 'ok',
+ 3 => 'degraded',
+ 4 => 'failed',
+ },
+ cpqRackServerBladePoweredValue => {
+ 0 => 'aechz',
+ 1 => 'other',
+ 2 => 'on',
+ 3 => 'off',
+ 4 => 'powerStagedOff',
+ 5 => 'reboot',
+ },
+ cpqRackServerBladePOSTStatusValue => {
+ 1 => 'other',
+ 2 => 'started',
+ 3 => 'completed',
+ 4 => 'failed',
+ },
+ };
+
+
+ # INDEX { cpqRackServerBladeRack, cpqRackServerBladeChassis, cpqRackServerBladeIndex }
+ # dreckada dreck, dreckada
+ foreach ($self->get_entries($oids, 'cpqRackServerBladeEntry')) {
+ push(@{$self->{server_blades}},
+ HP::BladeSystem::Component::ServerBladeSubsystem::ServerBlade->new(%{$_}));
+ }
+}
+
+sub check {
+ my $self = shift;
+ foreach (@{$self->{server_blades}}) {
+ $_->check() if $_->{cpqRackServerBladePresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent blades nur bei -vvv
+ }
+}
+
+sub dump {
+ my $self = shift;
+ foreach (@{$self->{server_blades}}) {
+ $_->dump() if $_->{cpqRackServerBladePresent} eq 'present' ||
+ $self->{runtime}->{options}->{verbose} >= 3; # absent blades nur bei -vvv
+ }
+}
+
+
+package HP::BladeSystem::Component::ServerBladeSubsystem::ServerBlade;
+our @ISA = qw(HP::BladeSystem::Component::ServerBladeSubsystem);
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ rawdata => $params{rawdata},
+ method => $params{method},
+ blacklisted => 0,
+ info => undef,
+ extendedinfo => undef,
+ };
+ map { $self->{$_} = $params{$_} } grep /cpqRackServerBlade/, keys %params;
+ $self->{cpqRackServerBladeDiagnosticString} ||= '';
+ $self->{name} = $self->{cpqRackServerBladeRack}.
+ ':'.$self->{cpqRackServerBladeChassis}.
+ ':'.$self->{cpqRackServerBladeIndex};
+ bless $self, $class;
+ $self->init();
+ return $self;
+}
+
+sub check {
+ my $self = shift;
+ $self->blacklist('sb', $self->{name});
+ my $info = sprintf 'server blade %s \'%s\' is %s, status is %s, powered is %s',
+ $self->{name}, $self->{cpqRackServerBladeName}, $self->{cpqRackServerBladePresent},
+ $self->{cpqRackServerBladeStatus}, $self->{cpqRackServerBladePowered};
+ $self->add_info($info);
+ if ($self->{cpqRackServerBladePowered} eq 'on') {
+ if ($self->{cpqRackServerBladeCondition} eq 'degraded') {
+ $self->add_message(WARNING, sprintf 'server blade %s diag is \'%s\', post status is %s',
+ $self->{cpqRackServerBladeName}, $self->{cpqRackServerBladeDiagnosticString},
+ $self->{cpqRackServerBladePOSTStatus});
+ } elsif ($self->{cpqRackServerBladeCondition} eq 'failed') {
+ $self->add_message(CRITICAL, sprintf 'server blade %s diag is \'%s\', post status is %s',
+ $self->{cpqRackServerBladeName}, $self->{cpqRackServerBladeDiagnosticString},
+ $self->{cpqRackServerBladePOSTStatus});
+ }
+ }
+}
+
+sub dump {
+ my $self = shift;
+ printf "[SERVER_BLADE_%s]\n", $self->{cpqRackServerBladeName};
+ foreach (qw(cpqRackServerBladeRack cpqRackServerBladeChassis cpqRackServerBladeIndex cpqRackServerBladeName cpqRackServerBladeEnclosureName cpqRackServerBladePartNumber cpqRackServerBladeSparePartNumber cpqRackServerBladePosition cpqRackServerBladeHeight cpqRackServerBladeWidth cpqRackServerBladeDepth cpqRackServerBladePresent cpqRackServerBladeHasFuses cpqRackServerBladeEnclosureSerialNum cpqRackServerBladeSlotsUsed cpqRackServerBladeStatus cpqRackServerBladeDiagnosticString cpqRackServerBladePowered cpqRackServerBladePOSTStatus)) {
+ printf "%s: %s\n", $_, $self->{$_};
+ }
+ printf "\n";
+}
+
+
+
+package HP::BladeSystem::Component;
+
+use strict;
+
+our @ISA = qw(HP::BladeSystem);
+
+
+package HP::BladeSystem;
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+use Data::Dumper;
+
+our @ISA = qw(HP::Server HP::Proliant::Component::SNMP);
+
+sub init {
+ my $self = shift;
+ $self->{components} = {
+ common_enclosure_subsystem => undef,
+ power_enclosure_subsystem => undef,
+ power_supply_subsystem => undef,
+ net_connector_subsystem => undef,
+ server_blade_subsystem => undef,
+ };
+ $self->{serial} = 'unknown';
+ $self->{product} = 'unknown';
+ $self->{romversion} = 'unknown';
+ $self->trace(3, 'BladeSystem identified');
+ $self->collect();
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ $self->set_serial();
+ $self->analyze_common_enclosures();
+ $self->analyze_power_enclosures();
+ $self->analyze_power_supplies();
+ $self->analyze_net_connectors();
+ $self->analyze_server_blades();
+ $self->check_common_enclosures();
+ $self->check_power_enclosures();
+ $self->check_power_supplies();
+ $self->check_net_connectors();
+ $self->check_server_blades();
+ }
+}
+
+sub identify {
+ my $self = shift;
+ return sprintf "System: '%s', S/N: '%s'",
+ $self->{product}, $self->{serial};
+}
+
+sub dump {
+ my $self = shift;
+ printf STDERR "serial %s\n", $self->{serial};
+ printf STDERR "product %s\n", $self->{product};
+ printf STDERR "romversion %s\n", $self->{romversion};
+ printf STDERR "%s\n", Data::Dumper::Dumper($self->{enclosures});
+}
+
+sub analyze_common_enclosures {
+ my $self = shift;
+ $self->{components}->{common_enclosure_subsystem} =
+ HP::BladeSystem::Component::CommonEnclosureSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_power_enclosures {
+ my $self = shift;
+ $self->{components}->{power_enclosure_subsystem} =
+ HP::BladeSystem::Component::PowerEnclosureSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_power_supplies {
+ my $self = shift;
+ $self->{components}->{power_supply_subsystem} =
+ HP::BladeSystem::Component::PowerSupplySubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_net_connectors {
+ my $self = shift;
+ $self->{components}->{net_connector_subsystem} =
+ HP::BladeSystem::Component::NetConnectorSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_server_blades {
+ my $self = shift;
+ $self->{components}->{server_blade_subsystem} =
+ HP::BladeSystem::Component::ServerBladeSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub check_common_enclosures {
+ my $self = shift;
+ $self->{components}->{common_enclosure_subsystem}->check();
+ $self->{components}->{common_enclosure_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_power_enclosures {
+ my $self = shift;
+ $self->{components}->{power_enclosure_subsystem}->check();
+ $self->{components}->{power_enclosure_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_power_supplies {
+ my $self = shift;
+ $self->{components}->{power_supply_subsystem}->check();
+ $self->{components}->{power_supply_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_net_connectors {
+ my $self = shift;
+ $self->{components}->{net_connector_subsystem}->check();
+ $self->{components}->{net_connector_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_server_blades {
+ my $self = shift;
+ $self->{components}->{server_blade_subsystem}->check();
+ $self->{components}->{server_blade_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub collect {
+ my $self = shift;
+ if ($self->{runtime}->{plugin}->opts->snmpwalk) {
+ my $cpqRackMibCondition = '1.3.6.1.4.1.232.22.1.3.0';
+ $self->trace(3, 'getting cpqRackMibCondition');
+ if (! exists $self->{rawdata}->{$cpqRackMibCondition}) {
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no health data (cpqrack-mib)');
+ }
+ } else {
+ my $net_snmp_version = Net::SNMP->VERSION(); # 5.002000 or 6.000000
+ #$params{'-translate'} = [
+ # -all => 0x0
+ #];
+ my ($session, $error) =
+ Net::SNMP->session(%{$self->{runtime}->{snmpparams}});
+ if (! defined $session) {
+ $self->{plugin}->add_message(CRITICAL, 'cannot create session object');
+ $self->trace(1, Data::Dumper::Dumper($self->{runtime}->{snmpparams}));
+ } else {
+ # revMajor is often used for discovery of hp devices
+ my $cpqSeMibRev = '1.3.6.1.4.1.232.22.1';
+ my $cpqSeMibRevMajor = '1.3.6.1.4.1.232.22.1.1.0';
+ my $cpqRackMibCondition = '1.3.6.1.4.1.232.22.1.3.0';
+ $self->trace(3, 'getting cpqRackMibCondition');
+ my $result = $session->get_request(
+ -varbindlist => [$cpqRackMibCondition]
+ );
+ if (!defined($result) ||
+ $result->{$cpqRackMibCondition} eq 'noSuchInstance' ||
+ $result->{$cpqRackMibCondition} eq 'noSuchObject' ||
+ $result->{$cpqRackMibCondition} eq 'endOfMibView') {
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no health data (cpqrack-mib)');
+ $session->close;
+ } else {
+ $self->trace(3, 'getting cpqRackMibCondition done');
+ }
+ }
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ # snmp peer is alive
+ $self->trace(2, sprintf "Protocol is %s",
+ $self->{runtime}->{snmpparams}->{'-version'});
+ my $oidtrees = [
+ ["cpqSiComponent", "1.3.6.1.4.1.232.2.2"],
+ ["cpqSiAsset", "1.3.6.1.4.1.232.2.2.2"],
+ #["cpqRackInfo", "1.3.6.1.4.1.232.22"],
+ ['cpqRackCommonEnclosureEntry', '1.3.6.1.4.1.232.22.2.3.1.1.1'],
+ ['cpqRackCommonEnclosureTempEntry', '1.3.6.1.4.1.232.22.2.3.1.2.1'],
+ ['cpqRackCommonEnclosureFanEntry', '1.3.6.1.4.1.232.22.2.3.1.3.1'],
+ ['cpqRackCommonEnclosureFuseEntry', '1.3.6.1.4.1.232.22.2.3.1.4.1'],
+ ['cpqRackCommonEnclosureManagerEntry', '1.3.6.1.4.1.232.22.2.3.1.6.1'],
+ ['cpqRackPowerEnclosureEntry', '1.3.6.1.4.1.232.22.2.3.3.1.1'],
+ ['cpqRackServerBladeEntry', '1.3.6.1.4.1.232.22.2.4.1.1.1'],
+ ['cpqRackPowerSupplyEntry', '1.3.6.1.4.1.232.22.2.5.1.1.1'],
+ ['cpqRackNetConnectorEntry', '1.3.6.1.4.1.232.22.2.6.1.1.1'],
+ ['cpqRackMibCondition', '1.3.6.1.4.1.232.22.1.3.0'],
+ ];
+ my $cpqSiComponent = "1.3.6.1.4.1.232.2.2";
+ my $cpqSiAsset = "1.3.6.1.4.1.232.2.2.2";
+ my $cpqRackInfo = "1.3.6.1.4.1.232.22";
+ $session->translate;
+ my $response = {}; #break the walk up in smaller pieces
+ foreach my $subtree (@{$oidtrees}) {
+ my $tic = time; my $tac = $tic;
+ my $response0 = $session->get_table(
+ -maxrepetitions => 1,
+ -baseoid => $subtree->[1]);
+ if (scalar (keys %{$response0}) == 0) {
+ $self->trace(2, sprintf "maxrepetitions failed. fallback");
+ $response0 = $session->get_table(
+ -baseoid => $subtree->[1]);
+ }
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk %s (%d oids)",
+ $tac - $tic, $subtree->[0], scalar(keys %{$response0}));
+ map { $response->{$_} = $response0->{$_} } keys %{$response0};
+ }
+ $session->close;
+ map { $response->{$_} =~ s/^\s+//; $response->{$_} =~ s/\s+$//; }
+ keys %$response;
+ $self->{rawdata} = $response;
+ }
+ }
+ return $self->{runtime}->{plugin}->check_messages();
+}
+
+sub set_serial {
+ my $self = shift;
+
+ my $cpqSiSysSerialNum = "1.3.6.1.4.1.232.2.2.2.1.0";
+ my $cpqSiProductName = "1.3.6.1.4.1.232.2.2.4.2.0";
+
+ $self->{serial} =
+ SNMP::Utils::get_object($self->{rawdata}, $cpqSiSysSerialNum);
+ $self->{product} =
+ SNMP::Utils::get_object($self->{rawdata}, $cpqSiProductName);
+ $self->{serial} = $self->{serial};
+ $self->{product} = lc $self->{product};
+ $self->{romversion} = 'unknown';
+#####################################################################
+$self->{runtime}->{product} = $self->{product};
+}
+
+package HP::Storage;
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+use Data::Dumper;
+
+our @ISA = qw(HP::Server);
+
+sub init {
+ my $self = shift;
+ $self->{components} = {
+ powersupply_subsystem => undef,
+ fan_subsystem => undef,
+ temperature_subsystem => undef,
+ cpu_subsystem => undef,
+ memory_subsystem => undef,
+ disk_subsystem => undef,
+ sensor_subsystem => undef,
+ };
+ $self->{serial} = 'unknown';
+ $self->{product} = 'unknown';
+ $self->{romversion} = 'unknown';
+ $self->collect();
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ $self->set_serial();
+# $self->check_for_buggy_firmware();
+# $self->analyze_cpus();
+# $self->analyze_powersupplies();
+# $self->analyze_fan_subsystem();
+# $self->analyze_temperatures();
+# $self->analyze_memory_subsystem();
+ $self->analyze_disk_subsystem();
+## $self->analyze_sensor_subsystem();
+# $self->check_cpus();
+# $self->check_powersupplies();
+# $self->check_fan_subsystem();
+# $self->check_temperatures();
+# $self->check_memory_subsystem();
+ $self->check_disk_subsystem();
+## $self->check_sensor_subsystem();
+ }
+}
+
+sub identify {
+ my $self = shift;
+ return sprintf "System: '%s', S/N: '%s', ROM: '%s'",
+ $self->{product}, $self->{serial}, $self->{romversion};
+}
+
+sub check_for_buggy_firmware {
+ my $self = shift;
+ my @buggyfirmwares = (
+ "P24 12/11/2001",
+ "P24 11/15/2002",
+ "D13 06/03/2003",
+ "D13 09/15/2004",
+ "P20 12/17/2002"
+ );
+ $self->{runtime}->{options}->{buggy_firmware} =
+ grep /^$self->{romversion}/, @buggyfirmwares;
+}
+
+sub dump {
+ my $self = shift;
+ printf STDERR "serial %s\n", $self->{serial};
+ printf STDERR "product %s\n", $self->{product};
+ printf STDERR "romversion %s\n", $self->{romversion};
+ printf STDERR "%s\n", Data::Dumper::Dumper($self->{components});
+}
+
+sub analyze_powersupplies {
+ my $self = shift;
+ $self->{components}->{powersupply_subsystem} =
+ HP::Storage::Component::PowersupplySubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_fan_subsystem {
+ my $self = shift;
+ $self->{components}->{fan_subsystem} =
+ HP::Storage::Component::FanSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_temperatures {
+ my $self = shift;
+ $self->{components}->{temperature_subsystem} =
+ HP::Storage::Component::TemperatureSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_cpus {
+ my $self = shift;
+ $self->{components}->{cpu_subsystem} =
+ HP::Storage::Component::CpuSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_memory_subsystem {
+ my $self = shift;
+ $self->{components}->{memory_subsystem} =
+ HP::Storage::Component::MemorySubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_disk_subsystem {
+ my $self = shift;
+ $self->{components}->{disk_subsystem} =
+ HP::Proliant::Component::DiskSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub analyze_sensor_subsystem {
+ my $self = shift;
+ $self->{components}->{sensor_subsystem} =
+ HP::FCMGMT::Component::SensorSubsystem->new(
+ rawdata => $self->{rawdata},
+ method => $self->{method},
+ runtime => $self->{runtime},
+ );
+}
+
+sub check_cpus {
+ my $self = shift;
+ $self->{components}->{cpu_subsystem}->check();
+ $self->{components}->{cpu_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_powersupplies {
+ my $self = shift;
+ $self->{components}->{powersupply_subsystem}->check();
+ $self->{components}->{powersupply_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_fan_subsystem {
+ my $self = shift;
+ $self->{components}->{fan_subsystem}->check();
+ $self->{components}->{fan_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_temperatures {
+ my $self = shift;
+ $self->{components}->{temperature_subsystem}->check();
+ $self->{components}->{temperature_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_memory_subsystem {
+ my $self = shift;
+ $self->{components}->{memory_subsystem}->check();
+ $self->{components}->{memory_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 2;
+}
+
+sub check_disk_subsystem {
+ my $self = shift;
+ $self->{components}->{disk_subsystem}->check();
+ $self->{components}->{disk_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 1;
+}
+
+sub check_sensor_subsystem {
+ my $self = shift;
+ $self->{components}->{isensor_subsystem}->check();
+ $self->{components}->{sensor_subsystem}->dump()
+ if $self->{runtime}->{options}->{verbose} >= 1;
+}
+
+
+sub collect {
+ my $self = shift;
+ if ($self->{runtime}->{plugin}->opts->snmpwalk) {
+ my $cpqSeMibCondition = '1.3.6.1.4.1.232.6.1.3.0';
+ # rindsarsch!
+ $self->{rawdata}->{$cpqSeMibCondition} = 0;
+ if (! exists $self->{rawdata}->{$cpqSeMibCondition}) {
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no health data (cpqhlth-mib)');
+ }
+ } else {
+ my $net_snmp_version = Net::SNMP->VERSION(); # 5.002000 or 6.000000
+ #$params{'-translate'} = [
+ # -all => 0x0
+ #];
+ my ($session, $error) =
+ Net::SNMP->session(%{$self->{runtime}->{snmpparams}});
+ if (! defined $session) {
+ $self->{plugin}->add_message(CRITICAL, 'cannot create session object');
+ $self->trace(1, Data::Dumper::Dumper($self->{runtime}->{snmpparams}));
+ } else {
+ # revMajor is often used for discovery of hp devices
+ my $cpqSeMibRev = '1.3.6.1.4.1.232.6.1';
+ my $cpqSeMibRevMajor = '1.3.6.1.4.1.232.6.1.1.0';
+ my $cpqSeMibCondition = '1.3.6.1.4.1.232.6.1.3.0';
+ my $result = $session->get_request(
+ -varbindlist => [$cpqSeMibCondition]
+ );
+ # rindsarsch!
+ $result->{$cpqSeMibCondition} = 0;
+ if (!defined($result) ||
+ $result->{$cpqSeMibCondition} eq 'noSuchInstance' ||
+ $result->{$cpqSeMibCondition} eq 'noSuchObject' ||
+ $result->{$cpqSeMibCondition} eq 'endOfMibView') {
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no health data (cpqhlth-mib)');
+ $session->close;
+ } else {
+ # this is not reliable. many agents return 4=failed
+ #if ($result->{$cpqSeMibCondition} != 2) {
+ # $obstacle = "cmapeerstart";
+ #}
+ }
+ }
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ # snmp peer is alive
+ $self->trace(2, sprintf "Protocol is %s",
+ $self->{runtime}->{snmpparams}->{'-version'});
+ my $cpqSsSys = "1.3.6.1.4.1.232.8";
+ $session->translate;
+ my $response = {}; #break the walk up in smaller pieces
+ my $tic = time; my $tac = $tic;
+ my $response1 = $session->get_table(
+ -baseoid => $cpqSsSys);
+ $tac = time;
+ $self->trace(2, sprintf "%03d seconds for walk cpqSsSys (%d oids)",
+ $tac - $tic, scalar(keys %{$response1}));
+ $session->close;
+ map { $response->{$_} = $response1->{$_} } keys %{$response1};
+ map { $response->{$_} =~ s/^\s+//; $response->{$_} =~ s/\s+$//; }
+ keys %$response;
+ $self->{rawdata} = $response;
+ }
+ }
+ return $self->{runtime}->{plugin}->check_messages();
+}
+
+sub set_serial {
+ my $self = shift;
+ my $snmpwalk = $self->{rawdata};
+ my @serials = ();
+ my @models = ();
+ my @fws = ();
+ my $cpqSsBackplaneEntry = '1.3.6.1.4.1.232.8.2.2.6.1';
+ my $cpqSsBackplaneFWRev = '1.3.6.1.4.1.232.8.2.2.6.1.3';
+ my $cpqSsBackplaneModel = '1.3.6.1.4.1.232.8.2.2.6.1.9';
+ my $cpqSsBackplaneSerialNumber = '1.3.6.1.4.1.232.8.2.2.6.1.13';
+ # INDEX { cpqSsBackplaneChassisIndex, cpqSsBackplaneIndex }
+ my @indexes = SNMP::Utils::get_indices($snmpwalk,
+ $cpqSsBackplaneEntry);
+ foreach (@indexes) {
+ my($idx1, $idx2) = ($_->[0], $_->[1]);
+ my $fw = SNMP::Utils::get_object($snmpwalk,
+ $cpqSsBackplaneFWRev, $idx1, $idx2);
+ my $model = SNMP::Utils::get_object($snmpwalk,
+ $cpqSsBackplaneModel, $idx1, $idx2);
+ my $serial = SNMP::Utils::get_object($snmpwalk,
+ $cpqSsBackplaneSerialNumber, $idx1, $idx2);
+ push(@serials, $serial);
+ push(@models, $model);
+ push(@fws, $fw);
+ }
+
+ $self->{serial} = join('/', @serials);
+ $self->{product} = join('/', @models);
+ $self->{romversion} = join('/', @fws);
+ $self->{runtime}->{product} = $self->{product};
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+package HP::Server;
+
+use strict;
+use constant { OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 };
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ runtime => $params{runtime},
+ productname => 'unknown',
+ };
+ bless $self, $class;
+ if (! ($self->{runtime}->{plugin}->opts->hostname ||
+ $self->{runtime}->{plugin}->opts->snmpwalk)) {
+ bless $self, 'HP::Proliant::CLI';
+ $self->{method} = 'cli';
+ } else {
+ $self->check_snmp_and_model();
+ if ($self->{runtime}->{options}->{servertype}) {
+ $self->{productname} = 'ProLiant' if
+ $self->{runtime}->{options}->{servertype} eq 'proliant';
+ $self->{productname} = 'BladeSystem' if
+ $self->{runtime}->{options}->{servertype} eq 'bladesystem';
+ $self->{productname} = 'Storage' if
+ $self->{runtime}->{options}->{servertype} eq 'storage';
+ }
+ if (! $self->{runtime}->{plugin}->check_messages()) {
+ if ($self->{productname} =~ /ProLiant/) {
+ bless $self, 'HP::Proliant::SNMP';
+ $self->trace(3, 'using HP::Proliant::SNMP');
+ } elsif ($self->{productname} =~ /^DL\d+\s*G\d+/) {
+ bless $self, 'HP::Proliant::SNMP';
+ $self->trace(3, 'using HP::Proliant::SNMP');
+ } elsif ($self->{productname} =~ /OpenView .* appliance/) {
+ bless $self, 'HP::Proliant::SNMP';
+ $self->trace(3, 'using HP::Proliant::SNMP');
+ } elsif ($self->{productname} =~ /BladeSystem/) {
+ bless $self, 'HP::BladeSystem';
+ $self->trace(3, 'using HP::BladeSystem');
+ } elsif ($self->{productname} =~ /PROLIANT 4LEE/) {
+ bless $self, 'HP::Storage';
+ $self->trace(3, 'using HP::Storage');
+ } elsif ($self->{productname} =~ /X\d+[\s\w]* Network Storage/) {
+ # HP X1600 Network Storage System
+ # HP X1600 G2 Network Storage System
+ bless $self, 'HP::Proliant::SNMP';
+ $self->trace(3, 'using HP::Proliant::SNMP');
+ } elsif ($self->{productname} =~ /Storage/) { # fake
+ bless $self, 'HP::Storage';
+ $self->trace(3, 'using HP::Storage');
+ } else {
+ $self->add_message(CRITICAL,
+ sprintf('unknown device%s', $self->{productname} eq 'unknown' ?
+ '' : '('.$self->{productname}.')'));
+ }
+ $self->{method} = 'snmp';
+ }
+ }
+ if ($self->{runtime}->{options}->{blacklist} &&
+ -f $self->{runtime}->{options}->{blacklist}) {
+ $self->{runtime}->{options}->{blacklist} = do {
+ local (@ARGV, $/) = $self->{runtime}->{options}->{blacklist}; <> };
+ }
+ return $self;
+}
+
+sub check_snmp_and_model {
+# uptime pruefen
+# dann whoami
+ my $self = shift;
+ if ($self->{runtime}->{plugin}->opts->snmpwalk) {
+ my $response = {};
+ if (! -f $self->{runtime}->{plugin}->opts->snmpwalk) {
+ $self->{runtime}->{plugin}->add_message(CRITICAL,
+ sprintf 'file %s not found',
+ $self->{runtime}->{plugin}->opts->snmpwalk);
+ } elsif (-x $self->{runtime}->{plugin}->opts->snmpwalk) {
+ my $cmd = sprintf "%s -On -v%s -c%s %s 1.3.6.1.4.1.232 2>&1",
+ $self->{runtime}->{plugin}->opts->snmpwalk,
+ $self->{runtime}->{plugin}->opts->protocol,
+ $self->{runtime}->{plugin}->opts->community,
+ $self->{runtime}->{plugin}->opts->hostname;
+ open(WALK, "$cmd |");
+ while (<WALK>) {
+ if (/^.*?\.(232\.[\d\.]+) = .*?: (\-*\d+)/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ } elsif (/^.*?\.(232\.[\d\.]+) = .*?: "(.*?)"/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $response->{'1.3.6.1.4.1.'.$1} =~ s/\s+$//;
+ }
+ }
+ close WALK;
+ } else {
+ open(MESS, $self->{runtime}->{plugin}->opts->snmpwalk);
+ my $in_string = 0;
+ my $in_hex_string = 0;
+ my $hex_oid = 0;
+ while(<MESS>) {
+ chomp;
+ if ($in_hex_string && /^(([0-9a-fA-F]{2})( [0-9a-fA-F]{2})*)\s*$/) {
+ $response->{$hex_oid} .= " ".$1;
+ } elsif ($in_string) {
+ if (/(.*)"$/) {
+ $response->{$hex_oid} .= $1;
+ $in_string = 0;
+ } else {
+ $response->{$hex_oid} .= $_;
+ }
+ } elsif (/^.*?\.(232\.[\d\.]+) = .*?: (\-*\d+)\s*$/) {
+ # SNMPv2-SMI::enterprises.232.6.2.6.7.1.3.1.4 = INTEGER: 6
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $in_hex_string = 0;
+ } elsif (/^.*?\.(232\.[\d\.]+) = .*?: "(.*?)"/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $response->{'1.3.6.1.4.1.'.$1} =~ s/\s+$//;
+ $in_hex_string = 0;
+ } elsif (/^.*?\.(232\.[\d\.]+) = (\-*\d+)/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $in_hex_string = 0;
+ } elsif (/^.*?\.(232\.[\d\.]+) = "(.*?)"/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $response->{'1.3.6.1.4.1.'.$1} =~ s/\s+$//;
+ $in_hex_string = 0;
+ } elsif (/^.*?\.(232\.[\d\.]+) = STRING: "(.*?[^"])$/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $response->{'1.3.6.1.4.1.'.$1} =~ s/\s+$//;
+ $in_string = 0;
+ $in_hex_string = 0;
+ } elsif (/^.*?\.(232\.[\d\.]+) = Hex-STRING: (.*)/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $in_hex_string = 1;
+ $hex_oid = '1.3.6.1.4.1.'.$1;
+ } elsif (/^.*?\.(232\.[\d\.]+) =[ ]{1,2}Hex: (.*)/) {
+ $response->{'1.3.6.1.4.1.'.$1} = $2;
+ $in_hex_string = 1;
+ $hex_oid = '1.3.6.1.4.1.'.$1;
+ }
+ }
+ close MESS;
+ }
+ map { $response->{$_} =~ s/^\s+//; $response->{$_} =~ s/\s+$//; }
+ keys %$response;
+ $self->{rawdata} = $response;
+ $self->whoami();
+ } else {
+ if (eval "require Net::SNMP") {
+ my %params = ();
+ my $net_snmp_version = Net::SNMP->VERSION(); # 5.002000 or 6.000000
+ #$params{'-translate'} = [
+ # -all => 0x0
+ #];
+ $params{'-hostname'} = $self->{runtime}->{plugin}->opts->hostname;
+ $params{'-version'} = $self->{runtime}->{plugin}->opts->protocol;
+ if ($self->{runtime}->{plugin}->opts->port) {
+ $params{'-port'} = $self->{runtime}->{plugin}->opts->port;
+ }
+ if ($self->{runtime}->{plugin}->opts->protocol eq '3') {
+ $params{'-username'} = $self->{runtime}->{plugin}->opts->username;
+ if ($self->{runtime}->{plugin}->opts->authpassword) {
+ $params{'-authpassword'} = $self->{runtime}->{plugin}->opts->authpassword;
+ }
+ if ($self->{runtime}->{plugin}->opts->authprotocol) {
+ $params{'-authprotocol'} = $self->{runtime}->{plugin}->opts->authprotocol;
+ }
+ if ($self->{runtime}->{plugin}->opts->privpassword) {
+ $params{'-privpassword'} = $self->{runtime}->{plugin}->opts->privpassword;
+ }
+ if ($self->{runtime}->{plugin}->opts->privprotocol) {
+ $params{'-privprotocol'} = $self->{runtime}->{plugin}->opts->privprotocol;
+ }
+ } else {
+ $params{'-community'} = $self->{runtime}->{plugin}->opts->community;
+ }
+ $self->{runtime}->{snmpparams} = \%params;
+ my ($session, $error) = Net::SNMP->session(%params);
+ $self->{session} = $session;
+ if (! defined $session) {
+ $self->add_message(CRITICAL, 'cannot create session object (maybe wrong hostname)');
+ $self->trace(1, Data::Dumper::Dumper(\%params));
+ } else {
+ my $sysUpTime = '1.3.6.1.2.1.1.3.0';
+ my $result = $session->get_request(
+ -varbindlist => [$sysUpTime]
+ );
+ if (!defined($result)) {
+ $self->add_message(CRITICAL,
+ 'could not contact snmp agent');
+ $session->close;
+ } else {
+ $self->trace(3, 'snmp agent answered');
+ $self->whoami();
+ }
+ }
+ } else {
+ $self->add_message(CRITICAL,
+ 'could not find Net::SNMP module');
+ }
+ }
+}
+
+sub whoami {
+ my $self = shift;
+ my $productname = undef;
+ if ($self->{runtime}->{plugin}->opts->snmpwalk) {
+ my $cpqSiProductName = '1.3.6.1.4.1.232.2.2.4.2.0';
+ my $cpqSsMibRevMajor = '1.3.6.1.4.1.232.8.1.1.0';
+ my $cpqSsBackplaneModel = '1.3.6.1.4.1.232.8.2.2.6.1.9'.'.1.1';
+ if ($productname = $self->{rawdata}->{$cpqSiProductName}) {
+ if (! $productname) {
+ $self->{productname} = 'ProLiant';
+ } else {
+ $self->{productname} = $self->{rawdata}->{$cpqSiProductName};
+ }
+ } elsif (exists $self->{rawdata}->{$cpqSsBackplaneModel}) {
+ $self->{productname} = $self->{rawdata}->{$cpqSsBackplaneModel};
+ } elsif (exists $self->{rawdata}->{$cpqSsMibRevMajor}) {
+ # at least there is a CPQSTSYS-MIB
+ $self->{productname} = 'Storage'
+ } else {
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no product name (cpqsinfo-mib)');
+ }
+ } else {
+ my $cpqSiProductName = '1.3.6.1.4.1.232.2.2.4.2.0';
+ my $cpqSsMibRevMajor = '1.3.6.1.4.1.232.8.1.1.0';
+ my $cpqSsBackplaneModel = '1.3.6.1.4.1.232.8.2.2.6.1.9'.'.1.1';
+ my $dummy = '1.3.6.1.2.1.1.5.0';
+ if ($productname = $self->valid_response($cpqSiProductName)) {
+ if ($productname eq '') {
+ $self->{productname} = 'ProLiant';
+ } else {
+ $self->{productname} = $productname;
+ }
+ } elsif ($productname = $self->valid_response($cpqSsBackplaneModel)) {
+ $self->{productname} = $productname;
+ } elsif ($self->valid_response($cpqSsMibRevMajor)) {
+ # at least there is a CPQSTSYS-MIB
+ $self->{productname} = 'Storage'
+ } else {
+ $self->add_message(CRITICAL,
+ 'snmpwalk returns no product name (cpqsinfo-mib)');
+ $self->{session}->close;
+ }
+ $self->trace(3, 'whoami: '.$self->{productname});
+ }
+}
+
+sub valid_response {
+ my $self = shift;
+ my $oid = shift;
+ my $result = $self->{session}->get_request(
+ -varbindlist => [$oid]
+ );
+ if (!defined($result) ||
+ ! defined $result->{$oid} ||
+ $result->{$oid} eq 'noSuchInstance' ||
+ $result->{$oid} eq 'noSuchObject' ||
+ $result->{$oid} eq 'endOfMibView') {
+ return undef;
+ } else {
+ return $result->{$oid};
+ }
+}
+
+sub trace {
+ my $self = shift;
+ my $level = shift;
+ my $message = shift;
+ if ($self->{runtime}->{options}->{verbose} >= $level) {
+ printf "%s\n", $message;
+ }
+}
+
+sub blacklist {
+ my $self = shift;
+ my $type = shift;
+ my $name = shift;
+ $self->{blacklisted} = $self->is_blacklisted($type, $name);
+}
+
+sub add_blacklist {
+ my $self = shift;
+ my $list = shift;
+ $self->{runtime}->{options}->{blacklist} = join('/',
+ (split('/', $self->{runtime}->{options}->{blacklist}), $list));
+}
+
+sub is_blacklisted {
+ my $self = shift;
+ my $type = shift;
+ my $name = shift;
+ my $blacklisted = 0;
+# $name =~ s/\:/-/g;
+ foreach my $bl_items (split(/\//, $self->{runtime}->{options}->{blacklist})) {
+ if ($bl_items =~ /^(\w+):([\:\d\-,]+)$/) {
+ my $bl_type = $1;
+ my $bl_names = $2;
+ foreach my $bl_name (split(/,/, $bl_names)) {
+ if ($bl_type eq $type && $bl_name eq $name) {
+ $blacklisted = 1;
+ }
+ }
+ } elsif ($bl_items =~ /^(\w+)$/) {
+ my $bl_type = $1;
+ if ($bl_type eq $type) {
+ $blacklisted = 1;
+ }
+ }
+ }
+ return $blacklisted;
+}
+
+sub add_message {
+ my $self = shift;
+ my $level = shift;
+ my $message = shift;
+ $self->{runtime}->{plugin}->add_message($level, $message)
+ unless $self->{blacklisted};
+ if (exists $self->{failed}) {
+ if ($level == UNKNOWN && $self->{failed} == OK) {
+ $self->{failed} = $level;
+ } elsif ($level > $self->{failed}) {
+ $self->{failed} = $level;
+ }
+ }
+}
+
+sub remove_message {
+ my $self = shift;
+ my $level = shift;
+ my $message = shift;
+ $self->{runtime}->{plugin}->remove_message($level) ;
+}
+
+sub has_failed {
+ my $self = shift;
+ return $self->{failed};
+}
+
+sub add_info {
+ my $self = shift;
+ my $info = shift;
+ $info = $self->{blacklisted} ? $info.' (blacklisted)' : $info;
+ $self->{info} = $info;
+ if (! exists $self->{runtime}->{plugin}->{info}) {
+ $self->{runtime}->{plugin}->{info} = [];
+ }
+ push(@{$self->{runtime}->{plugin}->{info}}, $info);
+}
+
+sub annotate_info {
+ my $self = shift;
+ my $annotation = shift;
+ my $lastinfo = pop(@{$self->{runtime}->{plugin}->{info}});
+ $lastinfo .= sprintf ' (%s)', $annotation;
+ push(@{$self->{runtime}->{plugin}->{info}}, $lastinfo);
+}
+
+sub add_extendedinfo {
+ my $self = shift;
+ my $info = shift;
+ $self->{extendedinfo} = $info;
+ return if ! $self->{runtime}->{options}->{extendedinfo};
+ if (! exists $self->{runtime}->{plugin}->{extendedinfo}) {
+ $self->{runtime}->{plugin}->{extendedinfo} = [];
+ }
+ push(@{$self->{runtime}->{plugin}->{extendedinfo}}, $info);
+}
+
+sub get_extendedinfo {
+ my $self = shift;
+ if (! exists $self->{runtime}->{plugin}->{extendedinfo}) {
+ $self->{runtime}->{plugin}->{extendedinfo} = [];
+ }
+ return join(' ', @{$self->{runtime}->{plugin}->{extendedinfo}});
+}
+
+sub add_summary {
+ my $self = shift;
+ my $summary = shift;
+ if (! exists $self->{runtime}->{plugin}->{summary}) {
+ $self->{runtime}->{plugin}->{summary} = [];
+ }
+ push(@{$self->{runtime}->{plugin}->{summary}}, $summary);
+}
+
+sub get_summary {
+ my $self = shift;
+ if (! exists $self->{runtime}->{plugin}->{summary}) {
+ $self->{runtime}->{plugin}->{summary} = [];
+ }
+ return join(', ', @{$self->{runtime}->{plugin}->{summary}});
+}
+
+sub dumper {
+ my $self = shift;
+ my $object = shift;
+ my $run = $object->{runtime};
+ delete $object->{runtime};
+ printf STDERR "%s\n", Data::Dumper::Dumper($object);
+ $object->{runtime} = $run;
+}
+package main;
+#! /usr/bin/perl
+
+use strict;
+
+my $CELSIUS = 1;
+my $PERFDATA = 1;
+my $EXTENDEDINFO = 1;
+my $HWINFO = 1;
+my $HPACUCLI = 0;
+my $NOINSTLEVEL = 'unknown';
+
+use constant OK => 0;
+use constant WARNING => 1;
+use constant CRITICAL => 2;
+use constant UNKNOWN => 3;
+use constant DEPENDENT => 4;
+
+my $plugin = Nagios::MiniPlugin->new(
+ shortname => '',
+ usage => 'Usage: %s [ -v|--verbose ] [ -t <timeout> ] '.
+ '--hostname <proliant> --community <snmp-community>'.
+ ' ...]',
+ version => '4.5.2',
+ blurb => 'This plugin checks the hardware of hp/compaq proliant servers',
+ url => 'http://labs.consol.de/nagios/check_hpasm',
+ timeout => 60,
+ shortname => '',
+);
+$plugin->add_arg(
+ spec => 'blacklist|b=s',
+ help => '--blacklist
+ Blacklist some (missing/failed) components',
+ required => 0,
+ default => '',
+);
+$plugin->add_arg(
+ spec => 'ignore-dimms|i',
+ help => '--ignore-dimms
+ Ignore "N/A"-DIMM status on misc. servers (e.g. older DL320)',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'ignore-fan-redundancy',
+ help => '--ignore-fan-redundancy
+ Ignore missing redundancy partners',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'customthresholds|c=s',
+ help => '--customthresholds
+ Use custom thresholds for certain temperatures',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'eventrange=s',
+ help => '--eventrange=<warningrange>/<criticalrange>
+ Period of time before critical IML events respecively become warnings or vanish
+ A range is descibed as a number and a unit (s, m, h, d), e.g. --eventrange 1h/20m',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'perfdata=s',
+ help => '--perfdata=[short]
+ Output performance data. If your performance data string becomes
+ too long and is truncated by Nagios, then you can use --perfdata=short
+ instead. This will output temperature tags without location information',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'hostname|H=s',
+ help => '--hostname
+ Hostname or IP-address of the server (SNMP mode only)',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'port=i',
+ help => '--port
+ The SNMP port to use (default: 161)',
+ required => 0,
+ default => 161,
+);
+$plugin->add_arg(
+ spec => 'protocol|P=s',
+ help => '--protocol
+ The SNMP protocol to use (default: 2c, other possibilities: 1,3)',
+ required => 0,
+ default => '2c',
+);
+$plugin->add_arg(
+ spec => 'community|C=s',
+ help => '--community
+ SNMP community of the server (SNMP v1/2 only)',
+ required => 0,
+ default => 'public',
+);
+$plugin->add_arg(
+ spec => 'username=s',
+ help => '--username
+ The securityName for the USM security model (SNMPv3 only)',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'authpassword=s',
+ help => '--authpassword
+ The authentication password for SNMPv3',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'authprotocol=s',
+ help => '--authprotocol
+ The authentication protocol for SNMPv3 (md5|sha)',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'privpassword=s',
+ help => '--privpassword
+ The password for authPriv security level',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'privprotocol=s',
+ help => '--privprotocol
+ The private protocol for SNMPv3 (des|aes|aes128|3des|3desde)',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'snmpwalk=s',
+ help => '--snmpwalk
+ A file with the output of snmpwalk 1.3.6.1.4.1.232',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'hpasmcli=s',
+ help => '--hpasmcli
+ A file with the output of hpasmcli',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'servertype=s',
+ help => '--servertype
+ The type of the server: proliant (default) or bladesystem',
+ required => 0,
+);
+$plugin->add_arg(
+ spec => 'eval-nics',
+ help => '--eval-nics
+ Check network interfaces (and groups). Try it and report me whyt you think about it. I need to build up some know how on this subject. If get an error and you think, it is not justified for your configuration, please tell me about it. (alwasy send the output of "snmpwalk -On .... 1.3.6.1.4.1.232" and a description how you setup your nics and why it is correct opposed to the plugins error message',
+ required => 0,
+);
+
+$plugin->getopts();
+if (! $PERFDATA && $plugin->opts->get('perfdata')) {
+ $PERFDATA = 1;
+}
+if ($PERFDATA && $plugin->opts->get('perfdata') &&
+ ($plugin->opts->get('perfdata') eq 'short')) {
+ $PERFDATA = 2;
+}
+$plugin->{messages}->{unknown} = []; # wg. add_message(UNKNOWN,...)
+
+$plugin->{info} = []; # gefrickel
+
+$SIG{'ALRM'} = sub {
+ printf "UNKNOWN - check_hpasm timed out after %d seconds\n",
+ $plugin->opts->get('timeout');
+ exit $ERRORS{UNKNOWN};
+};
+alarm($plugin->opts->get('timeout'));
+
+my $server = HP::Server->new( runtime => {
+ plugin => $plugin,
+ options => {
+ servertype => $plugin->opts->get('servertype'),
+ verbose => $plugin->opts->get('verbose'),
+ scrapiron => 0,
+ ignore_fan_redundancy => $plugin->opts->get('ignore-fan-redundancy'),
+ ignore_dimms => $plugin->opts->get('ignore-dimms'),
+ customthresholds => $plugin->opts->get('customthresholds'),
+ eventrange => $plugin->opts->get('eventrange'),
+ blacklist => $plugin->opts->get('blacklist'),
+ celsius => $CELSIUS,
+ perfdata => $PERFDATA,
+ extendedinfo => $EXTENDEDINFO,
+ hwinfo => $HWINFO,
+ hpacucli => $HPACUCLI,
+ noinstlevel => $NOINSTLEVEL,
+ },
+},);
+if (! $plugin->check_messages()) {
+ $server->init();
+ $plugin->add_message(OK, $server->identify()) if $HWINFO;
+ if (! $plugin->check_messages()) {
+ $plugin->add_message(OK, 'hardware working fine');
+ $plugin->add_message(OK, $server->get_summary())
+ if $server->get_summary();
+ $plugin->add_message(OK, $server->get_extendedinfo())
+ if $server->get_extendedinfo();
+ }
+} else {
+ $plugin->add_message(CRITICAL, 'wrong device');
+}
+
+my ($code, $message) = $plugin->check_messages(join => ', ', join_all => ', ');
+$message .= sprintf "\n%s\n", join("\n", @{$plugin->{info}})
+ if $plugin->opts->get('verbose') >= 1;
+#printf "%s\n", Data::Dumper::Dumper($plugin->{info});
+$plugin->nagios_exit($code, $message);
+