File Coverage

blib/lib/Parse/cfggen.pm
Criterion Covered Total %
statement 6 81 7.4
branch 0 36 0.0
condition n/a
subroutine 2 6 33.3
pod 4 4 100.0
total 12 127 9.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2              
3             # Copyright 2012 Mathieu Alorent.
4             #
5             # This program is free software; you can redistribute it and/or modify it
6             # under the terms of either: the GNU General Public License as published
7             # by the Free Software Foundation; or the Artistic License.
8             #
9             # See http://dev.perl.org/licenses/ for more information.
10              
11             package Parse::cfggen;
12              
13 1     1   19134 use warnings;
  1         3  
  1         28  
14 1     1   6 use strict;
  1         1  
  1         984  
15              
16             =head1 NAME
17              
18             Parse::cfggen - Parse the output of cfggen utility.
19              
20             =head1 VERSION
21              
22             Version 0.01
23              
24             =cut
25              
26             our $VERSION = '0.02';
27              
28             =head1 SYNOPSIS
29              
30             Parse::cfggen parses the output of C utility to allow
31             programmatic access to the RAID configuration information provided by the
32             cfggen utility on LSI RAID cards.
33              
34             use Parse::cfggen;
35              
36             my $cfggen = Parse::cfggen->new();
37              
38             Run the C tool directly to query the hardware (requires root):
39              
40             my $controllers = $cfggen->parse_config();
41            
42             Parse a text file created already by running C tool:
43              
44             my $controllers = $cfggen->parse_config_file("foo.txt");
45              
46             Read from a file descriptor already opened by the program:
47              
48             my $controllers = $cfggen->parse_config_fh(\*STDIN);
49              
50             =head1 SUBROUTINES/METHODS
51              
52             =head2 new
53              
54             Return an instance of the Parse::cfggen class that can be used to parse
55             input in one of several ways.
56              
57             =cut
58              
59             sub new
60             {
61 0     0 1   my ($class, $config, $plugin) = @_;
62 0           my $self = {};
63 0           $self->{_controllers} = {};
64              
65 0           bless($self, $class);
66 0           return $self;
67             }
68              
69             =head2 parse_config
70              
71             Attempt to run the cfggen utility, and parse the output. This command
72             actually uses parse_config_fh() after opening a pipe to the relevant command.
73              
74             The commands that are actually run are approximately:
75              
76             =over 4
77              
78             cfggen LIST
79             cfggen 0 DISPLAY
80             cfggen 1 DISPLAY
81             cfggen ... DISPLAY
82              
83             =back
84              
85             This command requires root access, and Parse::cfggen makes no attempt to
86             use sudo or any other method to gain root access. It is recommended to call
87             your script which uses this module as root.
88              
89             The parse_config_fh() and parse_config_file() will expect output equivalent
90             to that from the above command.
91              
92             =cut
93              
94             sub parse_config
95             {
96 0     0 1   my ($self) = @_;
97              
98 0           my $cfggen = "/usr/sbin/cfggen";
99 0           my $command = sprintf("%s %s|", $cfggen, 'LIST');
100 0           my @ctrls = ();
101              
102             # list controllers
103 0 0         if(open LIST, $command) {
104 0           while () {
105 0 0         next unless $_ =~ /^\s+(\d+)\s+\W/;
106 0           push @ctrls, $1;
107             }
108 0           close LIST;
109             }
110              
111             # parse controlers
112 0           my $c = undef;
113 0           foreach my $ctrl (@ctrls) {
114 0           $command = sprintf("%s %s|", $cfggen, "$ctrl DISPLAY");
115 0           my $fh;
116 0 0         if(open $fh, $command)
117             {
118 0           $c = $self->parse_config_fh($fh);
119 0           close $fh;
120             }
121             }
122 0           return $c;
123             }
124              
125             =head2 parse_config_file
126              
127             Open and parse a file containing the output from cfggen.
128              
129             =cut
130              
131             sub parse_config_file
132             {
133 0     0 1   my ($self, $file) = @_;
134              
135 0           my $fh;
136 0 0         if(open $fh, "<".$file)
137             {
138 0           my $c = $self->parse_config_fh($fh);
139 0           close $fh;
140 0           return $c;
141             }
142 0           return undef;
143              
144             }
145              
146             =head2 parse_config_fh
147              
148             Read from the file handle and parse it, returning a hash-of-hashes.
149              
150             =cut
151              
152             sub parse_config_fh
153             {
154 0     0 1   my ($self, $fh) = @_;
155              
156 0           my $current_controller = 0;
157 0           my $current_logical_drive = undef;
158 0           my $current_physical_drive = undef;
159 0           my $ctrl = undef;
160 0           my $line = undef;
161 0           my $controller = $self->{_controller};
162              
163 0           LEVEL1: while($line = <$fh>)
164             {
165 0           chomp $line;
166              
167 0 0         next if($line =~ /^$/);
168 0 0         next if($line =~ /^-+$/);
169              
170 0 0         if($line =~ /^Read configuration has been initiated for controller (\d+)$/) {
171 0           $current_controller = $1;
172             }
173              
174 0 0         if($line =~ /^Controller information/) {
    0          
    0          
175 0           $controller->{$current_controller} = {};
176 0           $ctrl = $controller->{$current_controller};
177              
178 0           $line = <$fh>;
179              
180 0           while($line = <$fh>) {
181 0           chomp $line;
182              
183 0 0         if ($line =~ /^\s+(.*\w\)?)\s+:\s+(.*)$/) {
    0          
184 0           my $key = $1;
185 0           $key =~ tr/\#//;
186 0           $ctrl->{$key} = $2;
187             } elsif ($line =~ /^-+$/) {
188 0           last;
189             }
190             }
191             } elsif($line =~ /^IR Volume information/) {
192 0           $current_logical_drive = undef;
193              
194 0           $line = <$fh>;
195              
196 0           while($line = <$fh>) {
197 0           chomp $line;
198              
199 0 0         if ( $line =~ /^IR volume (\d+)$/ ) {
    0          
    0          
200 0           $current_logical_drive = $1;
201             } elsif ($line =~ /^\s+(.*\w\)?)\s+:\s+(.*)$/) {
202 0           my $key = $1;
203 0           $key =~ tr/\#//;
204             #$key =~ tr#+.:/'&()-##;
205 0           $ctrl->{logical_drive}{$current_logical_drive}{$key} = $2;
206             } elsif ($line =~ /^-+$/) {
207 0           last;
208             }
209             }
210             } elsif($line =~ /^Physical device information/) {
211 0           $current_physical_drive = undef;
212              
213 0           $line = <$fh>;
214              
215 0           while($line = <$fh>) {
216 0           chomp $line;
217              
218 0 0         if ( $line =~ /^Target on ID #(\d+)$/ ) {
    0          
    0          
219 0           $current_physical_drive = $1;
220             } elsif ($line =~ /^\s+(.*\w\)?( \#)?)\s+:\s+(.*)$/) {
221 0           my $key = $1;
222 0           $key =~ tr/\#//;
223             #$key =~ tr#+.:/'&()-##;
224 0           $ctrl->{physical_drive}{$current_physical_drive}{$key} = $3;
225 0           $ctrl->{physical_drive}{$current_physical_drive}{$key} =~ s/\s*(\w*\s*\w)\s*/$1/;
226             } elsif ($line =~ /^-+$/) {
227 0           last;
228             }
229             }
230             }
231             }
232            
233 0           return $controller;
234             }
235              
236             =head1 AUTHOR
237              
238             Mathieu Alorent, C<< >>
239              
240             =head1 BUGS
241              
242             Please report any bugs or feature requests to C, or through
243             the web interface at L. I will be notified, and then you'll
244             automatically be notified of progress on your bug as I make changes.
245              
246             =head1 SUPPORT
247              
248             You can find documentation for this module with the perldoc command.
249              
250             perldoc Parse::cfggen
251              
252              
253             You can also look for information at:
254              
255             =over 4
256              
257             =item * Source code
258              
259             L
260              
261             =item * RT: CPAN's request tracker
262              
263             L
264              
265             =item * AnnoCPAN: Annotated CPAN documentation
266              
267             L
268              
269             =item * CPAN Ratings
270              
271             L
272              
273             =item * Search CPAN
274              
275             L
276              
277             =back
278              
279              
280             =head1 ACKNOWLEDGEMENTS
281              
282              
283             =head1 LICENSE AND COPYRIGHT
284              
285             Copyright 2012 Mathieu Alorent.
286              
287             This program is free software; you can redistribute it and/or modify it
288             under the terms of either: the GNU General Public License as published
289             by the Free Software Foundation; or the Artistic License.
290              
291             See http://dev.perl.org/licenses/ for more information.
292              
293             This program is based on Parse::HP::ACU a work of Jeremy Cole.
294              
295              
296             =cut
297              
298             1; # End of Parse::cfggen