1 #============================================================= -*-perl-*-
3 # BackupPC::CGI::Archive package
7 # This module implements the Archive action for the CGI interface.
10 # Craig Barratt <cbarratt@users.sourceforge.net>
13 # Copyright (C) 2003-2009 Craig Barratt
15 # This program is free software; you can redistribute it and/or modify
16 # it under the terms of the GNU General Public License as published by
17 # the Free Software Foundation; either version 2 of the License, or
18 # (at your option) any later version.
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #========================================================================
31 # Version 3.2.0, released 31 Jul 2010.
33 # See http://backuppc.sourceforge.net.
35 #========================================================================
37 package BackupPC::CGI::Archive;
40 use BackupPC::CGI::Lib qw(:all);
46 my $archHost = $In{host};
47 my $Privileged = CheckPermission();
50 ErrorExit($Lang->{Only_privileged_users_can_archive} );
52 if ( $In{type} == 0 ) {
53 my($fullTot, $fullSizeTot, $incrTot, $incrSizeTot, $str,
54 $strNone, $strGood, $hostCntGood, $hostCntNone, $checkBoxCnt,
57 $hostCntGood = $hostCntNone = $checkBoxCnt = $fullSizeTot = 0;
58 GetStatusInfo("hosts");
60 foreach my $host ( sort(keys(%Status)) ) {
61 my($fullDur, $incrCnt, $fullSize, $fullRate);
62 my @Backups = $bpc->BackupInfoRead($host);
63 my $fullCnt = $incrCnt = 0;
64 my $all_backup_numbers;
66 for ( my $i = 0 ; $i < @Backups ; $i++ ) {
67 if ( $Backups[$i]{type} eq "full" ) {
68 $fullSize = $Backups[$i]{size} / (1024 * 1024);
71 $incrSizeTot = $Backups[$i]{size} / (1024 * 1024);
73 $backupnumber = $Backups[$i]{num};
74 $all_backup_numbers->{$backupnumber}++;
76 $fullSizeTot += $fullSize + $incrSizeTot;
77 $fullSize = sprintf("%.2f", ($fullSize + $incrSizeTot) / 1000);
79 $bpc->ConfigRead($archHost);
82 use Data::Dump qw(dump);
84 my $dbh = DBI->connect($Conf{SearchDSN}, $Conf{SearchUser}, "", { RaiseError => 1, AutoCommit => 0 });
85 my $sth = $dbh->prepare(qq{
87 hosts.name as host, -- FIXME for debug
93 join hosts on hosts.id = hostid
97 # and inc_size < 0 and size > 0 and not inc_deleted
98 while( my $row = $sth->fetchrow_hashref ) {
99 warn "# row ",dump $row;
100 $all_backup_numbers->{ $row->{num} } =
101 $row->{inc_deleted} ? 0 :
102 $row->{size} == 0 ? 0 :
103 $row->{inc_size} > 0 ? 0 :
104 $row->{size} > 0 ? 1 :
108 warn "# host $host all_backup_numbers = ",dump($all_backup_numbers);
111 grep { $all_backup_numbers->{$_} }
112 keys %$all_backup_numbers;
115 foreach my $backupnumber ( @backup_nums ) {
117 <input type="hidden" name="fcb$checkBoxCnt" value="$host">
118 <input type="checkbox" name="backup$checkBoxCnt" value="$backupnumber">$backupnumber
123 =for ASA extension removed this
126 <td class="border"><input type="hidden" name="backup$checkBoxCnt" value="$backupnumber"><input type="checkbox" name="fcb$checkBoxCnt" value="$host"> ${HostLink($host)} </td>
127 <td align="center" class="border"> ${UserLink($Hosts->{$host}{user})} </td>
128 <td align="center" class="border"> $fullSize </td>
139 <td align="center" class="border">
140 ${UserLink($Hosts->{$host}{user})}
142 <td align="center" class="border"> $fullSize </td>
145 if ( @Backups == 0 ) {
153 $fullSizeTot = sprintf("%.2f", $fullSizeTot / 1000);
154 my $now = timeStamp2(time);
155 my $checkAllHosts = $Lang->{checkAllHosts};
157 <input type="hidden" name="archivehost" value="$In{'archivehost'}">
159 my $content = eval("qq{$Lang->{BackupPC_Archive}}");
160 Header(eval("qq{$Lang->{BackupPC__Archive}}"), $content, 1);
163 my(@HostList, @BackupList, $HostListStr, $hiddenStr, $pathHdr,
164 $badFileCnt, $reply, $str);
167 # Pick up the archive host's config file
169 $bpc->ConfigRead($archHost);
170 %Conf = $bpc->Conf();
173 SplitPath => $Conf{SplitPath},
174 ParPath => $Conf{ParPath},
175 CatPath => $Conf{CatPath},
176 GzipPath => $Conf{GzipPath},
177 Bzip2Path => $Conf{Bzip2Path},
178 ArchiveDest => $Conf{ArchiveDest},
179 ArchiveComp => $Conf{ArchiveComp},
180 ArchivePar => $Conf{ArchivePar},
181 ArchiveSplit => $Conf{ArchiveSplit},
182 topDir => $bpc->{TopDir},
187 for ( my $i = 0 ; $i < $In{fcbMax} ; $i++ ) {
188 next if ( !defined($In{"fcb$i"}) );
189 my $name = $In{"fcb$i"};
190 my $backupno = $In{"backup$i"};
191 next unless defined $backupno; # ASA - skip hosts without backups checked
192 push(@HostList, $name);
193 push(@BackupList, $backupno);
195 <input type="hidden" name="fcb$i" value="$In{'fcb' . $i}">
196 <input type="hidden" name="backup$i" value="$In{'backup' . $i}">
198 $HostListStr .= <<EOF;
199 <li> ${EscHTML($name)} $i
203 <input type="hidden" name="archivehost" value="$In{'archivehost'}">
205 $hiddenStr .= "<input type=\"hidden\" name=\"fcbMax\" value=\"$In{fcbMax}\">\n";
206 if ( @HostList == 0 ) {
207 ErrorExit($Lang->{You_haven_t_selected_any_hosts});
209 my ($ArchiveDest, $ArchiveCompNone, $ArchiveCompGzip,
210 $ArchiveCompBzip2, $ArchivePar, $ArchiveSplit);
211 $ArchiveDest = $Conf{ArchiveDest};
212 if ( $Conf{ArchiveComp} eq "none" ) {
213 $ArchiveCompNone = "checked";
215 $ArchiveCompNone = "";
217 if ( $Conf{ArchiveComp} eq "gzip" ) {
218 $ArchiveCompGzip = "checked";
220 $ArchiveCompGzip = "";
222 if ( $Conf{ArchiveComp} eq "bzip2" ) {
223 $ArchiveCompBzip2 = "checked";
225 $ArchiveCompBzip2 = "";
227 $ArchivePar = $Conf{ArchivePar};
228 $ArchiveSplit = $Conf{ArchiveSplit};
230 if ( $In{type} == 1 ) {
232 # Tell the user what options they have
235 if ( $Conf{ArchiveClientCmd} =~ /\$archiveloc\b/ ) {
236 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_location}}");
238 if ( $Conf{ArchiveClientCmd} =~ /\$compression\b/ ) {
239 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_compression}}");
241 if ( $Conf{ArchiveClientCmd} =~ /\$parfile\b/
242 && -x $Conf{ParPath} ) {
243 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_parity}}");
245 if ( $Conf{ArchiveClientCmd} =~ /\$splitsize\b/
246 && -x $Conf{SplitPath} ) {
247 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_split}}");
249 my $content = eval("qq{$Lang->{BackupPC_Archive2}}");
250 Header(eval("qq{$Lang->{BackupPC__Archive}}"), $content, 1);
252 } elsif ( $In{type} == 2 ) {
254 my $archivehost = $1 if ( $In{archivehost} =~ /(.+)/ );
255 for ( my $i = 0 ; ; $i++ ) {
256 $reqFileName = "archiveReq.$$.$i";
257 last if ( !-f "$TopDir/pc/$archivehost/$reqFileName" );
259 my($compname, $compext);
260 if ( $In{compression} == 2 ) { # bzip2 compression
261 $compname = $Conf{Bzip2Path};
263 } elsif ( $In{compression} == 1 ) { # gzip compression
264 $compname = $Conf{GzipPath};
266 } else { # No Compression
267 $compname = $Conf{CatPath};
270 my $fullsplitsize = $In{splitsize} . '000000'; # mb -> bytes
272 # parameters for the archive
273 archiveloc => $In{archive_device},
274 archtype => $In{archive_type},
275 compression => $compname,
278 splitsize => $fullsplitsize,
279 host => $archivehost,
281 # list of hosts to restore
282 HostList => \@HostList,
283 BackupList => \@BackupList,
289 my($archive) = Data::Dumper->new(
293 my $openPath = "$TopDir/pc/$archivehost/$reqFileName";
294 if ( open(REQ, ">", $openPath) ) {
296 print(REQ $archive->Dump);
299 ErrorExit(eval("qq{$Lang->{Can_t_open_create__openPath}}"));
301 $reply = $bpc->ServerMesg("archive $User $archivehost $reqFileName");
302 $str = eval("qq{$Lang->{Archive_requested}}");
304 my $content = eval("qq{$Lang->{BackupPC_Archive_Reply_from_server}}");
305 Header(eval("qq{$Lang->{BackupPC__Archive}}"), $content, 1);