File Coverage

blib/lib/Sys/RevoBackup/Cmd/Command/configcheck.pm
Criterion Covered Total %
statement 11 13 84.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 16 18 88.8


line stmt bran cond sub pod time code
1             package Sys::RevoBackup::Cmd::Command::configcheck;
2             {
3             $Sys::RevoBackup::Cmd::Command::configcheck::VERSION = '0.27';
4             }
5             BEGIN {
6 1     1   2500 $Sys::RevoBackup::Cmd::Command::configcheck::AUTHORITY = 'cpan:TEX';
7             }
8             # ABSTRACT: revobackup config self-test
9              
10 1     1   24 use 5.010_000;
  1         4  
  1         46  
11 1     1   6 use mro 'c3';
  1         2  
  1         8  
12 1     1   32 use feature ':5.10';
  1         2  
  1         99  
13              
14 1     1   500 use Moose;
  0            
  0            
15             use namespace::autoclean;
16              
17             # use IO::Handle;
18             # use autodie;
19             # use MooseX::Params::Validate;
20             # use Carp;
21             # use English qw( -no_match_vars );
22             # use Try::Tiny;
23             use File::Blarf;
24             use Sys::RevoBackup;
25             use List::MoreUtils;
26              
27             # extends ...
28             extends 'Sys::RevoBackup::Cmd::Command';
29             # has ...
30             has 'revobackup' => (
31             'is' => 'rw',
32             'isa' => 'Sys::RevoBackup',
33             'lazy' => 1,
34             'builder' => '_init_revobackup',
35             );
36             # with ...
37             # initializers ...
38             sub _init_revobackup {
39             my $self = shift;
40              
41             my $Revo = Sys::RevoBackup::->new({
42             'config' => $self->config(),
43             'logger' => $self->logger(),
44             'logfile' => $self->config()->get( 'Sys::RevoBackup::Logfile', { Default => '/tmp/revo.log', } ),
45             'bank' => $self->config()->get('Sys::RevoBackup::Bank', { Default => '/srv/backup/revobackup', } ),
46             'concurrency' => 1,
47             });
48              
49             return $Revo;
50             }
51              
52             # your code here ...
53             sub execute {
54             my $self = shift;
55              
56             # verify configuration
57             # - bankdir writeable
58             # - at least one vault
59             # - log writeable
60             # - diskspace available
61             # check config and configured dirs
62              
63             my $status = 1;
64              
65             # do we have a bank?
66             my $bank = $self->revobackup()->bank();
67             if($bank) {
68             say 'OK - Bank directory configured: '.$bank;
69             # is the bank a directory?
70             if(-d $bank) {
71             say 'OK - Bank location is a directory';
72             # is it writeable?
73             if(-w $bank) {
74             say 'OK - Bank location is writeable';
75             } else {
76             say 'ERROR - Bank directory is not writebale!';
77             $status = 0;
78             }
79             } else {
80             say 'ERROR - Configured Bank is no directory!';
81             $status = 0;
82             }
83             } else {
84             say 'ERROR - No bank configured!';
85             $status = 0;
86             }
87              
88             # do we have at least one vault?
89             my $vault_ref = $self->revobackup()->vaults();
90             my $num_vaults = 0;
91             if($vault_ref && ref($vault_ref) eq 'ARRAY') {
92             # check each vault if it is accessible
93             foreach my $vault (sort @{$vault_ref}) {
94             if($self->_check_vault($vault)) {
95             say 'OK - Valid vault '.$vault;
96             $num_vaults++;
97             } else {
98             say 'ERROR - Invalid vault. See above for errors on '.$vault;
99             $status = 0;
100             }
101             }
102             }
103              
104             if(!$num_vaults) {
105             say 'ERROR - No vaults configured';
106             $status = 0;
107             }
108              
109             return $status;
110             }
111              
112             sub _check_vault {
113             my $self = shift;
114             my $vault = shift;
115              
116             my $source = $self->revobackup()->config()->get('Sys::Revobackup::Vaults::'.$vault.'::source');
117              
118             if($self->_check_vault_writeable($vault)) {
119             # ok
120             } else {
121             return;
122             }
123              
124             # make sure the source is defined
125             if(!$source) {
126             say ' ERROR - Source for '.$vault.' not defined!';
127             return;
128             }
129              
130             # check if pw-less ssh access works
131             # make sure we connection to the source, if it is remote
132             if($source =~ m#^([^:]+):#) {
133             my $hostname = $1;
134             if($self->_check_vault_ssh_connection($hostname)) {
135             say ' OK - SSH access working to '.$vault;
136             } else {
137             say ' ERROR - SSH access failed! Check your public key setup for '.$vault;
138             say ' HINT: ssh-copy-id -i '.$hostname;
139             return;
140             }
141             }
142              
143             if($self->_check_vault_excludes($vault)) {
144             # nop
145             } else {
146             return;
147             }
148              
149             return 1;
150             }
151              
152             sub _check_vault_writeable {
153             my $self = shift;
154             my $vault = shift;
155              
156             my $bank = $self->revobackup()->bank();
157              
158             # make sure the vault directory is writeable
159             my $vault_dir = $bank.'/'.$vault;
160             if(-e $vault_dir && -w $vault_dir) {
161             say ' OK - Vault dir '.$vault_dir.' is writeable';
162             return 1;
163             } else {
164             say ' ERROR - Vault dir '.$vault_dir.' not writeable!';
165             return;
166             }
167             }
168              
169             sub _check_vault_excludes {
170             my $self = shift;
171             my $vault = shift;
172              
173             my $source = $self->revobackup()->config()->get('Sys::Revobackup::Vaults::'.$vault.'::source');
174             my $xcl = $self->revobackup()->config()->get('Sys::Revobackup::Vaults::'.$vault.'::excludefrom');
175             my $ncfs = $self->revobackup()->config()->get('Sys::Revobackup::Vaults::'.$vault.'::nocrossfs');
176             my $status = 1;
177              
178             # check excludes
179             if($xcl) {
180             if(-e $xcl) {
181             my @xcls = File::Blarf::slurp($xcl);
182             if(!@xcls) {
183             say ' WARNING - Exclude file for '.$vault.' exists but is empty!';
184             }
185             # if nocrossfs is disabled and the source is a fs root we require
186             # exclusion of /proc/, /sys/ and /dev/
187             if($ncfs == 0 && $source =~ m#:/$#) {
188             foreach my $dir (qw(proc sys dev)) {
189             if(List::MoreUtils::none { $_ =~ m/$dir/ } @xcls) {
190             say ' ERROR - Missing mandatory exclude '.$dir.' in '.$xcl.' for '.$vault;
191             $status = 0;
192             }
193             }
194             }
195             } else {
196             say ' ERROR - Exclude file for '.$vault.' not found at '.$xcl;
197             }
198             }
199              
200             return $status;
201             }
202              
203             sub _check_vault_ssh_connection {
204             my $self = shift;
205             my $hostname = shift;
206              
207             if ( $self->revobackup()->sys()->run_remote_cmd( $hostname, '/bin/true', { Timeout => 10, } ) ) {
208             return 1;
209             } else {
210             return;
211             }
212             }
213              
214             sub abstract {
215             return 'Check integrity of the configuration';
216             }
217              
218             no Moose;
219             __PACKAGE__->meta->make_immutable;
220              
221             1;
222              
223             __END__
224              
225             =pod
226              
227             =encoding UTF-8
228              
229             =head1 NAME
230              
231             Sys::RevoBackup::Cmd::Command::configcheck - revobackup config self-test
232              
233             =head1 METHODS
234              
235             =head2 abstract
236              
237             Workaround.
238              
239             =head2 execute
240              
241             Run the config check.
242              
243             =head1 NAME
244              
245             Sys::RevoBackup::Cmd::Command::configcheck - Perform a thorough configuration check
246              
247             =head1 AUTHOR
248              
249             Dominik Schulz <dominik.schulz@gauner.org>
250              
251             =head1 COPYRIGHT AND LICENSE
252              
253             This software is copyright (c) 2012 by Dominik Schulz.
254              
255             This is free software; you can redistribute it and/or modify it under
256             the same terms as the Perl 5 programming language system itself.
257              
258             =cut