File Coverage

blib/lib/Device/RAID/Poller/Backends/FBSD_graid.pm
Criterion Covered Total %
statement 8 70 11.4
branch 0 30 0.0
condition 0 3 0.0
subroutine 3 6 50.0
pod 3 3 100.0
total 14 112 12.5


line stmt bran cond sub pod time code
1              
2             package Device::RAID::Poller::Backends::FBSD_graid;
3              
4 1     1   65217 use 5.006;
  1         11  
5 1     1   7 use strict;
  1         2  
  1         29  
6 1     1   6 use warnings;
  1         2  
  1         856  
7              
8             =head1 NAME
9              
10             Device::RAID::Poller::Backends::FBSD_graid - FreeBSD GEOM RAID backend.
11              
12             =head1 VERSION
13              
14             Version 0.0.0
15              
16             =cut
17              
18             our $VERSION = '0.0.0';
19              
20              
21             =head1 SYNOPSIS
22              
23             use Device::RAID::Poller::Backends::FBSD_graid;
24            
25             my $backend = Device::RAID::Poller::Backends::FBSD_graid->new;
26            
27             my $usable=$backend->usable;
28             my %return_hash;
29             if ( $usable ){
30             %return_hash=$backend->run;
31             my %status=$backend->run;
32             use Data::Dumper;
33             print Dumper( \%status );
34             }
35              
36             =head1 METHODS
37              
38             =head2 new
39              
40             Initiates the backend object.
41              
42             my $backend = Device::RAID::Poller::Backends::FBSD_graid->new;
43              
44             =cut
45              
46             sub new {
47 0     0 1   my $self = {
48             usable=>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             # Fetch the raw gmirror status.
81 0           my $raw=`/sbin/graid status`;
82 0 0         if ( $? != 0 ){
83 0           return %return_hash;
84             }
85              
86 0           my @raw_split=split( /\n/, $raw );
87              
88             # The first line contains nothing of interest.
89 0           shift @raw_split;
90              
91 0           my $dev=undef;
92 0           foreach my $line (@raw_split){
93 0           my @line_split=split( /[\t ]+/, $line );
94              
95             # lines starting with mirror mean we have a new dev
96 0 0         if ( $line_split[0] =~ /^raid/ ){
97 0           $dev=$line_split[0];
98              
99             # attempt to find the RAID level for the current device
100 0           my $raid_name=$dev;
101 0           $raid_name=~s/^raid\///;
102 0           my $level='unknown';
103 0           my $list_raw=~`/sbin/graid list $raid_name`;
104 0 0         if ( $? == 0 ){
105 0           my @list_split=split(/\n/, $list_raw);
106 0           my @levels=grep(/RAIDLevel\:/, @list_split);
107 0 0         if ( defined( $levels[0] ) ){
108 0           my $level=$levels[0];
109 0           chomp($level);
110 0           $level=~s/[\t ]*RAIDLevel\:[\t ]*//;
111             }
112             }
113              
114             #create the device if needed in the return hash
115 0 0         if ( ! defined( $return_hash{$dev} ) ){
116 0           $return_hash{devices}{$dev}={
117             'backend'=>'FBSD_graid',
118             'name'=>$dev,
119             'good'=>[],
120             'bad'=>[],
121             'spare'=>[],
122             'type'=>$level,
123             'BBUstatus'=>'na',
124             'status'=>'unknown',
125             };
126             }
127              
128             # Check known mirror status values.
129 0 0         if ( $line_split[1] =~ /OPTIMAL/ ){
    0          
    0          
130 0           $return_hash{devices}{$dev}{status}='good';
131             }elsif( $line_split[1] =~ /DEGRADED/ ){
132 0           $return_hash{devices}{$dev}{status}='bad';
133             }elsif( $line_split[1] =~ /BROKEN/ ){
134 0           $return_hash{devices}{$dev}{status}='bad';
135             }
136              
137             # Check known disk status values.
138 0 0         if ( $line_split[3] =~ /REBUILD/ ){
    0          
139 0           $return_hash{devices}{$dev}{status}='rebuilding';
140 0           push( @{ $return_hash{devices}{$dev}{good} }, $line_split[2] );
  0            
141             }elsif( $line_split[3] =~ /ACTIVE/ ){
142 0           push( @{ $return_hash{devices}{$dev}{good} }, $line_split[2] );
  0            
143             }else{
144 0           push( @{ $return_hash{devices}{$dev}{bad} }, $line_split[2] );
  0            
145             }
146              
147             }else{
148             # Check known disk status values.
149             # Values pulled from sys/geom/mirror/g_mirror.c
150 0 0         if ( $line_split[2] =~ /REBUILD/ ){
    0          
151 0           $return_hash{$dev}{status}='rebuilding';
152 0           push( @{ $return_hash{devices}{$dev}{good} }, $line_split[1] );
  0            
153             }elsif( $line_split[2] =~ /ACTIVE/ ){
154 0           push( @{ $return_hash{devices}{$dev}{good} }, $line_split[1] );
  0            
155             }else{
156 0           push( @{ $return_hash{devices}{$dev}{bad} }, $line_split[1] );
  0            
157             }
158             }
159             }
160              
161 0           $return_hash{status}=1;
162              
163 0           return %return_hash;
164             }
165              
166             =head2 usable
167              
168             Returns a perl boolean for if it is usable or not.
169              
170             my $usable=$backend->usable;
171             if ( ! $usable ){
172             print "This backend is not usable.\n";
173             }
174              
175             =cut
176              
177             sub usable {
178 0     0 1   my $self=$_[0];
179              
180 0 0 0       if (
181             ( $^O !~ 'freebsd' ) &&
182             ( ! -x '/sbin/graid' )
183             ){
184 0           $self->{usable}=0;
185 0           return 0;
186             }
187              
188             # Test for it this way as '/sbin/kldstat -q -n geom_raid3' will error
189             # if it is compiled in.
190 0           system('/sbin/sysctl -q kern.geom.raid.enable > /dev/null');
191 0 0         if ( $? != 0 ){
192 0           $self->{usable}=0;
193 0           return 0;
194             }
195              
196 0           $self->{usable}=1;
197 0           return 1;
198             }
199              
200             =head1 AUTHOR
201              
202             Zane C. Bowers-Hadley, C<< >>
203              
204             =head1 BUGS
205              
206             Please report any bugs or feature requests to C, or through
207             the web interface at L. I will be
208             notified, and then you'll automatically be notified of progress on your bug as I make changes.
209              
210              
211              
212              
213             =head1 SUPPORT
214              
215             You can find documentation for this module with the perldoc command.
216              
217             perldoc Device::RAID::Poller
218              
219              
220             You can also look for information at:
221              
222             =over 4
223              
224             =item * RT: CPAN's request tracker (report bugs here)
225              
226             L
227              
228             =item * AnnoCPAN: Annotated CPAN documentation
229              
230             L
231              
232             =item * CPAN Ratings
233              
234             L
235              
236             =item * Search CPAN
237              
238             L
239              
240             =back
241              
242              
243             =head1 ACKNOWLEDGEMENTS
244              
245              
246             =head1 LICENSE AND COPYRIGHT
247              
248             This software is Copyright (c) 2019 by Zane C. Bowers-Hadley.
249              
250             This is free software, licensed under:
251              
252             The Artistic License 2.0 (GPL Compatible)
253              
254              
255             =cut
256              
257             1; # End of Device::RAID::Poller