da3ef770c7b3ade765b063bf48da195b502fcdee
[BackupPC.git] / bin / BackupPC_ASA_ArchiveStart
1 #!/usr/bin/perl
2 #============================================================= -*-perl-*-
3 #
4 # BackupPC_archiveStart: start an archive request from the
5 # command line.
6 #
7 # DESCRIPTION
8 #  
9 #   Usage: BackupPC_archiveStart archiveHost userName hosts...
10 #
11 #   Initiates an archive request on archive host archiveHost
12 #   for the listed hosts.  The latest backup for each host is
13 #   archived.  The userName is name of the requesting user,
14 #   which appears in the log files.
15 #
16 # AUTHOR
17 #   Craig Barratt  <cbarratt@users.sourceforge.net>
18 #   Dobrica Pavlinusic <dpavlin@rot13.org>
19 #
20 # COPYRIGHT
21 #   Copyright (C) 2007-2009  Craig Barratt
22 #
23 #   This program is free software; you can redistribute it and/or modify
24 #   it under the terms of the GNU General Public License as published by
25 #   the Free Software Foundation; either version 2 of the License, or
26 #   (at your option) any later version.
27 #
28 #   This program is distributed in the hope that it will be useful,
29 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
30 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31 #   GNU General Public License for more details.
32 #
33 #   You should have received a copy of the GNU General Public License
34 #   along with this program; if not, write to the Free Software
35 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
36 #
37 #========================================================================
38 #
39 # Version 3.2.0, released 31 Jul 2010.
40 #
41 # See http://backuppc.sourceforge.net.
42 #
43 #========================================================================
44
45 use strict;
46 no  utf8;
47 use lib "/usr/local/BackupPC/lib";
48 use Getopt::Std;
49 use BackupPC::Lib;
50
51 use DBI;
52 use Data::Dump qw(dump);
53
54 my $debug = $ENV{DEBUG} || 0;
55
56 die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
57
58 my %opts;
59
60 # no options currently
61 if ( !getopts("", \%opts) || @ARGV < 2 ) {
62     print STDERR <<EOF;
63 usage: $0 archiveHost userName [hosts[:num]...]
64 EOF
65     exit(1);
66 }
67
68 my %Conf = $bpc->Conf();
69
70 my $dbh = DBI->connect($Conf{SearchDSN}, $Conf{SearchUser}, "", { RaiseError => 1, AutoCommit => 0 });
71
72 my $sth = $dbh->prepare(qq{
73         select
74                 backups.id as backup_id,
75                 hosts.name as host,
76                 backups.num as num,
77                 inc_size,
78                 size,
79                 inc_deleted
80         from backups
81         join hosts on hosts.id = hostid
82         where hosts.name = ?
83 });
84
85 my $Hosts       = $bpc->HostInfoRead();
86 my $ArchiveHost = shift @ARGV;
87 my $UserName    = shift @ARGV;
88 my @HostFilter  = @ARGV;
89 my $TopDir      = $bpc->{Conf}{TopDir};
90
91 if ( !defined($Hosts->{$ArchiveHost}) ) {
92     print(STDERR "$0: archive host $ArchiveHost doesn't exist... quitting\n");
93     exit(1);
94 }
95 $bpc->ConfigRead($ArchiveHost);
96
97 my(@HostList, @BackupList);
98
99
100 my $host_nums;
101
102 foreach my $host ( keys %$Hosts ) {
103         $host = lc $host;
104         my @backups = $bpc->BackupInfoRead($host);
105         if ( !@backups ) {
106                 warn "$0: host $host doesn't have any backups... skipping\n";
107                 next;
108         }
109
110         my $all_backup_numbers;
111         $all_backup_numbers->{ $_->{num} }++ foreach @backups;
112
113         $sth->execute( $host );
114         while ( my $row = $sth->fetchrow_hashref ) {
115                 warn "# row ",dump($row) if $debug;
116                 $all_backup_numbers->{ $row->{num} } =
117                 $row->{inc_deleted}  ? 0 :
118                 $row->{size}    == 0 ? 0 :
119                 $row->{inc_size} > 0 ? 0 :
120                 $row->{size}     > 0 ? 1 :
121                 0;
122         }
123
124         warn "# $host all_backup_numbers = ",dump($all_backup_numbers),"\n";
125
126         $host_nums->{$host} = [
127                 sort
128                 grep { $all_backup_numbers->{$_} }
129                 keys %$all_backup_numbers
130         ];
131 }
132
133 foreach ( @HostFilter ) {
134         my ($host,$num) = split(/:/,$_,2);
135         if ( !defined($Hosts->{$host}) ) {
136                 print(STDERR "$0: host $host doesn't exist... quitting\n");
137                 exit(1);
138         }
139         if ( defined $num ) {
140                 warn "+ $host $num\n";
141                 push(@HostList, $host);
142                 push(@BackupList, $num);
143         } else {
144                 foreach my $num ( @{ $host_nums->{$host} } ) {
145                         warn "+ $host $num\n";
146                         push(@HostList, $host);
147                         push(@BackupList, $num);
148                 }
149         }
150 }
151
152 if ( ! @HostFilter ) {
153         foreach my $host ( keys %$host_nums ) {
154                 foreach my $num ( @{ $host_nums->{$host} } ) {
155                         warn "+ $host $num\n";
156                         push(@HostList, $host);
157                         push(@BackupList, $num);
158                 }
159         }
160 }
161
162 warn "# HostList=",dump(@HostList),"\n";
163 warn "# BackupList=",dump(@BackupList),"\n";
164
165 $dbh->disconnect;
166
167 my $ReqFileName;
168 for ( my $i = 0 ; ; $i++ ) {
169     $ReqFileName="archiveReq.$$.$i";
170     last if ( !-f "$TopDir/pc/$ArchiveHost/$ReqFileName" );
171 }
172 my %ArchiveReq = (
173     archiveloc  => $bpc->{Conf}{ArchiveDest},
174     archtype    => 0,
175     compression => $bpc->{Conf}{ArchiveComp} eq 'none' ? $bpc->{Conf}{CatPath}
176                     : ($bpc->{Conf}{ArchiveComp} eq 'gzip'
177                       ? $bpc->{Conf}{GzipPath} : $bpc->{Conf}{Bzip2Path}),
178     compext     => $bpc->{Conf}{ArchiveComp} eq 'none' ? ''
179                     : ($bpc->{Conf}{ArchiveComp} eq 'gzip' ? '.gz' : '.bz2'),
180     parfile     => $bpc->{Conf}{ArchivePar},
181     splitsize   => $bpc->{Conf}{ArchiveSplit} . '000000', # mb -> bytes
182     host        => $ArchiveHost,
183     HostList    => \@HostList,
184     BackupList  => \@BackupList,
185     user        => $UserName,
186     reqTime     => time,
187 );
188 my $archive = Data::Dumper->new([\%ArchiveReq], [qw(*ArchiveReq)]);
189 $archive->Indent(1);
190 if ( !open(REQ, ">", "$TopDir/pc/$ArchiveHost/$ReqFileName") ) {
191     print(STDERR "$0: can't open/write request file $TopDir/pc/$ArchiveHost/$ReqFileName... quitting\n");
192     exit(1);
193 }
194 binmode(REQ);
195 print REQ $archive->Dump;
196 close(REQ);
197 $bpc->ServerConnect($bpc->{Conf}{ServerHost}, $bpc->{Conf}{ServerPort});
198 my $reply = $bpc->ServerMesg("archive $UserName $ArchiveHost $ReqFileName");
199 $bpc->ServerDisconnect();
200 print("Sent archive request, reply: $reply\n");
201 exit(0);