????
| Current Path : /lib/raider/Raider/Jobs/ |
| Current File : //lib/raider/Raider/Jobs/Mdraid.pm |
use strict;
use warnings;
package Raider::Jobs::Mdraid;
use base qw( Raider::Jobs );
use Raider::Notification::API;
use Raider::Notification::Email;
=head1 NAME
Raider::Jobs::Mdraid - Mdraid specific tasks for checking raid health
=head1 DESCRIPTION
Checks raid health for Mdraid arrays.
=head1 USAGE
use Raider::Jobs::Mdraid;
my jobsMdraid = Raider::Jobs::Mdraid->new();
=head1 METHODS
=head2 run_job
Takes all needed actions for checking raid health.
=head2 get_array_list(\%args)
Returns a list of arrays.
=head2 array_is_ok(\%args)
Returns true if array is healthy.
=cut
sub run_job {
my $self = shift;
my $conf_file = $self->read_conf_file();
unless ($conf_file->{'enable_mdraid_notifications'}) {
$self->logger({cat => 'i', msg => "Run job for device 'Mdraid' suppressed by config file."});
return;
}
my $degraded_raids = 0;
my @degraded_md_devices = ();
# We only want to health check the whitelisted MD devices if defined.
my ($md_devices,$mdstat_contents) = $self->get_md_devices({ whitelisted_only => 1 });
for my $md_device ( @{ $md_devices } ) {
unless ( $self->array_is_ok({ md_device => $md_device, mdstat_contents => $mdstat_contents }) ) {
$degraded_raids = 1;
push(@degraded_md_devices, $md_device);
}
};
my $notifEmail = Raider::Notification::Email->new();
my $notifAPI = Raider::Notification::API->new();
if ( $degraded_raids ) {
my $output = "Degraded MD device(s): [@degraded_md_devices]\nroot ~ # cat /proc/mdstat\n$mdstat_contents\nroot ~ #\n";
if ( $notifAPI->can_alert({ notify_type => 'Mdraid' }) ) {
$self->logger({ cat => 'w', msg => 'Mdraid RAID Alarm Detected' });
my $notify_msg = "Mdraid RAID Alarm Detected 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 => 'Mdraid'});
}
else {
$self->logger({ cat => 'w', msg => 'Notification for Mdraid suppressed, alert file for today already exists.' });
}
}
else {
# health is ok, clear alerts for device
$notifAPI->clear_alerts_for_device('Mdraid');
}
}
sub get_md_devices {
my $self = shift;
my $opts = shift;
my @md_devices = ();
my $mdstat_contents = do {
local $/ = undef;
open my $fh, "<", '/proc/mdstat' || $self->logger({ cat => 'c', msg => "Unable to open /proc/mdstat: [$!]" });
<$fh>;
};
# If we are told to only get whitelisted devices, and if mdraid_monitoring_whitelisted_devices is enabled, record what is whitelisted for later use.
my $whitelisted_md_device;
if ( defined($opts->{whitelisted_only}) && $opts->{whitelisted_only} ) {
my $conf_file = $self->read_conf_file();
if ( defined($conf_file->{'mdraid_monitoring_whitelisted_devices'}) && $conf_file->{'mdraid_monitoring_whitelisted_devices'} ) {
for my $md_device ( split /:/, $conf_file->{'mdraid_monitoring_whitelisted_devices'} ) {
$whitelisted_md_device->{ $md_device } = 1;
}
}
}
for my $line ( split /^/, $mdstat_contents ) {
if ( $line =~ /^(md\d+)(\s+):\s+/ ) {
# If we have whitelisted MD devices specified, respect that.
if ( ref($whitelisted_md_device) eq 'HASH' ) {
if ( defined($whitelisted_md_device->{ $1 }) ) {
push(@md_devices, $1);
}
else {
$self->logger({ cat => 'w', msg => "Ignoring health check of non-whitelisted MD device [$1]" });
next;
}
}
else {
push(@md_devices, $1);
}
}
}
return (\@md_devices,$mdstat_contents);
}
sub array_is_ok {
my $self = shift;
my $opts = shift;
my $ideal_disks = 0;
my $disks_in_use = 0;
my $passed_md = 0;
for my $line ( split /^/, $opts->{mdstat_contents} ) {
if ( $passed_md ) {
if ( $line =~ /blocks/ && $line =~ /\[(\d+)\/(\d+)\]/ ) {
$ideal_disks = $1;
$disks_in_use = $2;
last; # Found what we wanted, break loop.
}
}
if ( $line =~ /^$opts->{md_device}(\s+)?:\s+\S+/ ) {
$passed_md = 1;
next;
}
else {
$passed_md = 0;
}
}
# degraded if actually used disks is less than ideal.
if ( $disks_in_use < $ideal_disks ) {
return 0;
}
else {
return 1;
}
}
1;