package Device::RAID::Poller::Backends::Linux_mdadm;
use 5.006;
use strict;
use warnings;
=head1 NAME
Device::RAID::Poller::Backends::Linux_mdadm - Handles Linux mdadm software RAID.
=head1 VERSION
Version 0.0.0
=cut
our $VERSION = '0.0.0';
=head1 SYNOPSIS
use Device::RAID::Poller::Backends::Linux_mdadm;
my $backend = Device::RAID::Poller::Backends::Linux_mdadm->new;
my $usable=$backend->usable;
my %return_hash;
if ( $usable ){
%return_hash=$backend->run;
my %status=$backend->run;
use Data::Dumper;
print Dumper( \%status );
}
=head1 METHODS
=head2 new
Initiates the backend object.
my $backend = Device::RAID::Poller::Backends::Linux_mdadm->new;
=cut
sub new {
my $self = {
usable=>0,
};
bless $self;
return $self;
}
=head2 run
Runs the poller backend and report the results.
If nothing is nothing is loaded, load will be called.
my %status=$backend->run;
use Data::Dumper;
print Dumper( \%status );
=cut
sub run {
my $self=$_[0];
my %return_hash=(
'status'=>0,
'devices'=>{},
);
# if not usable, no point in continuing
if ( ! $self->{usable} ){
return %return_hash;
}
$return_hash{status}=1;
# get a list of devices
my $raw=`mdadm --detail --scan`;
my @raw_split=split(/\n/, $raw);
my @devs;
foreach my $line (@raw_split){
if ( $line =~ /^ARRAY/ ){
my @line_split=split(/[\t ]+/, $line);
push(@devs, $line_split[1]);
}
}
# Process each md device that exists.
foreach my $dev (@devs){
$return_hash{devices}{$dev}={
'backend'=>'Linux_mdadm',
'name'=>$dev,
'good'=>[],
'bad'=>[],
'spare'=>[],
'type'=>'mdadm',
'BBUstatus'=>'na',
'status'=>'unknown',
};
# check device and break it appart
$raw=`mdadm --detail $dev`;
@raw_split=split(/\n/, $raw);
my $number_found=0;
my $process=0;
foreach my $line (@raw_split){
chomp($line);
if ( $line =~ /[\t ]*Number/ ){
$number_found=1;
}elsif( $number_found ){
$process=1;
}
if ( $process ){
# good disk...
# active
# rebuilding
# bad disk...
# removed
# spare disks...
# spare
# spare rebuilding = good, rebuilding... in the process of becoming not a spare
my $disk_status='good';
if (
( $line =~ /active/ ) ||
( $line =~ /rebuilding/ )
){
$disk_status='good';
}
if ( $line =~ /spare/ ){
$disk_status='spare';
}
if (
( $line =~ /spare/ ) &&
( $line =~ /rebuilding/ )
){
$disk_status='good';
}
if ( $line =~ /removed/ ){
$disk_status='bad';
}
$line=~s/^.*[\t ]//;
push(@{ $return_hash{devices}{$dev}{$disk_status} }, $line);
}{
if ( $line =~ /^[\t ]*State/ ){
# good states...
# clean
# active
# bad states...
# degraded
# inactive
# rebuilding states...
# resyncing
# recovering
# clean, degraded = degraded
# clean, degraded, recovering = rebuilding
if (
( $line =~ /clean/ ) ||
( $line =~ /active/ )
){
$return_hash{devices}{$dev}{status}='good';
}
if ( $line =~ /degraded/ ){
$return_hash{devices}{$dev}{status}='bad';
}
if (
( $line =~ /recovering/ ) ||
( $line =~ /resyncing/ )
){
$return_hash{devices}{$dev}{status}='rebuilding';
}
if ( $line =~ /inactive/ ){
$return_hash{devices}{$dev}{status}='bad';
}
}elsif( $line =~ /^[\t ]*Raid\ Level[\t ]*\:[\t ]*/ ){
$line=~s/^[\t ]*Raid\ Level[\t ]*\:[\t ]*//;
$return_hash{devices}{$dev}{type}=$line;
}
}
}
}
return %return_hash;
}
=head2 usable
Returns a perl boolean for if it is usable or not.
my $usable=$backend->usable;
if ( ! $usable ){
print "This backend is not usable.\n";
}
=cut
sub usable {
my $self=$_[0];
if ( $^O !~ 'linux' ){
$self->{usable}=0;
return 0;
}
# make sure we can locate mdadm
my $mdadm_bin=`/bin/sh -c 'which mdadm 2> /dev/null'`;
if ( $? != 0 ){
$self->{usable}=0;
return 0;
}
chomp($mdadm_bin);
$self->{mdadm_bin}=$mdadm_bin;
# make sure we have atleast one device
my $raw=`mdadm --detail --scan`;
if ( $raw !~ /^ARRAY/ ){
$self->{usable}=0;
return 0;
}
$self->{usable}=1;
return 1;
}
=head1 AUTHOR
Zane C. Bowers-Hadley, C<< <vvelox at vvelox.net> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-device-raid-poller at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Device-RAID-Poller>. I will be
notified, and then you'll automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Device::RAID::Poller
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker (report bugs here)
L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Device-RAID-Poller>
=item * AnnoCPAN: Annotated CPAN documentation
L<http://annocpan.org/dist/Device-RAID-Poller>
=item * CPAN Ratings
L<https://cpanratings.perl.org/d/Device-RAID-Poller>
=item * Search CPAN
L<https://metacpan.org/release/Device-RAID-Poller>
=back
=head1 ACKNOWLEDGEMENTS
=head1 LICENSE AND COPYRIGHT
This software is Copyright (c) 2019 by Zane C. Bowers-Hadley.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
=cut
1; # End of Device::RAID::Poller