????
| Current Path : /usr/lib/raider/Raider/Jobs/ |
| Current File : //usr/lib/raider/Raider/Jobs/MegaraidSAS.pm |
use strict;
use warnings;
package Raider::Jobs::MegaraidSAS;
use base qw( Raider::Jobs );
use Raider::Notification::API;
use Raider::Notification::Email;
=head1 NAME
Raider::Jobs::MegaraidSAS - MegaraidSAS specific tasks for checking raid health
=head1 DESCRIPTION
Checks raid health for MegaraidSAS cards.
=head1 USAGE
use Raider::Jobs::MegaraidSAS;
my jobs3ware = Raider::Jobs::MegaraidSAS->new();
=head1 METHODS
=head2 get_icmd()
Returns the PATH to the icmd.
=head2 run_job
Takes all needed actions for checking raid health.
=head2 get_controller_list()
Returns a list of controllers.
=head2 get_array_list(\%args)
Returns a list of arrays.
=head2 array_is_ok(\%args)
Returns true if array is healthy.
=cut
sub get_icmd {
my $self = shift;
my $arch = $self->get_arch();
my $icmd;
if ( $arch eq '64bit' ) {
$icmd = '/opt/MegaRAID/MegaCli/MegaCli64';
}
elsif ( $arch eq '32bit' ) {
$icmd = '/opt/MegaRAID/MegaCli/MegaCli';
}
else {
$self->logger({ cat => 'c', msg => "get_arch() returned an invalid value: '$arch'" });
}
return $icmd;
}
sub run_job {
my $self = shift;
my $opts = shift;
my $icmd = $self->get_icmd();
$self->icmd_in_path({ icmd => "$icmd" });
my $output;
my $controller_list_ref = $self->get_controller_list({ icmd => "$icmd" });
my @controller_list = @$controller_list_ref;
my $raid_bad = 0;
my $bbu_bad = 0;
# Health checks
for my $controller ( @controller_list ) {
# RAID
my $array_list_ref = $self->get_array_list({ icmd => "$icmd", c => "$controller" });
my @array_list = @$array_list_ref;
for my $u ( @array_list ) {
my $health_check = `$icmd -LDInfo -L$u -a$controller`;
unless ( $self->array_is_ok({ health_check => $health_check }) ) {
$output .= "root ~ # $icmd -LDInfo -L$u -a$controller\n";
$output .= "$health_check\n";
$output .= "root ~ #\n";
$raid_bad = 1;
}
};
# BBU
if ( $opts->{'bbu_check'} ) {
for my $line ( split /^/, `$icmd -AdpAllInfo -a$controller` ) {
if ( $line =~ /^BBU(\s+)?:\s+Present/i ) {
$self->logger({ cat => 'i', msg => "BBU detected on adapter $controller" });
my $bbu_check_cmd = `$icmd -AdpBbuCmd -GetBbuStatus -a$controller`;
# Prevent appending entry for good BBUs that were set bad by previous
# controller.
my $needs_append = 0;
# MegaCLI Ver 8.02.21 uses "Operational" , MegaCLI Ver 8.07.06 uses "Optimal".
# FS#5916 - Don't report state 'Learning'.
if ( $bbu_check_cmd !~ /Battery\s+State(\s+)?:\s+[Operational|Optimal|Learning]/i ) {
$bbu_bad = 1;
$needs_append = 1;
}
# 'Battery State:' field will show as "Failed" on charging, account for this.
if ( $bbu_check_cmd =~ /Charging\s+Status(\s+)?:\s+Discharging/i ) {
$bbu_bad = 0;
}
# If utility says we need replacing, always report.
if ( $bbu_check_cmd =~ /Battery\s+Replacement\s+required(\s+)?:\s+Yes/i ) {
$bbu_bad = 1;
$needs_append = 1;
}
if ( $needs_append ) {
$self->logger({ cat => 'w', msg => "Error detected with BBU on adapter $controller" });
my $bbu_check_cmd_pretty = "root ~ # $icmd -AdpBbuCmd -GetBbuStatus -a$controller\n";
$bbu_check_cmd_pretty .= "$bbu_check_cmd\n";
$bbu_check_cmd_pretty .= "root ~ #\n";
$output .= "Error detected with BBU on Adapter $controller. Details below:\n";
$output .= $bbu_check_cmd_pretty;
}
}
}
}
};
my $notIfAPI = Raider::Notification::API->new();
my $notIfEmail = Raider::Notification::Email->new();
if ( $raid_bad || $bbu_bad ) {
if ( $notIfAPI->can_alert({ notify_type => 'MegaraidSAS' }) ) {
# First alarm today. Log some additional information.
my $megacli_cfg_display = `$icmd -CfgDsply -aALL`;
$self->logger({ cat => 'i', msg => "First invocation of MegaraidSAS alarm today; Full details:\n$megacli_cfg_display" });
my $notify_summary;
if ( $raid_bad && $bbu_bad ) {
$notify_summary = 'MegaraidSAS Hardware RAID and BBU Alarm Detected';
}
elsif ( $raid_bad && ! $bbu_bad ) {
$notify_summary = 'MegaraidSAS Hardware RAID Alarm Detected';
}
elsif ( $bbu_bad && ! $raid_bad ) {
$notify_summary = 'MegaraidSAS BBU Alarm Detected';
}
$self->logger({ cat => 'w', msg => $notify_summary });
my $notify_msg = "$notify_summary on [$Raider::Base::base_conf{'hostname'}] at [$self->{uniq_id}]\nDetails:\n $output";
if ( $notIfAPI->can_api() ) {
$notIfAPI->send_notification({
message => $notify_msg
});
}
else {
$notIfEmail->send_notification({
subject => "RAID Controller Alarm on $Raider::Base::base_conf{'hostname'}",
message => $notify_msg
});
}
$notIfAPI->place_alert({notify_type => 'MegaraidSAS'});
}
else {
$self->logger({ cat => 'w', msg => 'Notification for MegaraidSAS suppressed, alert file for today already exists.' });
}
}
else {
# health is ok, clear alerts for device
$notIfAPI->clear_alerts_for_device('MegaraidSAS');
}
}
sub get_controller_list {
my $self = shift;
my $opts = shift;
my @ctrls = ();
for my $line ( split /^/, `$opts->{icmd} -AdpAllInfo -aALL` ) {
if ( $line =~ /Adapter\s+#(\d+)/i ) {
push(@ctrls, $1);
}
}
return \@ctrls;
}
sub get_array_list {
my $self = shift;
my $opts = shift;
my $utotal = 0;
for my $line ( split /^/, `$opts->{icmd} -AdpAllInfo -a$opts->{c}` ) {
if ( $line =~ /^Virtual\s+Drives\s+:\s+(\d+)/i ) {
$utotal = $1;
}
}
$utotal--;
my @array_list = map { 0 + $_ } 0..$utotal;
return \@array_list;
}
sub array_is_ok {
my $self = shift;
my $opts = shift;
$self->logger({ cat => 'c', msg => "array_is_ok() missing an argument!" }) unless ( $opts->{health_check} );
if ( $opts->{health_check} =~ /State(\s+)?:\s+Optimal|Virtual\s+Drive\s+\d+\s+Does\s+not\s+Exist/i ) {
return 1;
}
# CacheCade virtual drives don't always have a State field (FS#5948).
# ~/ssullivan 2013/04/08
if ( $opts->{health_check} =~ /Virtual\s+Drive\s+Type(\s+)?:\s+CacheCade/i ) {
if ( $opts->{health_check} =~ /State(\s+)?:\s+(\S+)/i ) {
if ( $2 =~ /Optimal/i ) {
return 1;
}
else {
return 0;
}
}
else {
return 1;
}
}
return 0;
}
1;