File Coverage

blib/lib/App/MBUtiny/Storage/Command.pm
Criterion Covered Total %
statement 41 175 23.4
branch 1 58 1.7
condition 0 23 0.0
subroutine 11 17 64.7
pod 7 7 100.0
total 60 280 21.4


line stmt bran cond sub pod time code
1             package App::MBUtiny::Storage::Command; # $Id: Command.pm 121 2019-07-01 19:51:50Z abalama $
2 2     2   16 use strict;
  2         5  
  2         59  
3 2     2   11 use utf8;
  2         5  
  2         16  
4              
5             =encoding utf-8
6              
7             =head1 NAME
8              
9             App::MBUtiny::Storage::Command - App::MBUtiny::Storage subclass for Command storage support
10              
11             =head1 VIRSION
12              
13             Version 1.00
14              
15             =head1 SYNOPSIS
16              
17            
18            
19             #FixUP on
20             test "test -d ./foo && ls -1 ./foo || mkdir ./foo"
21             put "cp [FILE] ./foo/[NAME]"
22             get "cp ./foo/[NAME] [FILE]"
23             del "test -e ./foo/[NAME] && unlink ./foo/[NAME] || true"
24             list "ls -1 ./foo"
25             comment Command storage said blah-blah-blah # Optional for collector
26            
27              
28             # . . .
29              
30            
31              
32             =head1 DESCRIPTION
33              
34             App::MBUtiny::Storage subclass for Command storage support
35              
36             =head2 del
37              
38             Removes the specified file.
39             This is backend method of L
40              
41             Variables: B, B, B
42              
43             =head2 get
44              
45             Gets the backup file from storage and saves it to specified path.
46             This is backend method of L
47              
48             Variables: B, B, B, B
49              
50             =head2 init
51              
52             The method performs initialization of storage.
53             This is backend method of L
54              
55             =head2 list
56              
57             Gets backup file list on storage.
58             This is backend method of L
59              
60             Variables: B, B
61              
62             =head2 cmd_storages
63              
64             my @list = $storage->cmd_storages;
65              
66             Returns list of command storage nodes
67              
68             =head2 put
69              
70             Sends backup file to storage.
71             This is backend method of L
72              
73             Variables: B, B, B, B, B
74              
75             =head2 test
76              
77             Storage testing.
78             This is backend method of L
79              
80             Variables: B, B
81              
82             =head1 VARIABLES
83              
84             =over 4
85              
86             =item B
87              
88             Full file path of backup file
89              
90             For example:
91              
92             /tmp/mbutiny/files/foo-2019-06-20.tar.gz
93              
94             =item B
95              
96             MBUtiny host name
97              
98             For example:
99              
100             foo
101              
102             =item B
103              
104             File name of backup file
105              
106             For example:
107              
108             foo-2019-06-20.tar.gz
109              
110             =item B
111              
112             Path to backup files
113              
114             For example:
115              
116             /tmp/mbutiny/files
117              
118             =item B
119              
120             Size of backup file (bytes)
121              
122             For example:
123              
124             32423
125              
126             =back
127              
128             =head1 HISTORY
129              
130             See C file
131              
132             =head1 TO DO
133              
134             See C file
135              
136             =head1 BUGS
137              
138             * none noted
139              
140             =head1 SEE ALSO
141              
142             L
143              
144             =head1 AUTHOR
145              
146             Serż Minus (Sergey Lepenkov) L Eabalama@cpan.orgE
147              
148             =head1 COPYRIGHT
149              
150             Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved
151              
152             =head1 LICENSE
153              
154             This program is free software; you can redistribute it and/or
155             modify it under the same terms as Perl itself.
156              
157             See C file and L
158              
159             =cut
160              
161 2     2   83 use vars qw/ $VERSION /;
  2         4  
  2         102  
162             $VERSION = '1.00';
163              
164 2     2   12 use Storable qw/dclone/;
  2         4  
  2         99  
165 2     2   9 use List::Util qw/uniq/;
  2         4  
  2         103  
166 2     2   9 use CTK::Util qw/dformat trim execute/;
  2         4  
  2         113  
167 2     2   21 use CTK::ConfGenUtil;
  2         10  
  2         154  
168 2     2   11 use CTK::TFVals qw/ :ALL /;
  2         5  
  2         513  
169 2     2   14 use App::MBUtiny::Util qw/ node2anode /;
  2         4  
  2         104  
170              
171             use constant {
172 2         2834 STORAGE_SIGN => 'Command',
173 2     2   12 };
  2         4  
174              
175             sub init {
176 1     1 1 11 my $self = shift;
177 1         4 $self->maybe::next::method();
178 1         13 $self->storage_status(STORAGE_SIGN, -1);
179 1         2 my $usecmd = 0;
180              
181 1         7 my $cmd_nodes = dclone(node2anode(node($self->{host}, 'command')));
182             #print explain($ftp_nodes), "\n";
183              
184 1         4 my %cmd_storages;
185 1         1 my $i = 0;
186 1         4 foreach my $cmd_node (@$cmd_nodes) {
187 0         0 my $id = sprintf("%s-%s-%d", STORAGE_SIGN, $self->{name}, ++$i);
188             my %attr = (
189             HOST => $self->{name},
190             PATH => $self->{path},
191 0         0 );
192 0   0     0 my $cmd_test = value($cmd_node, 'test') || "";
193 0   0     0 my $cmd_put = value($cmd_node, 'put') || "";
194 0   0     0 my $cmd_get = value($cmd_node, 'get') || "";
195 0   0     0 my $cmd_list = value($cmd_node, 'list') || "";
196 0   0     0 my $cmd_del = value($cmd_node, 'del') || "";
197 0   0     0 my $comment = value($cmd_node, 'comment') || "";
198             $cmd_storages{$id} = {
199             id => $id,
200             cmd_test => $cmd_test,
201             cmd_put => $cmd_put,
202             cmd_get => $cmd_get,
203             cmd_list => $cmd_list,
204             cmd_del => $cmd_del,
205             attr => {%attr},
206 0 0 0     0 comment => join("\n", grep {$_} ($cmd_put || sprintf("Command storage: %s", $id), $comment)),
  0         0  
207             fixup => value($cmd_node, 'fixup') ? 1 : 0,
208             };
209 0         0 $usecmd++;
210              
211             }
212 1         4 $self->{cmd_storages} = [(values(%cmd_storages))];
213              
214 1 50       4 $self->storage_status(STORAGE_SIGN, $usecmd) if $usecmd;
215             #print explain($self->{cmd_storages}), "\n";
216 1         3 return $self;
217             }
218             sub cmd_storages {
219 0     0 1   my $self = shift;
220 0   0       my $storages = $self->{cmd_storages} || [];
221 0           return @$storages;
222             }
223             sub test {
224 0     0 1   my $self = shift;
225 0           my %params = @_; $self->maybe::next::method(%params);
  0            
226 0           my $sign = STORAGE_SIGN;
227 0 0         return -1 if $self->storage_status($sign) <= 0; # SKIP
228              
229 0           my @test = ();
230 0           foreach my $storage ($self->cmd_storages) {
231 0           my $id = $storage->{id};
232 0           my $attr = $storage->{attr};
233 0           my $cmd_test = dformat($storage->{cmd_test}, $attr);
234              
235             # Execute
236 0           my $exe_err = '';
237 0           my $exe_out = execute($cmd_test, undef, \$exe_err);
238 0           my $exe_stt = $? >> 8;
239 0 0         if ($exe_stt) {
240 0           $self->storage_status($sign, 0);
241 0           push @test, [0, $id, sprintf("Can't execute %s: %s", $cmd_test, $exe_err)];
242 0           next;
243             }
244             #print explain($exe_out), "\n";
245              
246             # Result
247 0           push @test, [1, $id];
248             }
249              
250 0           $self->{test}->{$sign} = [@test];
251 0           return 1;
252             }
253             sub put {
254 0     0 1   my $self = shift;
255 0           my %params = @_; $self->maybe::next::method(%params);
  0            
256 0 0         return $self->storage_status(STORAGE_SIGN, -1) if $self->storage_status(STORAGE_SIGN) <= 0; # SKIP and set SKIP
257 0           my $status = 1;
258 0           my $name = $params{name}; # File name only
259 0           my $file = $params{file}; # Path to local file
260 0   0       my $src_size = $params{size} || 0;
261              
262 0           foreach my $storage ($self->cmd_storages) {
263 0           my $attr = $storage->{attr};
264 0           $attr->{SIZE} = $src_size;
265 0           $attr->{NAME} = $name;
266 0           $attr->{FILE} = $file;
267 0           my $cmd_put = dformat($storage->{cmd_put}, $attr);
268 0   0       my $comment = $storage->{comment} || "";
269 0           my $ostat = 1;
270              
271             # Execute
272 0           my $exe_err = '';
273 0           my $exe_out = execute($cmd_put, undef, \$exe_err);
274 0           my $exe_stt = $? >> 8;
275 0 0         if ($exe_stt) {
276 0           $self->error(sprintf("Can't execute %s", $cmd_put));
277 0 0         $self->error($exe_out) if $exe_out;
278 0 0         $self->error($exe_err) if $exe_err;
279 0           $ostat = 0;
280             }
281             #print explain($exe_out), "\n";
282              
283             # Fixup!
284 0 0         $self->fixup("put", $ostat, $comment) if $storage->{fixup};
285 0 0         $status = 0 unless $ostat;
286             }
287              
288 0 0         $self->storage_status(STORAGE_SIGN, 0) unless $status;
289             }
290             sub get {
291 0     0 1   my $self = shift;
292 0           my %params = @_;
293 0 0         if ($self->storage_status(STORAGE_SIGN) <= 0) { # SKIP and set SKIP
294 0           $self->maybe::next::method(%params);
295 0           return $self->storage_status(STORAGE_SIGN, -1);
296             }
297 0           my $name = $params{name}; # archive name
298 0           my $file = $params{file}; # destination archive file path
299              
300 0           foreach my $storage ($self->cmd_storages) {
301 0           my $attr = $storage->{attr};
302 0           $attr->{NAME} = $name;
303 0           $attr->{FILE} = $file;
304 0           my $cmd_get = dformat($storage->{cmd_get}, $attr);
305              
306             # Execute
307 0           my $exe_err = '';
308 0           my $exe_out = execute($cmd_get, undef, \$exe_err);
309 0           my $exe_stt = $? >> 8;
310 0 0         if ($exe_stt) {
311 0           $self->error(sprintf("Can't execute %s", $cmd_get));
312 0 0         $self->error($exe_out) if $exe_out;
313 0 0         $self->error($exe_err) if $exe_err;
314 0           next;
315             }
316              
317             # Validate
318 0 0         unless ($self->validate($file)) { # FAIL validation!
319 0           $self->error(sprintf("Command storage %s failed: file %s is not valid!", $cmd_get, $file));
320             next
321 0           }
322              
323             # Done!
324 0           return $self->storage_status(STORAGE_SIGN, 1);
325             }
326              
327 0           $self->storage_status(STORAGE_SIGN, 0);
328 0           $self->maybe::next::method(%params);
329             }
330             sub del {
331 0     0 1   my $self = shift;
332 0           my $name = shift;
333 0           $self->maybe::next::method($name);
334 0 0         return $self->storage_status(STORAGE_SIGN, -1) if $self->storage_status(STORAGE_SIGN) <= 0; # SKIP and set SKIP
335 0           my $status = 1;
336              
337 0           foreach my $storage ($self->cmd_storages) {
338 0           my $attr = $storage->{attr};
339 0           $attr->{NAME} = $name;
340 0           my $cmd_del = dformat($storage->{cmd_del}, $attr);
341 0   0       my $comment = $storage->{comment} || "";
342 0           my $ostat = 1;
343              
344             # Execute
345 0           my $exe_err = '';
346 0           my $exe_out = execute($cmd_del, undef, \$exe_err);
347 0           my $exe_stt = $? >> 8;
348 0 0         if ($exe_stt) {
349 0           $self->error(sprintf("Can't execute %s", $cmd_del));
350 0 0         $self->error($exe_out) if $exe_out;
351 0 0         $self->error($exe_err) if $exe_err;
352 0           $ostat = 0;
353             }
354              
355             # Fixup!
356 0 0         $self->fixup("del", $name) if $storage->{fixup};
357 0 0         $status = 0 unless $ostat;
358             }
359 0 0         $self->storage_status(STORAGE_SIGN, 0) unless $status;
360             }
361             sub list {
362 0     0 1   my $self = shift;
363 0           my %params = @_; $self->maybe::next::method(%params);
  0            
364 0 0         return $self->storage_status(STORAGE_SIGN, -1) if $self->storage_status(STORAGE_SIGN) <= 0; # SKIP and set SKIP
365 0           my $sign = STORAGE_SIGN;
366              
367 0           my @list = ();
368 0           foreach my $storage ($self->cmd_storages) {
369 0           my $attr = $storage->{attr};
370 0           my $cmd_list = dformat($storage->{cmd_list}, $attr);
371 0           my $ostat = 1;
372              
373             # Execute
374 0           my $exe_err = '';
375 0           my $exe_out = execute($cmd_list, undef, \$exe_err);
376 0           my $exe_stt = $? >> 8;
377 0 0         if ($exe_stt) {
378 0           $self->error(sprintf("Can't execute %s", $cmd_list));
379 0 0         $self->error($exe_out) if $exe_out;
380 0 0         $self->error($exe_err) if $exe_err;
381 0           $ostat = 0;
382             }
383              
384             # Get list
385 0 0         if ($ostat) {
386 0           my @ls = map {$_ = trim($_)} (split /\s*\n+\s*/, $exe_out);
  0            
387 0 0         push @list, grep { defined($_) && length($_) } @ls;
  0            
388             }
389             }
390 0           $self->{list}->{$sign} = [uniq(@list)];
391 0           return 1;
392             }
393              
394             1;
395              
396             __END__