File Coverage

blib/lib/Device/RAID/Poller/Backends/Adaptec_arcconf.pm
Criterion Covered Total %
statement 8 87 9.2
branch 0 36 0.0
condition 0 27 0.0
subroutine 3 6 50.0
pod 3 3 100.0
total 14 159 8.8


line stmt bran cond sub pod time code
1             package Device::RAID::Poller::Backends::Adaptec_arcconf;
2              
3 1     1   65246 use 5.006;
  1         14  
4 1     1   7 use strict;
  1         2  
  1         22  
5 1     1   4 use warnings;
  1         2  
  1         1230  
6              
7             =head1 NAME
8              
9             Device::RAID::Poller::Backends::Adaptec_arcconf - Handles polling using the Adaptec arcconf utility.
10              
11             =head1 VERSION
12              
13             Version 0.0.1
14              
15             =cut
16              
17             our $VERSION = '0.0.1';
18              
19              
20             =head1 SYNOPSIS
21              
22             use Device::RAID::Poller::Backends::Adaptec_arcconf;
23            
24             my $backend = Device::RAID::Poller::Backends::Adaptec_arcconf->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::Adaptec_arcconf->new;
42              
43             =cut
44              
45             sub new {
46 0     0 1   my $self = {
47             usable=>0,
48             adapters=>0,
49             };
50 0           bless $self;
51              
52 0           return $self;
53             }
54              
55             =head2 run
56              
57             Runs the poller backend and report the results.
58              
59             If nothing is nothing is loaded, load will be called.
60              
61             my %status=$backend->run;
62             use Data::Dumper;
63             print Dumper( \%status );
64              
65             =cut
66              
67             sub run {
68 0     0 1   my $self=$_[0];
69              
70 0           my %return_hash=(
71             'status'=>0,
72             'devices'=>{},
73             );
74              
75             # if not usable, no point in continuing
76 0 0         if ( ! $self->{usable} ){
77 0           return %return_hash;
78             }
79              
80             # get a list of devices
81 0           my $adapter=1;
82 0           while( $adapter <= $self->{adapters} ){
83 0           my $raw=`arcconf GETCONFIG $adapter AD`;
84 0           my @raw_split=split(/\n/, $raw);
85              
86             # Figures out the BBU status
87 0           my $bbustatus='unknown';
88 0           my @backup_lines=grep(/Overall\ Backup\ Unit\ Status/, @raw_split);
89 0 0 0       if (
    0 0        
    0 0        
      0        
90             defined($backup_lines[0]) &&
91             (
92             ( $backup_lines[0] =~ /\:[\t ]*Ready/ ) ||
93             ( $backup_lines[0] =~ /Normal/ )
94             )
95             ){
96             # If this matches, it should be good.
97             # Can't match just /Ready/ as it will also match "Not Ready".
98 0           $bbustatus='good';
99             }elsif(
100             defined($backup_lines[0]) &&
101             (
102             ( $backup_lines[0] =~ /Invalid/ ) ||
103             ( $backup_lines[0] =~ /Not\ Present/ )
104             )
105             ){
106 0           $bbustatus='na';
107             }elsif( defined($backup_lines[0]) ){
108             # If we are here, we did not match it as being good or not present
109 0           $bbustatus='bad';
110             }
111              
112             # Grab the LD config.
113 0           $raw=`arcconf GETCONFIG $adapter LD`;
114 0           @raw_split=split(/\n/, $raw);
115 0           my $LDN=undef;
116 0           my $dev=undef;
117 0           foreach my $line (@raw_split){
118 0 0         if ( $line =~ /Logical Device number/ ){
119 0           $line=~s/[\t ]*Logical Device number[\t ]*//;
120 0           $LDN=$line;
121 0           $dev='arcconf '.$adapter.'-'.$LDN;
122 0           $return_hash{devices}{$dev}={
123             'backend'=>'Adaptec_arcconf',
124             'name'=>$dev,
125             'good'=>[],
126             'bad'=>[],
127             'spare'=>[],
128             'type'=>'unknown',
129             'BBUstatus'=>$bbustatus,
130             'status'=>'unknown',
131             };
132             }
133              
134             # If we have a LDN, then we are in a LD information section of the output
135 0 0         if ( $line =~ /Status\ of\ Logical\ Device/ ){
    0          
    0          
    0          
136 0           $line=~s/[\t ]*Status\ of\ Logical\ Device\:[\t ]*//;
137 0 0 0       if (
    0 0        
      0        
138             ( $line =~ /Optimal/ ) ||
139             (
140             ( $line =~ /Reconfiguring/ ) &&
141             ( $line !~ /Degraded/ ) &&
142             ( $line !~ /Suboptimal/ )
143             )
144             ){
145             # Optimal appears to be the only fully good one.
146             # Reconfiguring not paired with either Suboptimal or Degraded is good
147 0           $return_hash{devices}{$dev}{status}='good';
148             }elsif( $line =~ /Rebuilding/ ){
149             # Should match either of the two below.
150             # Suboptimal, Rebuilding
151             # Degraded, Rebuilding
152 0           $return_hash{devices}{$dev}{status}='rebuilding';
153             }else{
154             # Anything else is bad.
155 0           $return_hash{devices}{$dev}{status}='bad';
156             }
157             }elsif( $line =~ /RAID\ level/ ){
158 0           $line=~s/[\t ]*RAID\ level[\t ]*\:[\t ]*//;
159 0           $return_hash{devices}{$dev}{type}=$line;
160             }elsif( $line =~ /[\t ]*Segment [0123456789]/ ){
161 0           $line =~ s/[\t ]*Segment [0123456789]*[\t ]*\:[\t ]*//;
162 0 0         if ( $line =~ /Present/ ){
    0          
163 0           $line=~s/Present[\t ]*//;
164 0           push( @{ $return_hash{devices}{$dev}{good} }, $line );
  0            
165             }elsif( $line =~ /Missing/ ){
166             # The disk is is just missing.
167 0           push( @{ $return_hash{devices}{$dev}{bad} }, $line );
  0            
168             }else{
169 0           $line=~s/[A-Za-z\t ]*//;
170 0           push( @{ $return_hash{devices}{$dev}{bad} }, $line );
  0            
171             }
172             }elsif( $line =~ /Logical\ Device\ name/ ){
173 0           $line =~ s/[\t ]*Logical\ Device\ name[\t ]*\:[\t ]*//;
174 0           my $new_dev=$dev.' - '.$line;
175 0           $return_hash{devices}{$new_dev}= delete $return_hash{devices}{$dev};
176 0           $dev=$new_dev;
177 0           $return_hash{devices}{$dev}{name}=$dev;
178             }
179             }
180              
181 0           $adapter++;
182             }
183 0           $return_hash{status}=1;
184 0           return %return_hash;
185             }
186              
187             =head2 usable
188              
189             Returns a perl boolean for if it is usable or not.
190              
191             my $usable=$backend->usable;
192             if ( ! $usable ){
193             print "This backend is not usable.\n";
194             }
195              
196             =cut
197              
198             sub usable {
199 0     0 1   my $self=$_[0];
200              
201 0 0 0       if (
202             ( $^O !~ 'linux' ) &&
203             ( $^O !~ 'freebsd' )
204             ){
205 0           $self->{usable}=0;
206 0           return 0;
207             }
208              
209             # make sure we can locate arcconf
210 0           my $arcconf_bin=`/bin/sh -c 'which arcconf 2> /dev/null'`;
211 0 0         if ( $? != 0 ){
212 0           $self->{usable}=0;
213 0           return 0;
214             }
215              
216             # make sure we have atleast one device
217 0           my $raw=`arcconf LIST`;
218 0 0         if ( $? != 0 ){
219 0           $self->{usable}=0;
220 0           return 0;
221             }
222 0           my @raw_split=split(/\n/, $raw);
223 0           my @found_lines=grep(/Controllers\ found/, @raw_split);
224 0 0         if (defined( $found_lines[0] )){
225             # grab the first and should be online line, which should be formatted like below...
226             # Controllers found: 1
227 0           my $found=$found_lines[0];
228 0           chomp($found);
229 0           $found=~s/.*\:[\t ]*//;
230 0 0 0       if (
231             ( $found =~ /[0123456789]+/ ) &&
232             ( $found > 0 )
233             ){
234 0           $self->{adapters}=$found;
235             }else{
236             # either contains extra characters or zero
237 0           $self->{usable}=0;
238 0           return 0;
239             }
240             }else{
241             # Command errored in some way or output changed.
242 0           $self->{usable}=0;
243 0           return 0;
244             }
245              
246 0           $self->{usable}=1;
247 0           return 1;
248             }
249              
250             =head1 AUTHOR
251              
252             Zane C. Bowers-Hadley, C<< >>
253              
254             =head1 BUGS
255              
256             Please report any bugs or feature requests to C, or through
257             the web interface at L. I will be
258             notified, and then you'll automatically be notified of progress on your bug as I make changes.
259              
260             =head1 SUPPORT
261              
262             You can find documentation for this module with the perldoc command.
263              
264             perldoc Device::RAID::Poller
265              
266              
267             You can also look for information at:
268              
269             =over 4
270              
271             =item * RT: CPAN's request tracker (report bugs here)
272              
273             L
274              
275             =item * AnnoCPAN: Annotated CPAN documentation
276              
277             L
278              
279             =item * CPAN Ratings
280              
281             L
282              
283             =item * Search CPAN
284              
285             L
286              
287             =back
288              
289              
290             =head1 ACKNOWLEDGEMENTS
291              
292              
293             =head1 LICENSE AND COPYRIGHT
294              
295             This software is Copyright (c) 2019 by Zane C. Bowers-Hadley.
296              
297             This is free software, licensed under:
298              
299             The Artistic License 2.0 (GPL Compatible)
300              
301              
302             =cut
303              
304             1; # End of Device::RAID::Poller