File Coverage

blib/lib/Device/RAID/Poller/Backends/Linux_mdadm.pm
Criterion Covered Total %
statement 8 76 10.5
branch 0 36 0.0
condition 0 12 0.0
subroutine 3 6 50.0
pod 3 3 100.0
total 14 133 10.5


line stmt bran cond sub pod time code
1             package Device::RAID::Poller::Backends::Linux_mdadm;
2              
3 1     1   66133 use 5.006;
  1         13  
4 1     1   5 use strict;
  1         2  
  1         20  
5 1     1   5 use warnings;
  1         1  
  1         948  
6              
7             =head1 NAME
8              
9             Device::RAID::Poller::Backends::Linux_mdadm - Handles Linux mdadm software RAID.
10              
11             =head1 VERSION
12              
13             Version 0.0.0
14              
15             =cut
16              
17             our $VERSION = '0.0.0';
18              
19              
20             =head1 SYNOPSIS
21              
22             use Device::RAID::Poller::Backends::Linux_mdadm;
23            
24             my $backend = Device::RAID::Poller::Backends::Linux_mdadm->new;
25            
26             my $usable=$backend->usable;
27             my %return_hash;
28             if ( $usable ){
29             %return_hash=$backend->run;
30             my %status=$backend->run;
31             use Data::Dumper;
32             print Dumper( \%status );
33             }
34              
35             =head1 METHODS
36              
37             =head2 new
38              
39             Initiates the backend object.
40              
41             my $backend = Device::RAID::Poller::Backends::Linux_mdadm->new;
42              
43             =cut
44              
45             sub new {
46 0     0 1   my $self = {
47             usable=>0,
48             };
49 0           bless $self;
50              
51 0           return $self;
52             }
53              
54             =head2 run
55              
56             Runs the poller backend and report the results.
57              
58             If nothing is nothing is loaded, load will be called.
59              
60             my %status=$backend->run;
61             use Data::Dumper;
62             print Dumper( \%status );
63              
64             =cut
65              
66             sub run {
67 0     0 1   my $self=$_[0];
68              
69 0           my %return_hash=(
70             'status'=>0,
71             'devices'=>{},
72             );
73              
74             # if not usable, no point in continuing
75 0 0         if ( ! $self->{usable} ){
76 0           return %return_hash;
77             }
78              
79 0           $return_hash{status}=1;
80              
81             # get a list of devices
82 0           my $raw=`mdadm --detail --scan`;
83 0           my @raw_split=split(/\n/, $raw);
84 0           my @devs;
85 0           foreach my $line (@raw_split){
86 0 0         if ( $line =~ /^ARRAY/ ){
87 0           my @line_split=split(/[\t ]+/, $line);
88 0           push(@devs, $line_split[1]);
89             }
90             }
91              
92             # Process each md device that exists.
93 0           foreach my $dev (@devs){
94 0           $return_hash{devices}{$dev}={
95             'backend'=>'Linux_mdadm',
96             'name'=>$dev,
97             'good'=>[],
98             'bad'=>[],
99             'spare'=>[],
100             'type'=>'mdadm',
101             'BBUstatus'=>'na',
102             'status'=>'unknown',
103             };
104              
105             # check device and break it appart
106 0           $raw=`mdadm --detail $dev`;
107 0           @raw_split=split(/\n/, $raw);
108 0           my $number_found=0;
109 0           my $process=0;
110 0           foreach my $line (@raw_split){
111 0           chomp($line);
112              
113 0 0         if ( $line =~ /[\t ]*Number/ ){
    0          
114 0           $number_found=1;
115             }elsif( $number_found ){
116 0           $process=1;
117             }
118              
119 0 0         if ( $process ){
120             # good disk...
121             # active
122             # rebuilding
123             # bad disk...
124             # removed
125             # spare disks...
126             # spare
127              
128             # spare rebuilding = good, rebuilding... in the process of becoming not a spare
129              
130 0           my $disk_status='good';
131 0 0 0       if (
132             ( $line =~ /active/ ) ||
133             ( $line =~ /rebuilding/ )
134             ){
135 0           $disk_status='good';
136             }
137              
138 0 0         if ( $line =~ /spare/ ){
139 0           $disk_status='spare';
140             }
141              
142 0 0 0       if (
143             ( $line =~ /spare/ ) &&
144             ( $line =~ /rebuilding/ )
145             ){
146 0           $disk_status='good';
147             }
148              
149 0 0         if ( $line =~ /removed/ ){
150 0           $disk_status='bad';
151             }
152              
153 0           $line=~s/^.*[\t ]//;
154 0           push(@{ $return_hash{devices}{$dev}{$disk_status} }, $line);
  0            
155             }{
156 0 0         if ( $line =~ /^[\t ]*State/ ){
  0 0          
157             # good states...
158             # clean
159             # active
160             # bad states...
161             # degraded
162             # inactive
163             # rebuilding states...
164             # resyncing
165             # recovering
166              
167             # clean, degraded = degraded
168             # clean, degraded, recovering = rebuilding
169              
170 0 0 0       if (
171             ( $line =~ /clean/ ) ||
172             ( $line =~ /active/ )
173             ){
174 0           $return_hash{devices}{$dev}{status}='good';
175             }
176              
177 0 0         if ( $line =~ /degraded/ ){
178 0           $return_hash{devices}{$dev}{status}='bad';
179             }
180              
181 0 0 0       if (
182             ( $line =~ /recovering/ ) ||
183             ( $line =~ /resyncing/ )
184             ){
185 0           $return_hash{devices}{$dev}{status}='rebuilding';
186             }
187              
188 0 0         if ( $line =~ /inactive/ ){
189 0           $return_hash{devices}{$dev}{status}='bad';
190             }
191              
192             }elsif( $line =~ /^[\t ]*Raid\ Level[\t ]*\:[\t ]*/ ){
193 0           $line=~s/^[\t ]*Raid\ Level[\t ]*\:[\t ]*//;
194 0           $return_hash{devices}{$dev}{type}=$line;
195             }
196             }
197              
198             }
199             }
200              
201 0           return %return_hash;
202             }
203              
204             =head2 usable
205              
206             Returns a perl boolean for if it is usable or not.
207              
208             my $usable=$backend->usable;
209             if ( ! $usable ){
210             print "This backend is not usable.\n";
211             }
212              
213             =cut
214              
215             sub usable {
216 0     0 1   my $self=$_[0];
217              
218 0 0         if ( $^O !~ 'linux' ){
219 0           $self->{usable}=0;
220 0           return 0;
221             }
222              
223             # make sure we can locate mdadm
224 0           my $mdadm_bin=`/bin/sh -c 'which mdadm 2> /dev/null'`;
225 0 0         if ( $? != 0 ){
226 0           $self->{usable}=0;
227 0           return 0;
228             }
229 0           chomp($mdadm_bin);
230 0           $self->{mdadm_bin}=$mdadm_bin;
231              
232             # make sure we have atleast one device
233 0           my $raw=`mdadm --detail --scan`;
234 0 0         if ( $raw !~ /^ARRAY/ ){
235 0           $self->{usable}=0;
236 0           return 0;
237             }
238              
239 0           $self->{usable}=1;
240 0           return 1;
241             }
242              
243             =head1 AUTHOR
244              
245             Zane C. Bowers-Hadley, C<< >>
246              
247             =head1 BUGS
248              
249             Please report any bugs or feature requests to C, or through
250             the web interface at L. I will be
251             notified, and then you'll automatically be notified of progress on your bug as I make changes.
252              
253             =head1 SUPPORT
254              
255             You can find documentation for this module with the perldoc command.
256              
257             perldoc Device::RAID::Poller
258              
259              
260             You can also look for information at:
261              
262             =over 4
263              
264             =item * RT: CPAN's request tracker (report bugs here)
265              
266             L
267              
268             =item * AnnoCPAN: Annotated CPAN documentation
269              
270             L
271              
272             =item * CPAN Ratings
273              
274             L
275              
276             =item * Search CPAN
277              
278             L
279              
280             =back
281              
282              
283             =head1 ACKNOWLEDGEMENTS
284              
285              
286             =head1 LICENSE AND COPYRIGHT
287              
288             This software is Copyright (c) 2019 by Zane C. Bowers-Hadley.
289              
290             This is free software, licensed under:
291              
292             The Artistic License 2.0 (GPL Compatible)
293              
294              
295             =cut
296              
297             1; # End of Device::RAID::Poller