package SrvMngr::Controller::Backup;
#----------------------------------------------------------------------
# heading : System
# description : Backup or restore
# navigation : 4000 200
# Copyright (C) 2002 Mitel Networks Corporation
#----------------------------------------------------------------------
# routes : end
# for information - routes
# $if_admin->get('/backup')->to('backup#main')->name('backup');
# $if_admin->post('/backup')->to('backup#do_display')->name('backupd');
# $if_admin->get('/backupd')->to('backup#do_display')->name('backupc');
# $if_admin->post('/backupd')->to('backup#do_update')->name('backupu');
use strict;
use warnings;
use Mojo::Base 'Mojolicious::Controller';
use utf8;
use Locale::gettext;
use SrvMngr::I18N;
use SrvMngr qw(theme_list init_session ip_number_or_blank);
use Quota;
use esmith::ConfigDB;
use esmith::AccountsDB;
use esmith::util;
use File::Basename;
use File::Find;
use File::Path qw(make_path remove_tree);
use esmith::Backup;
use esmith::BackupHistoryDB;
use esmith::util;
use esmith::lockfile;
use esmith::BlockDevices;
use constant DEBUG => $ENV{MOJO_SMANAGER_DEBUG} || 0;
our $cdb = esmith::ConfigDB->open || die "Couldn't open config db";
our $adb = esmith::AccountsDB->open || die "Couldn't open accounts db";
our $rdb = esmith::ConfigDB->open('/etc/e-smith/restore')
|| die "Couldn't open restore db";
my $es_backup = new esmith::Backup or die "Couldn't create Backup object\n";
my @directories = $es_backup->restore_list;
@directories = grep { -e "/$_" } @directories;
my @backup_excludes = $es_backup->excludes;
# Unbuffer standard output so that files and directories are listed as
# they are restored
$| = 1;
# Store away current gid of 'www' group.
my $www_gid = getgrnam("www");
sub main {
my $c = shift;
$c->app->log->info($c->log_req);
my %bac_datas = ();
my $title = $c->l('bac_BACKUP_TITLE');
my $notif;
$bac_datas{'function'} = 'desktop_backup';
my ($tarsize, $dumpsize, undef, undef) = $c->CalculateSizes();
my $module = $cdb->get('backup');
if ($module) {
$module = $module->prop('Program');
}
# The default e-smith backup program is flexbackup.
unless (defined $module) {
$module = "flexbackup";
} elsif ($module eq '') {
$module = "flexbackup";
}
$bac_datas{'tarsize'} = $tarsize;
$bac_datas{'dumpsize'} = $dumpsize;
$bac_datas{'module'} = $module;
if ($tarsize =~ /Tb/ or $tarsize =~ /(\d+)Gb/ and $1 >= 2) {
$notif = $c->l("bac_BACKUP_DESKTOP_TOO_BIG") . ' : ' . $tarsize;
}
my $rec = $cdb->get('backup');
my ($backup_status, $backupwk_status) = 'disabled';
if ($rec) {
$backup_status = $rec->prop('status') || 'disabled';
}
if ($backup_status eq "enabled") {
$bac_datas{'backupTime'} = $rec->prop('backupTime');
$bac_datas{'reminderTime'} = $rec->prop('reminderTime');
}
$rec = $cdb->get('backupwk');
if ($rec) {
$backupwk_status = $rec->prop('status') || 'disabled';
}
if ($backupwk_status eq "enabled") {
$bac_datas{'backupwkTime'} = $rec->prop('BackupTime');
}
$bac_datas{'backupStatus'} = $backup_status;
$bac_datas{'backupwkStatus'} = $backupwk_status;
$c->stash(warning => $notif) if ($notif);
$c->stash(title => $title, bac_datas => \%bac_datas);
$c->render(template => 'backup');
} ## end sub main
sub do_display {
my $c = shift;
$c->app->log->info($c->log_req);
my $rt = $c->current_route;
my ($res, $result) = '';
my $function = $c->param('Function');
if ($function =~ /^(\S+)$/) {
$function = $1;
} elsif ($function =~ /^\s*$/) {
$function = "zoverall";
} else {
$result = $c->l('bac_INVALID_FUNCTION') . $function;
$function = undef;
}
DEBUG && warn("do_display $function");
my %bac_datas = ();
$bac_datas{'function'} = $function;
my $title = $c->l('bac_BACKUP_TITLE');
my $dest = '';
if ($function eq 'desktop_backup') {
my $CompressionLevel = $cdb->get_prop("backupconsole", "CompressionLevel") || "-6";
my @exclude = map (" --exclude=$_", @backup_excludes);
$c->stash(compressionlevel => $CompressionLevel, exclude => \@exclude, directories => \@directories);
# streaming download in template
return $c->render("/backdown");
} ## end if ($function eq 'desktop_backup')
if ($function eq 'tape_configure') {
$bac_datas{'status'} = 'unchecked';
my $backupTime = "2:00";
my $rec = $cdb->get('backup');
if ($rec) {
$backupTime = $rec->prop('backupTime') || "2:00";
my $backup_status = $rec->prop('status');
if (defined $backup_status && $backup_status eq "enabled") {
$bac_datas{'status'} = "checked";
}
} ## end if ($rec)
($bac_datas{backupAMPM}, $bac_datas{reminderAMPM}) = 'AM';
($bac_datas{backupHour}, $bac_datas{backupMin}) = split(":", $backupTime, -1);
if ($bac_datas{backupHour} > 11) {
if ($bac_datas{backupHour} > 12) {
$bac_datas{backupHour} -= 12;
}
$bac_datas{backupAMPM} = 'PM';
} ## end if ($bac_datas{backupHour...})
# Obtain time for reminder notice from the backup cron template
my $reminderTime = "14:00";
if ($rec) {
$reminderTime = $rec->prop('reminderTime') || "14:00";
}
($bac_datas{reminderHour}, $bac_datas{reminderMin}) = split(":", $reminderTime, -1);
if ($bac_datas{reminderHour} > 12) {
$bac_datas{reminderHour} -= 12;
$bac_datas{reminderAMPM} = 'PM';
}
} ## end if ($function eq 'tape_configure')
if ($function eq 'workstn_configure') {
my $rec = $cdb->get('backupwk');
$bac_datas{vfstype} = $rec->prop('VFSType') || 'cifs';
$bac_datas{status} = $rec->prop('status');
} ## end if ($function eq 'workstn_configure')
if ($function eq 'workstn_configure1') {
$bac_datas{vfstype} = $c->param('VFSType');
$bac_datas{'status'} = '';
$bac_datas{ampm} = 'AM';
$bac_datas{min} = '';
$bac_datas{hour} = '';
$bac_datas{login} = 'backup';
$bac_datas{password} = 'backup';
$bac_datas{station} = 'host';
$bac_datas{folder} = 'share';
$bac_datas{mount} = '';
$bac_datas{setsNumber} = '';
$bac_datas{filesinset} = '';
$bac_datas{timeout} = '';
$bac_datas{incOnlyTimeout} = '';
$bac_datas{compression} = '';
$bac_datas{dof} = '';
# Obtain backup informations from configuration
my $rec = $cdb->get('backupwk');
my $Time = '2:00';
if ($rec) {
$Time = $rec->prop('BackupTime') || '2:00';
$bac_datas{login} = $rec->prop('Login') || 'backup';
$bac_datas{password} = $rec->prop('Password') || 'backup';
$bac_datas{station} = $rec->prop('SmbHost') || 'host';
$bac_datas{folder} = $rec->prop('SmbShare') || 'share';
$bac_datas{mount} = $rec->prop('Mount') || '';
$bac_datas{setsNumber} = $rec->prop('SetsMax') || '1';
$bac_datas{filesinset} = $rec->prop('DaysInSet') || '1';
$bac_datas{timeout} = $rec->prop('Timeout') || '12';
$bac_datas{incOnlyTimeout} = $rec->prop('IncOnlyTimeout') || 'yes';
$bac_datas{compression} = $rec->prop('Compression') || '0';
$bac_datas{dof} = (defined $rec->prop('FullDay')) ? $rec->prop('FullDay') : '7';
} ## end if ($rec)
($bac_datas{hour}, $bac_datas{min}) = split(':', $Time, -1);
if ($bac_datas{hour} > 12) {
$bac_datas{hour} -= 12;
$bac_datas{ampm} = 'PM';
}
my $backupwk_status;
if ($rec) {
$backupwk_status = $rec->prop('status');
}
if (defined $backupwk_status && $backupwk_status eq 'enabled') {
$bac_datas{status} = 'checked';
}
if (defined $bac_datas{incOnlyTimeout} && $bac_datas{incOnlyTimeout} eq 'yes') {
$bac_datas{incOnlyTimeout} = 'checked';
}
} ## end if ($function eq 'workstn_configure1')
if ($function eq 'workstn_verify') {
my $rec = $cdb->get('backupwk');
if ($rec) {
$bac_datas{status} = $rec->prop('status') || 'disabled';
}
} ## end if ($function eq 'workstn_verify')
if ($function eq 'workstn_verify1') {
$res = '';
if (!$result) {
$bac_datas{function} = $function;
}
} ## end if ($function eq 'workstn_verify1')
if ($function eq 'workstn_restore') {
my $rec = $cdb->get('backupwk');
if ($rec) {
$bac_datas{status} = $rec->prop('status') || 'disabled';
}
} ## end if ($function eq 'workstn_restore')
$dest = "back_$function";
$c->stash(error => $result);
$c->stash(title => $title, bac_datas => \%bac_datas);
return $c->render(template => $dest);
} ## end sub do_display
sub do_update {
my $c = shift;
$c->app->log->info($c->log_req);
my $rt = $c->current_route;
my $function = $c->param('Function');
DEBUG && warn("do_update $function");
my %bac_datas = ();
$bac_datas{function} = $function;
my $title = $c->l('bac_BACKUP_TITLE');
my ($dest, $res, $result) = '';
if ($function eq 'desktop_backup') {
# should not happen !! no desktop_backup template !!
$result .= ' ** Function error for desktop backup ** !';
} ## end if ($function eq 'desktop_backup')
if ($function eq 'tape_configure') {
my $status = $c->param('Tapebackup');
my $backupHour = $c->param('BackupHour');
my $backupMin = $c->param('BackupMin');
my $bampm = $c->param('BackupAMPM');
my $reminderHour = $c->param('ReminderHour');
my $reminderMin = $c->param('ReminderMin');
my $rampm = $c->param('ReminderAMPM');
if (defined $status && $status eq "on") {
if ($backupHour =~ /^(.*)$/) {
$backupHour = $1;
} else {
$backupHour = "12";
}
if (($backupHour < 1) || ($backupHour > 12)) {
$result .= $c->l('bac_ERR_INVALID_HOUR') . $backupHour . ' ' . $c->l('bac_BETWEEN_0_AND_12') . ' ';
}
if ($backupMin =~ /^(.*)$/) {
$backupMin = $1;
} else {
$backupMin = "0";
}
if (($backupMin < 0) || ($backupMin > 59)) {
$result .= $c->l('bac_ERR_INVALID_MINUTE') . $backupMin . ' ' . $c->l('bac_BETWEEN_0_AND_59') . ' ';
}
if ($reminderHour =~ /^(.*)$/) {
$reminderHour = $1;
} else {
$reminderHour = "12";
}
if (($reminderHour < 1) || ($reminderHour > 12)) {
$result
.= $c->l('bac_ERR_INVALID_REMINDER_HOUR')
. $reminderHour . ' '
. $c->l('bac_BETWEEN_0_AND_12') . ' ';
} ## end if (($reminderHour < 1...))
if ($reminderMin =~ /^(.*)$/) {
$reminderMin = $1;
} else {
$reminderMin = "0";
}
if (($reminderMin < 0) || ($reminderMin > 59)) {
$result
.= $c->l('bac_ERR_INVALID_REMINDER_MINUTE')
. $reminderMin . ' '
. $c->l('bac_BETWEEN_0_AND_59') . ' ';
} ## end if (($reminderMin < 0)...)
} else {
# service disabled no controls
}
##$result .= ' ** Blocked for testing ** !';
$res = '';
if (!$result) {
$res = $c->tapeBackupConfig($status, $backupHour, $backupMin, $bampm, $reminderHour, $reminderMin, $rampm);
$result .= $res unless $res eq 'OK';
if (!$result) {
if (defined $status && $status eq "on") {
$result
.= ( $c->l('bac_SUCCESSFULLY_ENABLED_TAPE') . ' '
. $c->l('bac_WITH_BACKUP_TIME')
. "$backupHour:$backupMin" . ' '
. $c->l('bac_WITH_REMINDER_TIME')
. "$reminderHour:$reminderMin");
} else {
$result .= $c->l('bac_SUCCESSFULLY_DISABLED');
}
$cdb->reload;
} ## end if (!$result)
} ## end if (!$result)
} ## end if ($function eq 'tape_configure')
if ($function eq 'tape_restore') {
my $lock_file = "/var/lock/subsys/e-smith-restore";
my $file_handle = &esmith::lockfile::LockFileOrReturn($lock_file);
unless ($file_handle) {
$result .= $c->l('bac_UNABLE_TO_RESTORE_CONF') . ' ' . $c->l('bac_ANOTHER_RESTORE_IN_PROGRESS');
}
##$result .= ' ** Blocked for testing ** !';
$res = '';
if (!$result) {
$res = $c->tapeRestore($lock_file, $file_handle);
$result .= $res unless $res eq 'OK';
#if ( ! $result ) {
#$result = $c->l('bac_SUCCESS');
#}
} ## end if (!$result)
} ## end if ($function eq 'tape_restore')
if ($function eq 'workstn_configure') {
# should not happen !!
$result .= ' ** Function error for workstation configure *** !';
} ## end if ($function eq 'workstn_configure')
if ($function eq 'workstn_configure1') {
#$result .= ' ** Blocked for testing ** !';
$res = '';
if (!$result) {
$res = $c->updateWorkstnBackupConfig();
if (($result = $res) =~ s|^#OK#||) {
$res = 'OK';
$cdb->reload;
}
} ## end if (!$result)
} ## end if ($function eq 'workstn_configure1')
if ($function eq 'workstn_verify') {
# should not happen !!
$result .= ' ** Function error for workstation verify *** !';
} ## end if ($function eq 'workstn_verify')
if ($function eq 'workstn_verify1') {
##$result .= ' ** Blocked for testing ** !';
$res = 'OK';
$result = '';
} ## end if ($function eq 'workstn_verify1')
if ($function eq 'workstn_restore') {
##$result .= ' ** Blocked for testing ** !';
$res = 'NOK';
if (!$result) {
$res = $c->workstnRestore();
if (($result = $res) =~ s|^#OK#||) {
$bac_datas{restore_log} = $result;
$res = 'OK';
} else {
$c->stash(error => $result);
}
$bac_datas{function} = 'workstn_restore1';
$res = 'NEXT';
} ## end if (!$result)
} ## end if ($function eq 'workstn_restore')
if ($function eq 'workstn_restore1') {
my $state = 'unknown';
my $rec = $rdb->get('restore');
if ($rec) {
$state = $rec->prop('state') || 'unknown';
}
$result .= "Restore state unexpected: $state" if ($state ne 'complete');
$res = 'NOK';
if (!$result) {
$res = $c->performReboot();
if (($result = $res) =~ s|^#OK#||) {
$res = 'OK';
} else {
$c->stash(error => $result);
}
} ## end if (!$result)
} ## end if ($function eq 'workstn_restore1')
if ($function eq 'workstn_sel_restore') {
my $backupset = $c->param('Backupset');
my $filterexp = $c->param('Filterexp');
if ($filterexp =~ /^(.*)$/) {
$filterexp = $1;
} else {
$filterexp = '';
}
#$result .= ' ** Blocked for testing 1 ** !';
$res = '';
if (!$result) {
$bac_datas{function} = 'workstn_sel_restore1';
$bac_datas{backupset} = $backupset;
$bac_datas{filterexp} = $filterexp;
$res = 'NEXT';
} ## end if (!$result)
} ## end if ($function eq 'workstn_sel_restore')
if ($function eq 'workstn_sel_restore1') {
$bac_datas{backupset} = $c->param('Backupset');
$bac_datas{filterexp} = $c->param('Filterexp');
my @restorefiles = @{ $c->every_param('Restorefiles') };
my $seldatebefore = $c->param('Seldatebefore');
if ($seldatebefore =~ /^(.*)$/) {
$seldatebefore = $1;
} else {
$result .= 'Unsecure data : ' . $seldatebefore;
}
my $tymd = qr/((19|20)\d\d\/(?=\d\d\/\d\d-))?((0?[1-9]|1[0-2])\/(?=\d\d-))?((31|[123]0|[012]?[1-9])-)?/;
my $thms = qr/([01]?[0-9]|2[0-3]):([0-5][0-9])(:[0-5][0-9])?/;
$result .= " $seldatebefore : " . $c->l('bac_ERR_INVALID_SELDATE')
unless (($seldatebefore =~ m/^$tymd$thms$/) || ($seldatebefore eq ""));
##$result .= ' ** Blocked for testing 2 ** !';
$res = '';
if (!$result) {
$res = $c->performWorkstnSelRestore($seldatebefore, \@restorefiles); # restore log returned
if (($result = $res) =~ s|^#OK#||) {
$bac_datas{restore_log} = $result;
$res = 'OK';
} else {
$c->stash(error => $result);
}
$bac_datas{function} = 'workstn_sel_restore2';
$res = 'NEXT';
} ## end if (!$result)
} ## end if ($function eq 'workstn_sel_restore1')
if ($function eq 'workstn_sel_restore2') {
##$result .= ' ** Blocked for testing 3 ** !';
$res = 'OK';
$result = '';
} ## end if ($function eq 'workstn_sel_restore2')
# common part for all functions
if ($res ne 'OK') {
if ($res eq 'NEXT') {
$dest = 'back_' . $bac_datas{"function"};
} else {
$c->stash(error => $result);
$dest = "back_$function";
}
$c->stash(title => $title, bac_datas => \%bac_datas);
return $c->render($dest);
} ## end if ($res ne 'OK')
my $message = "'Backup' $function updates DONE";
$c->app->log->info($message);
$c->flash(success => $result);
$c->redirect_to('backup');
} ## end sub do_update
sub tapeBackupConfig {
my ($c, $status, $backupHour, $backupMin, $bampm, $reminderHour, $reminderMin, $rampm) = @_;
if (defined $status && $status eq "on") {
$backupMin = sprintf("%02d", $backupMin);
if ($bampm =~ /^(.*)$/) {
$bampm = $1;
} else {
$bampm = "AM";
}
# convert to 24 hour time
$backupHour = $backupHour % 12;
if ($bampm eq "PM") {
$backupHour = $backupHour + 12;
}
$reminderMin = sprintf("%02d", $reminderMin);
if ($rampm =~ /^(.*)$/) {
$rampm = $1;
} else {
$rampm = "AM";
}
# convert to 24 hour time
$reminderHour = $reminderHour % 12;
if ($rampm eq "PM") {
$reminderHour = $reminderHour + 12;
}
# variables passed validity checks, set configuration database values
my $oldUnsav = $cdb->get('UnsavedChanges')->value;
my $rec = $cdb->get('backup');
unless (defined $rec) {
$rec = $cdb->new_record('backup', { type => 'service' });
}
$rec->set_prop('status', 'enabled');
my $module = $rec->prop('Program');
# The default e-smith backup program is flexbackup.
unless (defined $module) {
$module = "flexbackup";
} elsif ($module eq '') {
$module = "flexbackup";
}
$rec->set_prop('Program', $module);
$rec->set_prop('backupTime', "$backupHour:$backupMin");
$rec->set_prop('reminderTime', "$reminderHour:$reminderMin");
$cdb->get('UnsavedChanges')->set_value($oldUnsav);
system("/sbin/e-smith/signal-event", "conf-backup") == 0
or return ($c->l('bac_ERR_CONF_BACKUP'), "\n");
return 'OK';
} else {
# set service to disabled
my $oldUnsav = $cdb->get('UnsavedChanges')->value;
my $rec = $cdb->get('backup');
unless ($rec) {
$rec = $cdb->new_record('backup', { type => 'service' });
}
$rec->set_prop('status', 'disabled');
$cdb->get('UnsavedChanges')->set_value($oldUnsav);
system("/sbin/e-smith/signal-event", "conf-backup") == 0
or return ($c->l('bac_ERR_CONF_BACKUP') . "\n");
return 'OK';
} ## end else [ if (defined $status &&...)]
return undef;
} ## end sub tapeBackupConfig
sub tapeRestore {
my ($c, $lock_file, $file_handle) = @_;
my $rec = $rdb->get('restore');
$rec->set_prop('state', 'running');
$rec->set_prop('start', time);
my $child;
if ($child = fork) {
# Parent
$SIG{'CHLD'} = 'IGNORE';
&esmith::lockfile::UnlockFile($file_handle);
return 'OK';
} elsif (defined $child) {
# Child
# Re-establish the lock. Wait till it is relinquished by the parent.
$file_handle = &esmith::lockfile::LockFileOrWait($lock_file);
# Close STDOUT so that the web server connection is closed.
close STDOUT;
# Now reopen STDOUT for the child. Redirect it to STDERR.
open(STDOUT, ">&STDERR");
unless (system("/sbin/e-smith/signal-event", "pre-restore") == 0) {
$rec->set_prop('errmsg', $c->l('bac_ERR_PRE_RESTORE'));
$rec->delete_prop('state');
die($c->l('bac_ERR_PRE_RESTORE'), "\n");
} ## end unless (system("/sbin/e-smith/signal-event"...))
unless (system("/sbin/e-smith/signal-event", "restore-tape") == 0) {
$rec->set_prop('errmsg', $c->l('bac_ERR_RESTORING_FROM_TAPE'));
$rec->delete_prop('state');
die($c->l('bac_ERR_RESTORING_FROM_TAPE') . "\n");
} ## end unless (system("/sbin/e-smith/signal-event"...))
#----------------------------------------
# regenerate configuration files
#----------------------------------------
unless (system("/usr/sbin/groupmod", "-g", "$www_gid", "www") == 0) {
$rec->set_prop('errmsg', $rec->prop('errmsg') . ', ' . $c->l('bac_ERR_RESTORING_GID'));
warn($c->l('bac_ERR_RESTORING_GID') . "\n");
}
unless (system("/usr/sbin/usermod", "-g", "$www_gid", "www") == 0) {
$rec->set_prop('errmsg', $rec->prop('errmsg') . ', ' . $c->l('bac_ERR_RESTORING_INITIAL_GRP'));
warn($c->l('bac_ERR_RESTORING_INITIAL_GRP') . "\n");
}
esmith::util::backgroundCommand(0, "/sbin/e-smith/signal-event", "post-upgrade");
#unless(system("/sbin/e-smith/signal-event", "post-upgrade") == 0) {
# $rec->set_prop('errmsg', $rec->prop('errmsg').', '.
# $c->l('bac_ERR_UPDATING_CONF_AFTER_TAPE_RESTORE'));
# $rec->delete_prop('state');
# die ($c->l('bac_ERR_UPDATING_CONF_AFTER_TAPE_RESTORE'));
#}
my $finish = time;
$rec->set_prop('state', 'complete');
$rec->set_prop('finish', $finish);
my $start = $rec->prop('start');
$start = scalar localtime($start);
$finish = scalar localtime($finish);
&esmith::lockfile::UnlockFile($file_handle);
exit;
} else {
# Error
$rec->delete_prop('state');
$rec->set_prop('errmsg', $c->l('bac_COULD_NOT_FORK'));
die($c->l("bac_COULD_NOT_FORK") . " $!\n");
} ## end else [ if ($child = fork) ]
} ## end sub tapeRestore
sub workstnBackupConfig {
# called by template
my ($c) = @_;
my $out;
my $backupwk_status;
my $enabledIncOnlyTimeout = "";
my $backupwkLogin = 'backup';
my $backupwkPassword = 'backup';
my $backupwkStation = 'host';
my $backupwkFolder = 'share';
my $backupwkMount = '/mnt/smb';
my $setsNumber;
my $filesinset;
my $backupwkTime;
my $backupwkTimeout;
my $backupwkIncOnlyTimeout;
my $VFSType;
my $compression;
my $dof;
my @dlabels = split(' ', $c->l('bac_DOW'));
# Obtain backup informations from configuration
my $rec = $cdb->get('backupwk');
if ($rec) {
$backupwkTime = $rec->prop('BackupTime') || '2:00';
$backupwkLogin = $rec->prop('Login') || 'backup';
$backupwkPassword = $rec->prop('Password') || 'backup';
$backupwkStation = $rec->prop('SmbHost') || 'host';
$backupwkFolder = $rec->prop('SmbShare') || 'share';
$backupwkMount = $rec->prop('Mount') || '/mnt/smb';
$VFSType = $rec->prop('VFSType') || 'cifs';
$setsNumber = $rec->prop('SetsMax') || '1';
$filesinset = $rec->prop('DaysInSet') || '1';
$backupwkTimeout = $rec->prop('Timeout') || '12';
$backupwkIncOnlyTimeout = $rec->prop('IncOnlyTimeout') || 'yes';
$compression = $rec->prop('Compression') || '0';
$dof = (defined $rec->prop('FullDay')) ? $rec->prop('FullDay') : '7';
$backupwk_status = $rec->prop('status');
} ## end if ($rec)
if ($rec) {
if ($VFSType eq 'usb') {
$out .= $c->l('bac_WORKSTN_BACKUP_USB') . ' ' . $backupwkFolder . '
';
} elsif ($VFSType eq 'mnt') {
$out .= $c->l('bac_WORKSTN_BACKUP_MNT') . ' ' . $backupwkMount . '
';
} else {
$out .= $c->l('bac_WORKSTN_BACKUP_HOST') . ' ' . $backupwkStation . ' ';
$out .= $c->l('bac_WORKSTN_BACKUP_VFSTYPE') . ' ' . $VFSType . '
';
$out .= $c->l('bac_WORKSTN_BACKUP_SHARE') . ' ' . $backupwkFolder . '
';
}
if ($VFSType eq 'cifs') {
$out .= $c->l('bac_LOGIN') . ' ' . $backupwkLogin . '
';
$out .= $c->l('PASSWORD') . ' ********
';
}
$out .= $c->l('bac_WORKSTN_BACKUP_SETSNUM') . ' ' . $setsNumber . '
';
$out .= $c->l('bac_WORKSTN_BACKUP_DAYSINSET') . ' ' . $filesinset . '
';
$out .= $c->l('bac_WORKSTN_BACKUP_COMPRESSION') . ' ' . $compression . '
';
$out .= $c->l('bac_WORKSTN_BACKUP_TOD') . ' ' . $backupwkTime . '
';
$out .= $c->l('bac_WORKSTN_BACKUP_TIMEOUT') . ' ' . $backupwkTimeout . ' ' . $c->l('bac_HOURS');
if ($backupwkIncOnlyTimeout eq 'yes') {
$out .= $c->l('bac_WORKSTN_BACKUP_INCONLY_TIMEOUT');
}
$out .= '
';
if ($dof eq '7') {
$out .= $c->l('bac_WORKSTN_FULL_BACKUP_EVERYDAY') . '
';
} else {
$out .= $c->l('bac_WORKSTN_FULL_BACKUP_DAY') . ' ' . $dlabels[$dof] . '
';
}
} else {
$out = $c->l('bac_WORKSTN_BACKUP_NOT_CONFIGURED');
}
return $out;
} ## end sub workstnBackupConfig
sub workstnVerify {
my ($c) = @_;
my $out;
my $backupwkrec = $cdb->get('backupwk');
my $smbhost = $backupwkrec->prop('SmbHost');
my $smbshare = $backupwkrec->prop('SmbShare');
my $mntdir = $backupwkrec->prop('Mount') || '/mnt/smb';
my $key;
my $error_message;
my $id = $backupwkrec->prop('Id')
|| $cdb->get('SystemName')->value . '.' . $cdb->get('DomainName')->value;
my $err;
my $VFSType = $backupwkrec->prop('VFSType') || 'cifs';
my $verifyref = $c->param('Backupset');
$mntdir = "/$smbshare" if ($VFSType eq 'usb');
# Mounting backup shared folder
$error_message = $c->bmount($mntdir, $smbhost, $smbshare, $VFSType);
if ($error_message) {
return $error_message . ' ' . $id;
}
# Test if backup subdirectory for our server
my $mntbkdir = $mntdir . "/$id";
unless (-d $mntbkdir) {
$error_message = $c->l('bac_ERR_NO_HOST_DIR') . "\n";
$error_message .= $c->bunmount($mntdir, $VFSType);
return $error_message . ' ' . $id;
} ## end unless (-d $mntbkdir)
my $fullverify = $c->param('Verifyall') || '';
if ($fullverify eq "on") {
# Test all backups needed to full restore
my %backupsetfiles = ();
my @restorefiles;
my $set = $verifyref;
$set =~ s/\/[^\/]*$//;
my $backupsetlist = sub {
if ($_ =~ /\.dar/) {
my $backupref = $File::Find::name;
$backupref =~ s/\.[0-9]+\.dar//;
$_ =~ s/\..*\.dar//;
$_ =~ s/.*-//;
$backupsetfiles{$_} = $backupref;
} ## end if ($_ =~ /\.dar/)
};
# find list of available backups and verify
# it contains all backups needed for full restore
find { wanted => \&$backupsetlist, untaint => 1, untaint_pattern => qr|^([-+@\w\s./]+)$| }, $set;
my $key;
my $num = 0;
foreach $key (sort keys %backupsetfiles) {
push @restorefiles, $backupsetfiles{$key};
if ($num == 0) {
unless ($backupsetfiles{$key} =~ /\/full-/) {
$out .= $c->l('bac_ERR_NO_FULL_BACKUP');
return $out;
}
} else {
my $numf = sprintf("%03d", $num);
unless ($backupsetfiles{$key} =~ /\/inc-$numf-/) {
$out .= $c->l('bac_ERR_NO_INC_BACKUP') . " " . $numf;
return $out;
}
} ## end else [ if ($num == 0) ]
$num++;
last if ($backupsetfiles{$key} eq $verifyref);
} ## end foreach $key (sort keys %backupsetfiles)
if (open(RD, "-|")) {
$out .= '' . $c->l('bac_TESTING_NEEDED_BACKUPS_FOR_RESTORE') . '