File Coverage

blib/lib/NetApp/Filer/Export.pm
Criterion Covered Total %
statement 33 248 13.3
branch 9 92 9.7
condition 7 42 16.6
subroutine 6 31 19.3
pod 24 25 96.0
total 79 438 18.0


line stmt bran cond sub pod time code
1              
2             package NetApp::Filer::Export;
3              
4             our $VERSION = '500.002';
5             $VERSION = eval $VERSION; ## no critic: StringyEval
6              
7 7     7   39 use strict;
  7         13  
  7         214  
8 7     7   34 use warnings;
  7         12  
  7         170  
9 7     7   35 use Carp;
  7         44  
  7         487  
10              
11 7     7   40 use Class::Std;
  7         13  
  7         42  
12 7     7   712 use Params::Validate qw( :all );
  7         22  
  7         25497  
13              
14             {
15              
16             my %filer_of :ATTR( get => 'filer' );
17              
18             my %type_of :ATTR( get => 'type' );
19             my %active_of :ATTR( get => 'active', set => 'active' );
20              
21             my %path_of :ATTR( get => 'path' );
22             my %actual_of :ATTR( get => 'actual' );
23              
24             my %nosuid_of :ATTR( get => 'nosuid', set => 'nosuid' );
25             my %anon_of :ATTR( get => 'anon', set => 'anon' );
26              
27             my %sec_of :ATTR;
28             my %root_of :ATTR;
29              
30             my %rw_all_of :ATTR( get => 'rw_all' );
31             my %ro_all_of :ATTR( get => 'ro_all' );
32             my %rw_of :ATTR;
33             my %ro_of :ATTR;
34              
35             sub BUILD {
36              
37 0     0 0 0 my ($self,$ident,$args_ref) = @_;
38              
39 0         0 my @args = %$args_ref;
40              
41 0         0 my (%args) = validate( @args, {
42             filer => { isa => 'NetApp::Filer' },
43             type => { type => SCALAR,
44             default => 'permanent',
45             regex => qr{^(permanent|temporary)$},
46             optional => 1 },
47             active => { type => SCALAR,
48             default => 1,
49             optional => 1 },
50             path => { type => SCALAR },
51             actual => { type => SCALAR,
52             default => "",
53             optional => 1 },
54             nosuid => { type => SCALAR,
55             default => 0,
56             optional => 1 },
57             anon => { type => SCALAR | UNDEF,
58             default => undef,
59             optional => 1 },
60             sec => { type => ARRAYREF,
61             default => [qw(sys)],
62             optional => 1 },
63             root => { type => ARRAYREF,
64             default => [],
65             optional => 1 },
66             rw_all => { type => SCALAR,
67             optional => 1 },
68             rw => { type => ARRAYREF,
69             default => [],
70             optional => 1 },
71             ro_all => { type => SCALAR,
72             optional => 1 },
73             ro => { type => ARRAYREF,
74             default => [],
75             optional => 1 },
76             });
77              
78 0 0 0     0 if ( exists $args{rw_all} && @{ $args{rw} } ) {
  0         0  
79 0         0 croak("Mutually exclusive arguments: rw_all and rw\n");
80             }
81              
82 0 0 0     0 if ( exists $args{ro_all} && @{ $args{ro} } ) {
  0         0  
83 0         0 croak("Mutually exclusive arguments: ro_all and ro\n");
84             }
85              
86 0 0 0     0 if ( ! @{ $args{rw} } && ! exists $args{rw_all} &&
  0   0     0  
  0   0     0  
87             ! @{ $args{ro} } && ! exists $args{ro_all} ) {
88 0         0 $args{rw_all} = 1;
89             }
90              
91 0         0 $filer_of{$ident} = $args{filer};
92 0         0 $path_of{$ident} = $args{path};
93 0         0 $type_of{$ident} = $args{type};
94 0         0 $active_of{$ident} = $args{active};
95 0         0 $actual_of{$ident} = $args{actual};
96 0         0 $nosuid_of{$ident} = $args{nosuid};
97 0         0 $anon_of{$ident} = $args{anon};
98 0         0 $sec_of{$ident} = $args{sec};
99 0         0 $root_of{$ident} = $args{root};
100              
101 0 0       0 if ( $args{rw_all} ) {
102 0         0 $rw_all_of{$ident} = $args{rw_all};
103 0         0 $rw_of{$ident} = [];
104             } else {
105 0         0 $rw_of{$ident} = $args{rw};
106             }
107              
108 0 0       0 if ( $args{ro_all} ) {
109 0         0 $ro_all_of{$ident} = $args{ro_all};
110 0         0 $ro_of{$ident} = [];
111             } else {
112 0         0 $ro_of{$ident} = $args{ro};
113             }
114              
115             }
116              
117             sub get_rw {
118 0     0 1 0 my $self = shift;
119 0         0 my $ident = ident $self;
120 0         0 return @{ $rw_of{$ident} };
  0         0  
121             }
122              
123             sub set_rw_all {
124 0     0 1 0 my $self = shift;
125 0         0 my $ident = ident $self;
126 0         0 my ($rw_all) = validate_pos( @_, { type => BOOLEAN } );
127 0         0 $rw_of{$ident} = [];
128 0         0 $rw_all_of{$ident} = $rw_all;
129             }
130              
131             sub set_rw {
132 0     0 1 0 my $self = shift;
133 0         0 my $ident = ident $self;
134 0         0 my ($rw) = validate_pos( @_, { type => ARRAYREF } );
135 0         0 $self->set_rw_all(0);
136 0         0 $rw_of{$ident} = $rw;
137             }
138              
139             sub has_rw {
140 0     0 1 0 my $self = shift;
141 0         0 my $ident = ident $self;
142 0         0 my ($rw) = validate_pos( @_, { type => SCALAR } );
143 0         0 return grep { $_ eq $rw } @{ $rw_of{$ident} };
  0         0  
  0         0  
144             }
145              
146             sub add_rw {
147 0     0 1 0 my $self = shift;
148 0         0 my $ident = ident $self;
149 0         0 my ($rw) = validate_pos( @_, { type => SCALAR } );
150 0 0       0 if ( $self->get_rw_all ) {
151 0         0 return;
152             } else {
153 0 0       0 if ( not $self->has_rw( $rw ) ) {
154 0         0 push @{ $rw_of{$ident} }, $rw;
  0         0  
155             }
156             }
157 0         0 return 1;
158             }
159              
160             sub remove_rw {
161 0     0 1 0 my $self = shift;
162 0         0 my $ident = ident $self;
163 0         0 my ($rw) = validate_pos( @_, { type => SCALAR } );
164 0 0       0 if ( $self->get_rw_all ) {
165 0         0 return;
166             } else {
167 0 0       0 if ( $self->has_rw( $rw ) ) {
168 0         0 $rw_of{$ident} = [ grep { $_ ne $rw } @{ $rw_of{$ident} } ];
  0         0  
  0         0  
169             }
170             }
171 0         0 return 1;
172             }
173              
174             sub get_ro {
175 0     0 1 0 my $self = shift;
176 0         0 my $ident = ident $self;
177 0         0 return @{ $ro_of{$ident} };
  0         0  
178             }
179              
180             sub set_ro_all {
181 0     0 1 0 my $self = shift;
182 0         0 my $ident = ident $self;
183 0         0 my ($ro_all) = validate_pos( @_, { type => BOOLEAN } );
184 0         0 $ro_of{$ident} = [];
185 0         0 $ro_all_of{$ident} = $ro_all;
186             }
187              
188             sub set_ro {
189 0     0 1 0 my $self = shift;
190 0         0 my $ident = ident $self;
191 0         0 my ($ro) = validate_pos( @_, { type => ARRAYREF } );
192 0         0 $self->set_ro_all(0);
193 0         0 $ro_of{$ident} = $ro;
194             }
195              
196             sub has_ro {
197 0     0 1 0 my $self = shift;
198 0         0 my $ident = ident $self;
199 0         0 my ($ro) = validate_pos( @_, { type => SCALAR } );
200 0         0 return grep { $_ eq $ro } @{ $ro_of{$ident} };
  0         0  
  0         0  
201             }
202              
203             sub add_ro {
204 0     0 1 0 my $self = shift;
205 0         0 my $ident = ident $self;
206 0         0 my ($ro) = validate_pos( @_, { type => SCALAR } );
207 0 0       0 if ( $self->get_ro_all ) {
208 0         0 return;
209             } else {
210 0 0       0 if ( not $self->has_ro( $ro ) ) {
211 0         0 push @{ $ro_of{$ident} }, $ro;
  0         0  
212             }
213             }
214 0         0 return 1;
215             }
216              
217             sub remove_ro {
218 0     0 1 0 my $self = shift;
219 0         0 my $ident = ident $self;
220 0         0 my ($ro) = validate_pos( @_, { type => SCALAR } );
221 0 0       0 if ( $self->get_ro_all ) {
222 0         0 return;
223             } else {
224 0 0       0 if ( $self->has_ro( $ro ) ) {
225 0         0 $ro_of{$ident} = [ grep { $_ ne $ro } @{ $ro_of{$ident} } ];
  0         0  
  0         0  
226             }
227             }
228 0         0 return 1;
229             }
230              
231             sub get_sec {
232 0     0 1 0 my $self = shift;
233 0         0 my $ident = ident $self;
234 0         0 return @{ $sec_of{$ident} };
  0         0  
235             }
236              
237             sub set_sec {
238 0     0 1 0 my $self = shift;
239 0         0 my $ident = ident $self;
240 0         0 my ($sec) = validate_pos( @_, { type => ARRAYREF } );
241 0         0 $sec_of{$ident} = $sec;
242             }
243            
244             sub has_sec {
245 0     0 1 0 my $self = shift;
246 0         0 my $ident = ident $self;
247 0         0 my ($sec) = validate_pos( @_, { type => SCALAR } );
248 0         0 return grep { $_ eq $sec } @{ $sec_of{$ident} };
  0         0  
  0         0  
249             }
250              
251             sub add_sec {
252 0     0 1 0 my $self = shift;
253 0         0 my $ident = ident $self;
254 0         0 my ($sec) = validate_pos( @_, { type => SCALAR } );
255 0 0       0 if ( not $self->has_sec( $sec ) ) {
256 0         0 push @{ $sec_of{$ident} }, $sec;
  0         0  
257             }
258             }
259              
260             sub remove_sec {
261 0     0 1 0 my $self = shift;
262 0         0 my $ident = ident $self;
263 0         0 my ($sec) = validate_pos( @_, { type => SCALAR } );
264 0 0       0 if ( $self->has_sec( $sec ) ) {
265 0         0 $sec_of{$ident} = [ grep { $_ ne $sec } @{ $sec_of{$ident} } ];
  0         0  
  0         0  
266             }
267             }
268              
269             sub get_root {
270 0     0 1 0 my $self = shift;
271 0         0 my $ident = ident $self;
272 0         0 return @{ $root_of{$ident} };
  0         0  
273             }
274              
275             sub set_root {
276 0     0 1 0 my $self = shift;
277 0         0 my $ident = ident $self;
278 0         0 my ($root) = validate_pos( @_, { type => ARRAYREF } );
279 0         0 $root_of{$ident} = $root;
280             }
281              
282             sub has_root {
283 0     0 1 0 my $self = shift;
284 0         0 my $ident = ident $self;
285 0         0 my ($root) = validate_pos( @_, { type => SCALAR } );
286 0         0 return grep { $_ eq $root } @{ $root_of{$ident} };
  0         0  
  0         0  
287             }
288              
289             sub add_root {
290 0     0 1 0 my $self = shift;
291 0         0 my $ident = ident $self;
292 0         0 my ($root) = validate_pos( @_, { type => SCALAR } );
293 0 0       0 if ( not $self->has_root( $root ) ) {
294 0         0 push @{ $root_of{$ident} }, $root;
  0         0  
295             }
296             }
297              
298             sub remove_root {
299 0     0 1 0 my $self = shift;
300 0         0 my $ident = ident $self;
301 0         0 my ($root) = validate_pos( @_, { type => SCALAR } );
302 0 0       0 if ( $self->has_root( $root ) ) {
303 0         0 $root_of{$ident} = [ grep { $_ ne $root } @{ $root_of{$ident} } ];
  0         0  
  0         0  
304             }
305             }
306              
307             sub update {
308              
309 0     0 1 0 my $self = shift;
310 0         0 my $ident = ident $self;
311              
312 0         0 my @options = ();
313              
314 0 0       0 if ( $self->get_actual ) {
315 0         0 push @options, "actual=" . $self->get_actual;
316             }
317              
318 0 0       0 if ( defined $self->get_anon ) {
319 0         0 push @options, "anon=" . $self->get_anon;
320             }
321              
322 0 0       0 if ( $self->get_nosuid ) {
323 0         0 push @options, "nosuid";
324             }
325              
326 0 0       0 if ( $self->get_ro_all ) {
    0          
327 0         0 push @options, "ro";
328             } elsif ( my @ro = $self->get_ro ) {
329 0         0 push @options, "ro=" . join( ':', @ro );
330             }
331              
332 0 0       0 if ( $self->get_rw_all ) {
    0          
333 0         0 push @options, "rw";
334             } elsif ( my @rw = $self->get_rw ) {
335 0         0 push @options, "rw=" . join( ':', @rw );
336             }
337              
338 0 0       0 if ( my @root = $self->get_root ) {
339 0         0 push @options, "root=" . join( ':', @root );
340             }
341              
342 0 0       0 if ( my @sec = $self->get_sec ) {
343 0         0 push @options, "sec=" . join( ':', @sec );
344             }
345              
346 0         0 my $options = join ',', @options;
347              
348 0 0       0 my $argument =
349             $self->get_type eq 'permanent' ? '-p' : '-io';
350            
351 0         0 $self->get_filer->_run_command(
352             command => [
353             'exportfs', $argument, $options, $self->get_path,
354             ],
355             );
356              
357 0 0       0 if ( $self->get_type eq 'permanent' ) {
358 0         0 $active_of{$ident} = 1;
359             }
360              
361 0         0 return 1;
362              
363             }
364              
365             sub compare {
366              
367 0     0 1 0 my $self = shift;
368 0         0 my ($other) = validate_pos(
369             @_,
370             { isa => 'NetApp::Filer::Export' },
371             );
372              
373 0 0       0 if ( $self->get_actual ne $other->get_actual ) {
374 0         0 return;
375             }
376              
377 0 0       0 if ( $self->get_nosuid ne $other->get_nosuid ) {
378 0         0 return;
379             }
380              
381 0 0 0     0 if ( defined $self->get_anon && defined $other->get_anon ) {
    0 0        
382 0 0       0 if ( $self->get_anon ne $other->get_anon ) {
383 0         0 return;
384             }
385             } elsif ( defined $self->get_anon || defined $other->get_anon ) {
386 0         0 return;
387             }
388              
389 0 0 0     0 if ( $self->get_rw_all && ! $other->get_rw_all ) {
390 0         0 return;
391             }
392              
393 0 0 0     0 if ( ! $self->get_rw_all && $other->get_rw_all ) {
394 0         0 return;
395             }
396              
397 0 0 0     0 if ( $self->get_ro_all && ! $other->get_ro_all ) {
398 0         0 return;
399             }
400              
401 0 0 0     0 if ( ! $self->get_ro_all && $other->get_ro_all ) {
402 0         0 return;
403             }
404              
405 0 0       0 if ( join( ',', sort $self->get_rw) ne
406             join( ',', sort $other->get_rw ) ) {
407 0         0 return;
408             }
409              
410 0 0       0 if ( join( ',', sort $self->get_ro) ne
411             join( ',', sort $other->get_ro ) ) {
412 0         0 return;
413             }
414              
415 0 0       0 if ( join( ',', sort $self->get_sec) ne
416             join( ',', sort $other->get_sec ) ) {
417 0         0 return;
418             }
419              
420 0 0       0 if ( join( ',', sort $self->get_root) ne
421             join( ',', sort $other->get_root ) ) {
422 0         0 return;
423             }
424              
425 0         0 return 1;
426              
427             }
428              
429             }
430              
431             sub _parse_export {
432              
433 4     4   6313 my $class = shift;
434 4         8 my $line = shift;
435              
436 4         10 chomp($line);
437 4         38 $line =~ s/\s*$//;
438              
439 4         14 my ($path,$options) = split /\s+/, $line, 2;
440              
441 4         6 chomp($options);
442 4         15 $options =~ s/^-//;
443              
444 4         13 my $export = {
445             path => $path,
446             };
447              
448 4         14 foreach my $option ( split /,/, $options ) {
449              
450 10         28 my ($key,$value) = split /=/, $option;
451              
452 10 100 100     71 if ( $key eq 'nosuid' ) {
    100 100        
    100 33        
    50          
453 1         5 $export->{$key} = 1
454             } elsif ( $key eq 'ro' || $key eq 'rw' ) {
455 4 100       9 if ( $value ) {
456 2         13 $export->{$key} = [ split /:/, $value ];
457             } else {
458 2         8 $export->{ $key . '_all' } = 1;
459             }
460             } elsif ( $key eq 'sec' || $key eq 'root' ) {
461 4         22 $export->{$key} = [ split /:/, $value ];
462             } elsif ( $key eq 'actual' || $key eq 'anon' ) {
463 1         3 $export->{$key} = $value;
464             } else {
465 0         0 croak(
466             "Unrecognized export option '$key'\n",
467             "Exports entry: $line\n",
468             );
469             }
470              
471             }
472              
473 4         15 return $export;
474              
475             }
476              
477             1;