#! /usr/bin/perl -w 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 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=[
[@]]\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::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 => [], 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::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 => [], 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 => [], 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", 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->{powersupplies}}, # HP::Proliant::Component::PowersupplySubsystem::Powersupply->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}); } 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->init(%params); return $self; } 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(%{$_})); } } 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; 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}, ); } } } 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. 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 $self->update_si_with_si(); return; } 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::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 (/Controller Status: (\w+)/) { $tmpcntl->{$slot}->{cpqDaCntlrBoardCondition} = lc $1; $tmpcntl->{$slot}->{cpqDaCntlrCondition} = lc $1; } elsif (/Cache Status: (\w+)/) { $tmpaccel->{$slot}->{cpqDaAccelCntlrIndex} = $cntlindex; $tmpaccel->{$slot}->{cpqDaAccelSlot} = $slot; $tmpaccel->{$slot}->{cpqDaAccelCondition} = lc $1; $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 (/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) 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}; $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}->{$_}; } } } 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 =~ /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}); 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} 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}); } foreach (@{$self->{accelerators}}) { $_->check(); } foreach (@{$self->{logical_drives}}) { $_->check(); } foreach (@{$self->{physical_drives}}) { $_->check(); } foreach (@{$self->{spare_drives}}) { $_->check(); } } 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, }; $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") { $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} ne "ok") { # (other) failed degraded $self->add_message(CRITICAL, "controller accelerator battery needs attention"); } } 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; 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; 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; 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}, cpqScsiCntlrIndex => $params{cpqScsiCntlrIndex}, cpqScsiCntlrBusIndex => $params{cpqScsiCntlrBusIndex}, cpqScsiCntlrSlot => $params{cpqScsiCntlrSlot}, cpqScsiCntlrStatus => $params{cpqScsiCntlrStatus}, cpqScsiCntlrCondition => $params{cpqScsiCntlrCondition}, cpqScsiCntlrHwLocation => $params{cpqScsiCntlrHwLocation}, blacklisted => 0, }; $self->{name} = $params{name} || $self->{cpqScsiCntlrIndex}; $self->{controllerindex} = $self->{cpqScsiCntlrIndex}; bless $self, $class; return $self; } sub check { my $self = shift; if ($self->{cpqScsiCntlrCondition} eq 'other') { if (scalar(@{$self->{physical_drives}})) { $self->add_message(CRITICAL, sprintf 'scsi controller in slot %s needs attention', $self->{cpqScsiCntlrSlot}); $self->add_info(sprintf 'scsi controller in slot %s needs attention', $self->{cpqScsiCntlrSlot}); } else { $self->add_info(sprintf 'scsi controller in slot %s is ok and unused', $self->{cpqScsiCntlrSlot}); $self->{blacklisted} = 1; } } elsif ($self->{cpqScsiCntlrCondition} ne 'ok') { $self->add_message(CRITICAL, sprintf 'scsi controller in slot %s needs attention', $self->{cpqScsiCntlrSlot}); $self->add_info(sprintf 'scsi controller in slot %s needs attention', $self->{cpqScsiCntlrSlot}); } else { $self->add_info(sprintf 'scsi controller in slot %s is ok', $self->{cpqScsiCntlrSlot}); } 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}, cpqScsiLogDrvCntlrIndex => $params{cpqScsiLogDrvCntlrIndex}, cpqScsiLogDrvBusIndex => $params{cpqScsiLogDrvBusIndex}, cpqScsiLogDrvIndex => $params{cpqScsiLogDrvIndex}, cpqScsiLogDrvFaultTol => $params{cpqScsiLogDrvFaultTol}, cpqScsiLogDrvStatus => $params{cpqScsiLogDrvStatus}, cpqScsiLogDrvSize => $params{cpqScsiLogDrvSize}, cpqScsiLogDrvPhyDrvIDs => $params{cpqScsiLogDrvPhyDrvIDs}, cpqScsiLogDrvCondition => $params{cpqScsiLogDrvCondition}, blacklisted => 0, }; bless $self, $class; $self->{name} = $params{name} || $self->{cpqScsiLogDrvCntlrIndex}.':'. $self->{cpqScsiLogDrvBusIndex}.':'. $self->{cpqScsiLogDrvIndex}; ####vorerst $self->{controllerindex} = $self->{cpqScsiLogDrvCntlrIndex}; return $self; } sub check { my $self = shift; if ($self->{cpqScsiLogDrvCondition} ne "ok") { if ($self->{cpqScsiLogDrvStatus} =~ /rebuild|recovering/) { $self->add_message(WARNING, sprintf "logical drive %s is %s", $self->{name}, $self->{cpqScsiLogDrvStatus}); } else { $self->add_message(CRITICAL, sprintf "logical drive %s is %s", $self->{name}, $self->{cpqScsiLogDrvStatus}); } } $self->add_info( sprintf "logical drive %s is %s", $self->{name}, $self->{cpqScsiLogDrvStatus}); } sub dump { my $self = shift; printf "[LOGICAL_DRIVE]\n"; 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}, cpqScsiPhyDrvCntlrIndex => $params{cpqScsiPhyDrvCntlrIndex}, cpqScsiPhyDrvBusIndex => $params{cpqScsiPhyDrvBusIndex}, cpqScsiPhyDrvIndex => $params{cpqScsiPhyDrvIndex}, cpqScsiPhyDrvStatus => $params{cpqScsiPhyDrvStatus}, cpqScsiPhyDrvSize => $params{cpqScsiPhyDrvSize}, cpqScsiPhyDrvCondition => $params{cpqScsiPhyDrvCondition}, blacklisted => 0, }; $self->{name} = $params{name} || $self->{cpqScsiPhyDrvCntlrIndex}.':'.$self->{cpqScsiPhyDrvIndex}; $self->{controllerindex} = $self->{cpqScsiPhyDrvCntlrIndex}; bless $self, $class; return $self; } sub check { my $self = shift; if ($self->{cpqScsiPhyDrvCondition} ne 'ok') { $self->add_message(CRITICAL, sprintf "physical drive %s is %s", $self->{name}, $self->{cpqScsiPhyDrvCondition}); } $self->add_info( sprintf "physical drive %s is %s", $self->{name}, $self->{cpqScsiPhyDrvCondition}); } sub dump { my $self = shift; printf "[PHYSICAL_DRIVE]\n"; 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}, cpqFcaHostCntlrIndex => $params{cpqFcaHostCntlrIndex}, cpqFcaHostCntlrSlot => $params{cpqFcaHostCntlrSlot}, cpqFcaHostCntlrModel => $params{cpqFcaHostCntlrModel}, cpqFcaHostCntlrStatus => $params{cpqFcaHostCntlrStatus}, cpqFcaHostCntlrCondition => $params{cpqFcaHostCntlrCondition}, cpqFcaHostCntlrOverallCondition => $params{cpqFcaHostCntlrOverallCondition}, blacklisted => 0, }; $self->{name} = $params{name} || $self->{cpqFcaHostCntlrIndex}; $self->{controllerindex} = $self->{cpqFcaHostCntlrIndex}; $self->{ident} = sprintf '%s in slot %s', $self->{cpqFcaHostCntlrIndex}, $self->{cpqFcaHostCntlrSlot}; bless $self, $class; return $self; } sub check { my $self = shift; if ($self->is_blacklisted('fcahc', $self->{cpqFcaHostCntlrSlot}.'-'.$self->{cpqFcaHostCntlrIndex})) { $self->add_info(sprintf 'fcal host controller %s is %s (blacklisted)', $self->{ident}, $self->{cpqFcaHostCntlrCondition}); } elsif ($self->{cpqFcaHostCntlrCondition} eq 'other') { $self->add_message(CRITICAL, sprintf 'fcal host controller %s needs attention (%s)', $self->{ident}, $self->{cpqFcaHostCntlrStatus}); $self->add_info(sprintf 'fcal host controller %s needs attention (%s)', $self->{ident}, $self->{cpqFcaHostCntlrStatus}); } elsif ($self->{cpqFcaHostCntlrCondition} ne 'ok') { $self->add_message(CRITICAL, sprintf 'fcal host controller %s needs attention (%s)', $self->{ident}, $self->{cpqFcaHostCntlrStatus}); $self->add_info(sprintf 'fcal host controller %s needs attention (%s)', $self->{ident}, $self->{cpqFcaHostCntlrStatus}); } else { $self->add_info(sprintf 'fcal host controller %s is ok', $self->{ident}); } if ($self->is_blacklisted('fcahc', $self->{cpqFcaHostCntlrSlot}.'-'.$self->{cpqFcaHostCntlrIndex})) { } elsif ($self->{cpqFcaHostCntlrOverallCondition} ne 'ok') { $self->add_message(CRITICAL, sprintf 'fcal host controller %s reports problems (%s)', $self->{ident}, $self->{cpqFcaHostCntlrStatus}); $self->add_info(sprintf 'fcal host controller %s reports problems (%s)', $self->{ident}, $self->{cpqFcaHostCntlrStatus}); } } 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}, cpqFcaCntlrBoxIndex => $params{cpqFcaCntlrBoxIndex}, cpqFcaCntlrBoxIoSlot => $params{cpqFcaCntlrBoxIoSlot}, cpqFcaCntlrModel => $params{cpqFcaCntlrModel}, cpqFcaCntlrStatus => $params{cpqFcaCntlrStatus}, cpqFcaCntlrCondition => $params{cpqFcaCntlrCondition}, blacklisted => 0, }; $self->{name} = $params{name} || $self->{cpqFcaCntlrBoxIndex}.':'.$self->{cpqFcaCntlrBoxIoSlot}; $self->{controllerindex} = $self->{cpqFcaCntlrBoxIndex}; $self->{ident} = sprintf 'in box %s/slot %s', $self->{cpqFcaCntlrBoxIndex}, $self->{cpqFcaCntlrBoxIoSlot}; bless $self, $class; return $self; } sub check { my $self = shift; $self->blacklist('fcaco', $self->{name}); if ($self->{cpqFcaCntlrCondition} eq 'other') { if (1) { # was ist mit phys. drives? $self->add_message(CRITICAL, sprintf 'fcal controller %s needs attention (%s)', $self->{ident}, $self->{cpqFcaCntlrStatus}); $self->add_info(sprintf 'fcal controller %s %s needs attention (%s)', $self->{name}, $self->{ident}, $self->{cpqFcaCntlrStatus}); } else { $self->add_info(sprintf 'fcal controller %s is ok and unused', $self->{ident}); $self->{blacklisted} = 1; } } elsif ($self->{cpqFcaCntlrCondition} ne 'ok') { $self->add_message(CRITICAL, sprintf 'fcal controller %s needs attention', $self->{ident}); $self->add_info(sprintf 'fcal controller %s %s needs attention (%s)', $self->{name}, $self->{ident}, $self->{cpqFcaCntlrCondition}); } else { $self->add_info(sprintf 'fcal controller %s is ok', $self->{ident}); } } 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}, cpqFcaAccelBoxIndex => $params{cpqFcaAccelBoxIndex}, cpqFcaAccelBoxIoSlot => $params{cpqFcaAccelBoxIoSlot}, cpqFcaAccelStatus => $params{cpqFcaAccelStatus}, cpqFcaAccelErrCode => $params{cpqFcaAccelErrCode}, cpqFcaAccelBatteryStatus => $params{cpqFcaAccelBatteryStatus}, cpqFcaAccelCondition => $params{cpqFcaAccelCondition}, blacklisted => 0, }; $self->{name} = $params{name} || $self->{cpqFcaAccelBoxIndex}.':'.$self->{cpqFcaAccelBoxIoSlot}; $self->{controllerindex} = $self->{cpqFcaAccelBoxIndex}; $self->{ident} = sprintf 'in box %s/slot %s', $self->{cpqFcaAccelBoxIndex}, $self->{cpqFcaAccelBoxIoSlot}; bless $self, $class; return $self; } sub check { my $self = shift; # !!! cpqFcaAccelStatus $self->blacklist('fcaac', $self->{name}); if ($self->{cpqFcaAccelStatus} eq 'invalid') { $self->add_info(sprintf 'fcal accelerator %s is not installed', $self->{ident}); } elsif ($self->{cpqFcaAccelStatus} eq 'tmpDisabled') { $self->add_info(sprintf 'fcal accelerator %s is temp disabled', $self->{ident}); } elsif ($self->{cpqFcaAccelCondition} eq 'other') { $self->add_message(CRITICAL, sprintf 'fcal accelerator %s needs attention (%s)', $self->{ident}, $self->{cpqFcaAccelErrCode}); $self->add_info(sprintf 'fcal accelerator %s needs attention (%s)', $self->{ident}, $self->{cpqFcaAccelErrCode}); } elsif ($self->{cpqFcaAccelCondition} ne 'ok') { $self->add_message(CRITICAL, sprintf 'fcal accelerator %s needs attention (%s)', $self->{ident}, $self->{cpqFcaAccelErrCode}); $self->add_info(sprintf 'fcal accelerator %s needs attention (%s)', $self->{ident}, $self->{cpqFcaAccelErrCode}); } else { $self->add_info(sprintf 'fcal accelerator %s is ok', $self->{ident}); } } 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}, cpqFcaLogDrvBoxIndex => $params{cpqFcaLogDrvBoxIndex}, cpqFcaLogDrvIndex => $params{cpqFcaLogDrvIndex}, cpqFcaLogDrvFaultTol => $params{cpqFcaLogDrvFaultTol}, cpqFcaLogDrvStatus => $params{cpqFcaLogDrvStatus}, cpqFcaLogDrvPercentRebuild => $params{cpqFcaLogDrvPercentRebuild}, cpqFcaLogDrvSize => $params{cpqFcaLogDrvSize}, cpqFcaLogDrvPhyDrvIDs => $params{cpqFcaLogDrvPhyDrvIDs}, cpqFcaLogDrvCondition => $params{cpqFcaLogDrvCondition}, blacklisted => 0, }; 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}); if ($self->{cpqFcaLogDrvCondition} ne "ok") { if ($self->{cpqFcaLogDrvStatus} =~ /rebuild|recovering|expand/) { $self->add_message(WARNING, sprintf "logical drive %s is %s (%s)", $self->{name}, $self->{cpqFcaLogDrvStatus}, $self->{cpqFcaLogDrvFaultTol}); } else { $self->add_message(CRITICAL, sprintf "logical drive %s is %s (%s)", $self->{name}, $self->{cpqFcaLogDrvStatus}, $self->{cpqFcaLogDrvFaultTol}); } } $self->add_info( sprintf "logical drive %s is %s (%s)", $self->{name}, $self->{cpqFcaLogDrvStatus}, $self->{cpqFcaLogDrvFaultTol}); } sub dump { my $self = shift; printf "[LOGICAL_DRIVE]\n"; 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}, cpqFcaPhyDrvBoxIndex => $params{cpqFcaPhyDrvBoxIndex}, cpqFcaPhyDrvIndex => $params{cpqFcaPhyDrvIndex}, cpqFcaPhyDrvModel => $params{cpqFcaPhyDrvModel}, cpqFcaPhyDrvBay => $params{cpqFcaPhyDrvBay}, cpqFcaPhyDrvStatus => $params{cpqFcaPhyDrvStatus}, cpqFcaPhyDrvCondition => $params{cpqFcaPhyDrvCondition}, cpqFcaPhyDrvSize => $params{cpqFcaPhyDrvSize}, cpqFcaPhyDrvBusNumber => $params{cpqFcaPhyDrvBusNumber}, blacklisted => 0, }; $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}); 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, sprintf "physical drive %s is %s", $self->{name}, $self->{cpqFcaPhyDrvStatus}); } $self->add_info( sprintf "physical drive %s is %s", $self->{name}, $self->{cpqFcaPhyDrvStatus}); } sub dump { my $self = shift; printf "[PHYSICAL_DRIVE]\n"; 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, disk_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_disk_subsystem(); $self->auto_blacklist(); $self->check_cpus(); $self->check_powersupplies(); $self->check_fan_subsystem(); $self->check_temperatures(); $self->check_memory_subsystem(); $self->check_disk_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_disk_subsystem { my $self = shift; $self->{components}->{disk_subsystem} = HP::Proliant::Component::DiskSubsystem->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} >= 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 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() { 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 # 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 ($< != 0) { $hpasmcli = "sudo ".$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)) { if (open HPASMCLI, "$hpasmcli -s \"show $component\"|") { my @output = ; 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) { $hpacucli = "sudo ".$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 = ; close HPACUCLI; $self->{rawdata} .= join("\n", map { 'config '.$_; } @output); } if (open HPACUCLI, "$hpacucli ctrl all show status 2>&1|") { my @output = ; close HPACUCLI; $self->{rawdata} .= join("\n", map { 'status '.$_; } @output); } } } 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.'); } } } } } } } 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 = ; 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}/, ) { $known = 1; } close OSSIG; } } if (! $known) { $self->add_message(UNKNOWN, 'multiple hpasmd procs'); } } if ($numcliprocs == 1) { $self->add_message(UNKNOWN, 'another hpasmdcli is running'); } elsif ($numcliprocs > 1) { $self->add_message(UNKNOWN, 'hanging hpasmdcli processes'); } } } sub check_hpasm_client { my $self = shift; my $hpasmcli = shift; if (open HPASMCLI, "$hpasmcli -s help 2>&1 |") { my @output = ; 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 = ; 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"; $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; $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->{$_} =~ 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_temps => [], common_enclosure_fan_subsys => undef, common_enclosure_fuses => [], 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', 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}, ); } sub check { my $self = shift; foreach (@{$self->{common_enclosures}}) { $_->check(); } $self->{common_enclosure_fan_subsys}->check(); } sub dump { my $self = shift; foreach (@{$self->{common_enclosures}}) { $_->dump(); } $self->{common_enclosure_fan_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}, cpqRackCommonEnclosureRack => $params{cpqRackCommonEnclosureRack}, cpqRackCommonEnclosureIndex => $params{cpqRackCommonEnclosureIndex}, cpqRackCommonEnclosureModel => $params{cpqRackCommonEnclosureModel}, cpqRackCommonEnclosureSerialNum => $params{cpqRackCommonEnclosureSerialNum}, cpqRackCommonEnclosureFWRev => $params{cpqRackCommonEnclosureFWRev}, cpqRackCommonEnclosureName => $params{cpqRackCommonEnclosureName}, cpqRackCommonEnclosureCondition => $params{cpqRackCommonEnclosureCondition}, cpqRackCommonEnclosureHasServerBlades => $params{cpqRackCommonEnclosureHasServerBlades}, cpqRackCommonEnclosureHasPowerBlades => $params{cpqRackCommonEnclosureHasPowerBlades}, cpqRackCommonEnclosureHasNetConnectors => $params{cpqRackCommonEnclosureHasNetConnectors}, cpqRackCommonEnclosureHasTempSensors => $params{cpqRackCommonEnclosureHasTempSensors}, cpqRackCommonEnclosureHasFans => $params{cpqRackCommonEnclosureHasFans}, cpqRackCommonEnclosureHasFuses => $params{cpqRackCommonEnclosureHasFuses}, blacklisted => 0, info => undef, extendedinfo => undef, }; $self->{name} = $self->{cpqRackCommonEnclosureRack}.':'.$self->{cpqRackCommonEnclosureIndex}; bless $self, $class; return $self; } sub check { my $self = shift; $self->blacklist('ce', $self->{cpqRackCommonEnclosureName}); my $info = sprintf 'common enclosure %s condition is %s', $self->{cpqRackCommonEnclosureName}, $self->{cpqRackCommonEnclosureCondition}; $self->add_info($info); if ($self->{cpqRackCommonEnclosureCondition} eq 'failed') { $self->add_message(CRITICAL, $info); } elsif ($self->{cpqRackCommonEnclosureCondition} eq 'degraded') { $self->add_message(WARNING, $info); } } sub dump { my $self = shift; printf "[COMMON_ENCLOSURE_%s]\n", $self->{cpqRackCommonEnclosureName}; foreach (qw(cpqRackCommonEnclosureRack cpqRackCommonEnclosureIndex cpqRackCommonEnclosureModel cpqRackCommonEnclosureSerialNum 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(); } } sub dump { my $self = shift; foreach (@{$self->{fans}}) { $_->dump(); } } 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},cklisted => 0, #params cpqRackCommonEnclosureFanEntry => $params{cpqRackCommonEnclosureFanEntry}, cpqRackCommonEnclosureFanRack => $params{cpqRackCommonEnclosureFanRack}, cpqRackCommonEnclosureFanChassis => $params{cpqRackCommonEnclosureFanChassis}, cpqRackCommonEnclosureFanIndex => $params{cpqRackCommonEnclosureFanIndex}, cpqRackCommonEnclosureFanEnclosureName => $params{cpqRackCommonEnclosureFanEnclosureName}, cpqRackCommonEnclosureFanLocation => $params{cpqRackCommonEnclosureFanLocation}, cpqRackCommonEnclosureFanPartNumber => $params{cpqRackCommonEnclosureFanPartNumber}, cpqRackCommonEnclosureFanSparePartNumber => $params{cpqRackCommonEnclosureFanSparePartNumber}, cpqRackCommonEnclosureFanPresent => $params{cpqRackCommonEnclosureFanPresent}, cpqRackCommonEnclosureFanRedundant => $params{cpqRackCommonEnclosureFanRedundant}, cpqRackCommonEnclosureFanRedundantGroupId => $params{cpqRackCommonEnclosureFanRedundantGroupId}, cpqRackCommonEnclosureFanCondition => $params{cpqRackCommonEnclosureFanCondition}, cpqRackCommonEnclosureFanEnclosureSerialNum => $params{cpqRackCommonEnclosureFanEnclosureSerialNum}, info => undef, extendedinfo => undef, }; $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', $self->{name}, $self->{cpqRackCommonEnclosureFanPresent}, $self->{cpqRackCommonEnclosureFanLocation}, $self->{cpqRackCommonEnclosureFanRedundant}); if ($self->{cpqRackCommonEnclosureFanCondition} eq 'degraded') { $self->add_message(WARNING, 'fan %s is %s', $self->{name}, $self->{cpqRackCommonEnclosureFanCondition}); } elsif ($self->{cpqRackCommonEnclosureFanCondition} eq 'failed') { $self->add_message(CRITICAL, 'fan %s is %s', $self->{name}, $self->{cpqRackCommonEnclosureFanCondition}); } } 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::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}, cpqRackPowerEnclosureEntry => $params{cpqRackPowerEnclosureEntry}, cpqRackPowerEnclosureRack => $params{cpqRackPowerEnclosureRack}, cpqRackPowerEnclosureIndex => $params{cpqRackPowerEnclosureIndex}, cpqRackPowerEnclosureName => $params{cpqRackPowerEnclosureName}, cpqRackPowerEnclosureMgmgtBoardSerialNum => $params{cpqRackPowerEnclosureMgmgtBoardSerialNum}, cpqRackPowerEnclosureRedundant => $params{cpqRackPowerEnclosureRedundant}, cpqRackPowerEnclosureLoadBalanced => $params{cpqRackPowerEnclosureLoadBalanced}, cpqRackPowerEnclosureInputPwrType => $params{cpqRackPowerEnclosureInputPwrType}, cpqRackPowerEnclosurePwrFeedMax => $params{cpqRackPowerEnclosurePwrFeedMax}, cpqRackPowerEnclosureCondition => $params{cpqRackPowerEnclosureCondition}, blacklisted => 0, info => undef, extendedinfo => undef, }; bless $self, $class; $self->init(); return $self; } sub check { my $self = shift; $self->blacklist('pe', $self->{cpqRackPowerEnclosureName}); my $info = sprintf 'power enclosure %s condition is %s', $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', 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 } # dreckada dreck, dreckada foreach ($self->get_entries($oids, 'cpqRackPowerSupplyEntry')) { push(@{$self->{power_supplies}}, HP::BladeSystem::Component::PowerSupplySubsystem::PowerSupply->new(%{$_})); } my $total_power_output = 0; foreach my $powersupply (@{$self->{power_supplies}}) { $total_power_output += $powersupply->{cpqRackPowerSupplyCurPwrOutput}; } $self->{runtime}->{plugin}->add_perfdata( label => 'total_power_output', value => $total_power_output, uom => 'Watts', ); } sub check { my $self = shift; foreach (@{$self->{power_supplies}}) { $_->check(); } } sub dump { my $self = shift; foreach (@{$self->{power_supplies}}) { $_->dump(); } } 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}, cpqRackPowerSupplyRack => $params{cpqRackPowerSupplyRack}, cpqRackPowerSupplyChassis => $params{cpqRackPowerSupplyChassis}, cpqRackPowerSupplyIndex => $params{cpqRackPowerSupplyIndex}, cpqRackPowerSupplyEnclosureName => $params{cpqRackPowerSupplyEnclosureName}, cpqRackPowerSupplyMaxPwrOutput => $params{cpqRackPowerSupplyMaxPwrOutput}, cpqRackPowerSupplyCurPwrOutput => $params{cpqRackPowerSupplyCurPwrOutput}, cpqRackPowerSupplyIntakeTemp => $params{cpqRackPowerSupplyIntakeTemp}, cpqRackPowerSupplyExhaustTemp => $params{cpqRackPowerSupplyExhaustTemp}, cpqRackPowerSupplyStatus => $params{cpqRackPowerSupplyStatus}, cpqRackPowerSupplySupplyInputLineStatus => $params{cpqRackPowerSupplySupplyInputLineStatus}, cpqRackPowerSupplyPresent => $params{cpqRackPowerSupplyPresent}, cpqRackPowerSupplyCondition => $params{cpqRackPowerSupplyCondition}, blacklisted => 0, info => undef, extendedinfo => undef, }; $self->{name} = $params{cpqRackPowerSupplyRack}.':'.$params{cpqRackPowerSupplyChassis}.':'.$params{cpqRackPowerSupplyIndex}; 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', $self->{name}, $self->{cpqRackPowerSupplyPresent}, $self->{cpqRackPowerSupplyCondition}; $self->add_info($info) if $self->{cpqRackPowerSupplyPresent} eq 'present' || $self->{runtime}->{options}->{verbose} >= 3; if ($self->{cpqRackPowerSupplyPresent} eq 'present') { $self->{runtime}->{plugin}->add_perfdata( label => sprintf('power_supply_output_%s', $self->{name}), value => $self->{cpqRackPowerSupplyCurPwrOutput}, uom => 'Watts', ); if ($self->{cpqRackPowerSupplyCondition} eq 'degraded') { $self->add_message(WARNING, $info); $self->add_info(sprintf 'power supply %s status is %s, inp.line status is %s', $self->{cpqRackPowerSupplyName}, $self->{cpqRackPowerSupplyStatus}, $self->{cpqRackPowerSupplySupplyInputLineStatus}); } elsif ($self->{cpqRackPowerSupplyCondition} eq 'failed') { $self->add_message(CRITICAL, $info); $self->add_info(sprintf 'power supply %s status is %s, inp.line status is %s', $self->{cpqRackPowerSupplyName}, $self->{cpqRackPowerSupplyStatus}, $self->{cpqRackPowerSupplySupplyInputLineStatus}); } } } sub dump { my $self = shift; printf "[POWER_SUPPLY%s]\n", $self->{name}; foreach (qw(cpqRackPowerSupplyRack cpqRackPowerSupplyChassis cpqRackPowerSupplyIndex cpqRackPowerSupplyEnclosureName 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(); } } sub dump { my $self = shift; foreach (@{$self->{net_connectors}}) { $_->dump(); } } 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}, cpqRackNetConnectorRack => $params{cpqRackNetConnectorRack}, cpqRackNetConnectorChassis => $params{cpqRackNetConnectorChassis}, cpqRackNetConnectorIndex => $params{cpqRackNetConnectorIndex}, cpqRackNetConnectorEnclosureName => $params{cpqRackNetConnectorEnclosureName}, cpqRackNetConnectorName => $params{cpqRackNetConnectorName}, cpqRackNetConnectorModel => $params{cpqRackNetConnectorModel}, cpqRackNetConnectorSerialNum => $params{cpqRackNetConnectorSerialNum}, cpqRackNetConnectorPartNumber => $params{cpqRackNetConnectorPartNumber}, cpqRackNetConnectorSparePartNumber => $params{cpqRackNetConnectorSparePartNumber}, cpqRackNetConnectorFWRev => $params{cpqRackNetConnectorFWRev}, cpqRackNetConnectorType => $params{cpqRackNetConnectorType}, cpqRackNetConnectorLocation => $params{cpqRackNetConnectorLocation}, cpqRackNetConnectorPresent => $params{cpqRackNetConnectorPresent}, cpqRackNetConnectorHasFuses => $params{cpqRackNetConnectorHasFuses}, cpqRackNetConnectorEnclosureSerialNum => $params{cpqRackNetConnectorEnclosureSerialNum}, blacklisted => 0, info => undef, extendedinfo => undef, }; $self->{name} = $params{cpqRackNetConnectorRack}.':'.$params{cpqRackNetConnectorChassis}.':'.$params{cpqRackNetConnectorIndex}; 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', $self->{name}.($self->{cpqRackNetConnectorName} ? '('.$self->{cpqRackNetConnectorName}.')' : ''), $self->{cpqRackNetConnectorPresent}, $self->{cpqRackNetConnectorModel}; $self->add_info($info) if $self->{cpqRackNetConnectorPresent} eq 'present' || $self->{runtime}->{options}->{verbose} >= 3; # hat weder status noch condition } 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(); } } sub dump { my $self = shift; foreach (@{$self->{server_blades}}) { $_->dump(); } } 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}, cpqRackServerBladeRack => $params{cpqRackServerBladeRack}, cpqRackServerBladeChassis => $params{cpqRackServerBladeChassis}, cpqRackServerBladeIndex => $params{cpqRackServerBladeIndex}, cpqRackServerBladeName => $params{cpqRackServerBladeName}, cpqRackServerBladeEnclosureName => $params{cpqRackServerBladeEnclosureName}, cpqRackServerBladePartNumber => $params{cpqRackServerBladePartNumber}, cpqRackServerBladeSparePartNumber => $params{cpqRackServerBladeSparePartNumber}, cpqRackServerBladePosition => $params{cpqRackServerBladePosition}, cpqRackServerBladeHeight => $params{cpqRackServerBladeHeight}, cpqRackServerBladeWidth => $params{cpqRackServerBladeWidth}, cpqRackServerBladeDepth => $params{cpqRackServerBladeDepth}, cpqRackServerBladePresent => $params{cpqRackServerBladePresent}, cpqRackServerBladeHasFuses => $params{cpqRackServerBladeHasFuses}, cpqRackServerBladeEnclosureSerialNum => $params{cpqRackServerBladeEnclosureSerialNum}, cpqRackServerBladeSlotsUsed => $params{cpqRackServerBladeSlotsUsed}, cpqRackServerBladeStatus => $params{cpqRackServerBladeStatus}, cpqRackServerBladeDiagnosticString => $params{cpqRackServerBladeDiagnosticString} || '', cpqRackServerBladePowered => $params{cpqRackServerBladePowered}, cpqRackServerBladePOSTStatus => $params{cpqRackServerBladePOSTStatus}, blacklisted => 0, info => undef, extendedinfo => undef, }; bless $self, $class; $self->init(); return $self; } sub check { my $self = shift; $self->blacklist('sb', $self->{cpqRackServerBladeName}); my $info = sprintf 'serverblade %s is %s; partnumber=%s; name=%s', $self->{cpqRackServerBladeIndex}, $self->{cpqRackServerBladePresent}, $self->{cpqRackServerBladePartNumber}, $self->{cpqRackServerBladeName}; $self->add_info($info) if $self->{cpqRackServerBladePresent} eq 'present' || $self->{runtime}->{options}->{verbose} >= 3; # absent blades nur bei -vvv 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 $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 my $tic = time; my $tac = $tic; # Walk for Asset $tic = time; my $response0 = $session->get_table( -maxrepetitions => 1, -baseoid => $cpqSiComponent); if (scalar (keys %{$response0}) == 0) { $self->trace(2, sprintf "maxrepetitions failed. fallback"); $response0 = $session->get_table( -baseoid => $cpqSiComponent); } $tac = time; $self->trace(2, sprintf "%03d seconds for walk cpqSiComponent (%d oids)", $tac - $tic, scalar(keys %{$response0})); $tic = time; my $response1 = $session->get_table( -maxrepetitions => 1, -baseoid => $cpqRackInfo); if (scalar (keys %{$response1}) == 0) { $self->trace(2, sprintf "maxrepetitions failed. fallback"); $response1 = $session->get_table( -baseoid => $cpqRackInfo); } $tac = time; $self->trace(2, sprintf "%03d seconds for walk cpqRackInfo (%d oids)", $tac - $tic, scalar(keys %{$response1})); $session->close; map { $response->{$_} = $response0->{$_} } keys %{$response0}; 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 $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, }; $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->check_cpus(); # $self->check_powersupplies(); # $self->check_fan_subsystem(); # $self->check_temperatures(); # $self->check_memory_subsystem(); $self->check_disk_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 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 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} =~ /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} =~ /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 () { 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); while() { # SNMPv2-SMI::enterprises.232.6.2.6.7.1.3.1.4 = INTEGER: 6 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+$//; } 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 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->{plugin}->add_message(CRITICAL, 'cannot create session object'); $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}; } 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 ] '. '--hostname --community '. ' ...]', version => '4.1.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 => '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 bladecenter', 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 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'), 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);