1 #============================================================= -*-perl-*-
3 # BackupPC::CGI::HostInfo package
7 # This module implements the HostInfo action for the CGI interface.
10 # Craig Barratt <cbarratt@users.sourceforge.net>
13 # Copyright (C) 2003 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 2.1.0_CVS, released 3 Jul 2003.
33 # See http://backuppc.sourceforge.net.
35 #========================================================================
37 package BackupPC::CGI::HostInfo;
40 use BackupPC::CGI::Lib qw(:all);
44 my $host = $1 if ( $In{host} =~ /(.*)/ );
45 my($statusStr, $startIncrStr);
49 return Action_GeneralInfo() if ( $host eq "" );
51 if ( !-d "$TopDir/pc/$host" && -d "$TopDir/pc/" . lc($host) );
52 if ( $host =~ /\.\./ || !-d "$TopDir/pc/$host" ) {
54 # try to lookup by user name
56 if ( !defined($Hosts->{$host}) ) {
57 foreach my $h ( keys(%$Hosts) ) {
58 if ( $Hosts->{$h}{user} eq $host
59 || lc($Hosts->{$h}{user}) eq lc($host) ) {
65 ErrorExit(eval("qq{$Lang->{Unknown_host_or_user}}"))
66 if ( !defined($Hosts->{$host}) );
70 GetStatusInfo("host(${EscURI($host)})");
71 $bpc->ConfigRead($host);
73 my $Privileged = CheckPermission($host);
75 ErrorExit(eval("qq{$Lang->{Only_privileged_users_can_view_information_about}}"));
79 my @Backups = $bpc->BackupInfoRead($host);
80 my($str, $sizeStr, $compStr, $errStr, $warnStr);
81 for ( my $i = 0 ; $i < @Backups ; $i++ ) {
82 my $startTime = timeStamp2($Backups[$i]{startTime});
83 my $dur = $Backups[$i]{endTime} - $Backups[$i]{startTime};
84 $dur = 1 if ( $dur <= 0 );
85 my $duration = sprintf("%.1f", $dur / 60);
86 my $MB = sprintf("%.1f", $Backups[$i]{size} / (1024*1024));
87 my $MBperSec = sprintf("%.2f", $Backups[$i]{size} / (1024*1024*$dur));
88 my $MBExist = sprintf("%.1f", $Backups[$i]{sizeExist} / (1024*1024));
89 my $MBNew = sprintf("%.1f", $Backups[$i]{sizeNew} / (1024*1024));
90 my($MBExistComp, $ExistComp, $MBNewComp, $NewComp);
91 if ( $Backups[$i]{sizeExist} && $Backups[$i]{sizeExistComp} ) {
92 $MBExistComp = sprintf("%.1f", $Backups[$i]{sizeExistComp}
94 $ExistComp = sprintf("%.1f%%", 100 *
95 (1 - $Backups[$i]{sizeExistComp} / $Backups[$i]{sizeExist}));
97 if ( $Backups[$i]{sizeNew} && $Backups[$i]{sizeNewComp} ) {
98 $MBNewComp = sprintf("%.1f", $Backups[$i]{sizeNewComp}
100 $NewComp = sprintf("%.1f%%", 100 *
101 (1 - $Backups[$i]{sizeNewComp} / $Backups[$i]{sizeNew}));
103 my $age = sprintf("%.1f", (time - $Backups[$i]{startTime}) / (24*3600));
104 my $browseURL = "$MyURL?action=browse&host=${EscURI($host)}&num=$Backups[$i]{num}";
105 my $filled = $Backups[$i]{noFill} ? $Lang->{No} : $Lang->{Yes};
106 $filled .= " ($Backups[$i]{fillFromNum}) "
107 if ( $Backups[$i]{fillFromNum} ne "" );
109 if ($Backups[$i]{type} eq "full") { $ltype = $Lang->{full}; }
110 else { $ltype = $Lang->{incremental}; }
112 <tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
113 <td align="center"> $ltype </td>
114 <td align="center"> $filled </td>
115 <td align="right"> $startTime </td>
116 <td align="right"> $duration </td>
117 <td align="right"> $age </td>
118 <td align="left"> <tt>$TopDir/pc/$host/$Backups[$i]{num}</tt> </td></tr>
121 <tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
122 <td align="center"> $ltype </td>
123 <td align="right"> $Backups[$i]{nFiles} </td>
124 <td align="right"> $MB </td>
125 <td align="right"> $MBperSec </td>
126 <td align="right"> $Backups[$i]{nFilesExist} </td>
127 <td align="right"> $MBExist </td>
128 <td align="right"> $Backups[$i]{nFilesNew} </td>
129 <td align="right"> $MBNew </td>
132 my $is_compress = $Backups[$i]{compress} || $Lang->{off};
133 if (! $ExistComp) { $ExistComp = " "; }
134 if (! $MBExistComp) { $MBExistComp = " "; }
136 <tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
137 <td align="center"> $ltype </td>
138 <td align="center"> $is_compress </td>
139 <td align="right"> $MBExist </td>
140 <td align="right"> $MBExistComp </td>
141 <td align="right"> $ExistComp </td>
142 <td align="right"> $MBNew </td>
143 <td align="right"> $MBNewComp </td>
144 <td align="right"> $NewComp </td>
148 <tr><td align="center"> <a href="$browseURL">$Backups[$i]{num}</a> </td>
149 <td align="center"> $ltype </td>
150 <td align="center"> <a href="$MyURL?action=view&type=XferLOG&num=$Backups[$i]{num}&host=${EscURI($host)}">$Lang->{XferLOG}</a>,
151 <a href="$MyURL?action=view&type=XferErr&num=$Backups[$i]{num}&host=${EscURI($host)}">$Lang->{Errors}</a> </td>
152 <td align="right"> $Backups[$i]{xferErrs} </td>
153 <td align="right"> $Backups[$i]{xferBadFile} </td>
154 <td align="right"> $Backups[$i]{xferBadShare} </td>
155 <td align="right"> $Backups[$i]{tarErrs} </td></tr>
159 my @Restores = $bpc->RestoreInfoRead($host);
162 for ( my $i = 0 ; $i < @Restores ; $i++ ) {
163 my $startTime = timeStamp2($Restores[$i]{startTime});
164 my $dur = $Restores[$i]{endTime} - $Restores[$i]{startTime};
165 $dur = 1 if ( $dur <= 0 );
166 my $duration = sprintf("%.1f", $dur / 60);
167 my $MB = sprintf("%.1f", $Restores[$i]{size} / (1024*1024));
168 my $MBperSec = sprintf("%.2f", $Restores[$i]{size} / (1024*1024*$dur));
169 my $Restores_Result = $Lang->{failed};
170 if ($Restores[$i]{result} ne "failed") { $Restores_Result = $Lang->{success}; }
171 $restoreStr .= <<EOF;
172 <tr><td align="center"><a href="$MyURL?action=restoreInfo&num=$Restores[$i]{num}&host=${EscURI($host)}">$Restores[$i]{num}</a> </td>
173 <td align="center"> $Restores_Result </td>
174 <td align="right"> $startTime </td>
175 <td align="right"> $duration </td>
176 <td align="right"> $Restores[$i]{nFiles} </td>
177 <td align="right"> $MB </td>
178 <td align="right"> $Restores[$i]{tarCreateErrs} </td>
179 <td align="right"> $Restores[$i]{xferErrs} </td>
183 if ( $restoreStr ne "" ) {
184 $restoreStr = eval("qq{$Lang->{Restore_Summary}}");
186 if ( @Backups == 0 ) {
187 $warnStr = $Lang->{This_PC_has_never_been_backed_up};
189 if ( defined($Hosts->{$host}) ) {
190 my $user = $Hosts->{$host}{user};
191 my @moreUsers = sort(keys(%{$Hosts->{$host}{moreUsers}}));
193 foreach my $u ( sort(keys(%{$Hosts->{$host}{moreUsers}})) ) {
194 $moreUserStr .= ", " if ( $moreUserStr ne "" );
195 $moreUserStr .= "${UserLink($u)}";
197 if ( $moreUserStr ne "" ) {
198 $moreUserStr = " ($Lang->{and} $moreUserStr).\n";
200 $moreUserStr = ".\n";
203 $statusStr .= eval("qq{$Lang->{This_PC_is_used_by}$moreUserStr}");
205 if ( defined($UserEmailInfo{$user})
206 && $UserEmailInfo{$user}{lastHost} eq $host ) {
207 my $mailTime = timeStamp2($UserEmailInfo{$user}{lastTime});
208 my $subj = $UserEmailInfo{$user}{lastSubj};
209 $statusStr .= eval("qq{$Lang->{Last_email_sent_to__was_at___subject}}");
212 if ( defined($Jobs{$host}) ) {
213 my $startTime = timeStamp2($Jobs{$host}{startTime});
214 (my $cmd = $Jobs{$host}{cmd}) =~ s/$BinDir\///g;
215 $statusStr .= eval("qq{$Lang->{The_command_cmd_is_currently_running_for_started}}");
217 if ( $StatusHost{BgQueueOn} ) {
218 $statusStr .= eval("qq{$Lang->{Host_host_is_queued_on_the_background_queue_will_be_backed_up_soon}}");
220 if ( $StatusHost{UserQueueOn} ) {
221 $statusStr .= eval("qq{$Lang->{Host_host_is_queued_on_the_user_queue__will_be_backed_up_soon}}");
223 if ( $StatusHost{CmdQueueOn} ) {
224 $statusStr .= eval("qq{$Lang->{A_command_for_host_is_on_the_command_queue_will_run_soon}}");
226 my $startTime = timeStamp2($StatusHost{endTime} == 0 ?
227 $StatusHost{startTime} : $StatusHost{endTime});
229 if ( $StatusHost{reason} ne "" ) {
230 $reason = " ($Lang->{$StatusHost{reason}})";
232 $statusStr .= eval("qq{$Lang->{Last_status_is_state_StatusHost_state_reason_as_of_startTime}}");
234 if ( $StatusHost{state} ne "Status_backup_in_progress"
235 && $StatusHost{state} ne "Status_restore_in_progress"
236 && $StatusHost{error} ne "" ) {
237 $statusStr .= eval("qq{$Lang->{Last_error_is____EscHTML_StatusHost_error}}");
239 my $priorStr = "Pings";
240 if ( $StatusHost{deadCnt} > 0 ) {
241 $statusStr .= eval("qq{$Lang->{Pings_to_host_have_failed_StatusHost_deadCnt__consecutive_times}}");
242 $priorStr = $Lang->{Prior_to_that__pings};
244 if ( $StatusHost{aliveCnt} > 0 ) {
245 $statusStr .= eval("qq{$Lang->{priorStr_to_host_have_succeeded_StatusHostaliveCnt_consecutive_times}}");
247 if ( $StatusHost{aliveCnt} >= $Conf{BlackoutGoodCnt}
248 && $Conf{BlackoutGoodCnt} >= 0 && $Conf{BlackoutHourBegin} >= 0
249 && $Conf{BlackoutHourEnd} >= 0 ) {
250 my(@days) = qw(Sun Mon Tue Wed Thu Fri Sat);
251 my($days) = join(", ", @days[@{$Conf{BlackoutWeekDays}}]);
252 my($t0) = sprintf("%d:%02d", $Conf{BlackoutHourBegin},
253 60 * ($Conf{BlackoutHourBegin}
254 - int($Conf{BlackoutHourBegin})));
255 my($t1) = sprintf("%d:%02d", $Conf{BlackoutHourEnd},
256 60 * ($Conf{BlackoutHourEnd}
257 - int($Conf{BlackoutHourEnd})));
258 $statusStr .= eval("qq{$Lang->{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___}}");
261 if ( $StatusHost{backoffTime} > time ) {
262 my $hours = sprintf("%.1f", ($StatusHost{backoffTime} - time) / 3600);
263 $statusStr .= eval("qq{$Lang->{Backups_are_deferred_for_hours_hours_change_this_number}}");
267 # only allow incremental if there are already some backups
268 $startIncrStr = <<EOF;
269 <input type="submit" value="\$Lang->{Start_Incr_Backup}" name="action">
273 $startIncrStr = eval ("qq{$startIncrStr}");
275 Header(eval("qq{$Lang->{Host__host_Backup_Summary}}"));
276 print(eval("qq{$Lang->{Host__host_Backup_Summary2}}"));