#!/usr/bin/perl
#
# Script to be run by cron each night to backup locations specified in
# /etc/slbackup/slbackup.conf
#
# $Id: slbackup-cron,v 1.4 2003/11/23 20:37:24 werner-guest Exp $
#

use strict;
use Config::General;
use POSIX qw(strftime);
use SLBackup;

my $logfile = "/var/log/slbackup/slbackup.log";


# open logfile
open (LOG, ">>$logfile") or die ("Unable to open $logfile\n");
logger ("Starting slbackup:");

# fetch configuration
my $conffile = '/etc/slbackup/slbackup.conf';
my $config = &slbackup_readconfig($conffile);

# run rdiff-backup for each client in configuration
for my $key (keys %{$config->{client}}) {
    my $client = $config->{client}->{$key};
    my $execstr = "";
    my $execstr_serverpart = "";
    my $execstr_clientpart = "";

    # check if server is not of type "local" ->
    #   add server-part of the exeecstr in a 
    if (exists ($config->{server_type}) and
	$config->{server_type} ne "local") {
	
	# check if server_address is present in configuration
	#FIXME - check that the address is valid
	if (!exists ($config->{server_address})) {
	    logger ("Address for server is not present in configuration " .
		    "file... please fix!");
	    logger("Failed backing up clients.");
	    last;
	}
	
	# check if server_user is present in configuration
	if (!exists ($config->{server_user})) {
	    logger ("Username for server is not present in configuration " .
		    "file... please fix!");
	    logger("Failed backing up clients.");
	    last;
	}
	
	# test if ssh-connection to server works ok
	my $sshteststr = "ssh -o PasswordAuthentication=no " .
	    "$config->{server_user}" . "@" . 
		"$config->{server_address} 'echo -n 1'";
	if (`$sshteststr` ne "1") {
	    logger ("ssh-connection to server $key failed...");
	    logger ("Failed backing up clients.");
	    last;
	}

	# test that rdiff-backup has the same version as here
	$sshteststr = "ssh $config->{server_user}" . "@" . 
		"$config->{server_address} 'rdiff-backup -V'";
	if (`$sshteststr` ne `rdiff-backup -V`) {
	    logger ("rdiff-backup does not have the same version on " . 
		    "this computer and the backup server... please fix!");
	    logger ("Failed backing up clients.");
	    last;
	}
	
	# the server-part of the configuration shall be ok, so
	# build server-part of execstr and continue
	$execstr_serverpart = 
	    "$config->{server_user}\@$config->{server_address}::";
    }

    # check if destination directory on backup server is represented in
    # configuration file -> return, else add it :)
    if (!exists ($config->{server_destdir})) {
	logger ("Destination directory on the server is not specified " .
		"in the configuration... please fix!");
	logger ("Failed backing up clients.");
	last;
    }
    $execstr_serverpart .= "$config->{server_destdir}/$key";


    # start with the client-handling
    logger ("Starting backup of client $key");

    # check if client not is of type "local" ->
    #  - check if necessary configuration options are present
    #  - check if ssh-connection is ok
    #  - check if rdiff-backup is the same version as here
    if (exists ($config->{client}->{$key}->{type}) and
	$config->{client}->{$key}->{type} ne "local") {

	# check that address is provided
	#FIXME - check that the address is valid
	if (!exists ($config->{client}->{$key}->{address})) {
	    logger ("Address for client $key is not present in " .
		    "configuration... please fix!");
	    logger ("Backup of client $key failed.");
	    next;
	}

	# check that username is provided
	if (!exists ($config->{client}->{$key}->{user})) {
	    logger ("Username for client $key is not present in " .
		    "configuration... please fix!");
	    logger ("Backup of client $key failed");
	    next;
	}

	# test that ssh connection to the client works ok
	my $sshteststr = "ssh -o PasswordAuthentication=no " .
	    "$config->{client}->{$key}->{user}" . "@" . 
		"$config->{client}->{$key}->{address} 'echo -n 1'";
	if (`$sshteststr` ne "1") {
	    logger ("ssh-connection to $key failed...");
	    logger ("Failed backing up client $key.");
	    next;
	}
	
	# test that rdiff-backup on the client is the same version as here
	$sshteststr = "ssh $config->{client}->{$key}->{user}" . "@" . 
	    "$config->{client}->{$key}->{address} 'rdiff-backup -V'";
	if (`$sshteststr` ne `rdiff-backup -V`) {
	    logger ("rdiff-backup does not have the same version on this " .
		    "computer and the client $key... please fix!");
	    logger ("Failed backing up client $key.");
	    next;
	}

	# client configuration shall be ok, so we continue:
	# add client address in the client-part of execstr
	$execstr_clientpart .= 
	    "$config->{client}->{$key}->{user}\@" .
	    "$config->{client}->{$key}->{address}::";
    }
    
    # add the common part of the client execstring
    # (specify '/' as the location)
    $execstr_clientpart .= "/";

    # build execute string
    my $execstr = "rdiff-backup --print-statistics ";

    # include clients locations if exists
    if (!exists ($config->{client}->{$key}->{location})) {
	logger ("Locations for client $key is not present in " .
		"configuration... please fix!");
	logger ("No files from client $key will be backed up.");
	next;
    } elsif (ref ($config->{client}->{$key}->{location}) eq "ARRAY") {
	# there are more than one location => location is an array
	for my $loc (@{$config->{client}->{$key}->{location}}) {
	    $execstr .= "--include $loc ";
	}
    } else {
	# there is only one location => location is a string
	my $loc = $config->{client}->{$key}->{location};
	$execstr .= "--include $loc ";
    }

    # exclude everything else
    $execstr .= "--exclude '/*' ";
    
    # include client-part and server-part
    $execstr .= "$execstr_clientpart $execstr_serverpart";

    # before backing up, remove old backups
    my $client_keep;
    if (($client_keep = $config->{client}->{$key}->{keep}) and 
	($client_keep gt 0)) {
	my $removestr = "rdiff-backup --force --remove-older-than ";
	$removestr .= "$client_keep" . "D ";
	my $server_type = $config->{server_type};
	my $server_destdir = $config->{server_destdir};
	my $server_address = $config->{server_address};
	my $server_user = $config->{server_user};

	if ($server_type eq "extern") {
	    $removestr .= "$server_user" . "@" . "$server_address" . "::";
	}
	if (grep (/\/$/, $server_destdir)) {
	    $removestr .= "$server_destdir";
	} else {
	    $removestr .= "$server_destdir" . "/";
	}
	$removestr .= "$key";

	# remove backups older than $client_keep
	#FIXME - check if there are backups there...
	logger ("Trying to remove backups older than $client_keep days:");
	my $output .= `$removestr 2>&1`;
	logger ("$output");
    
	# 0 mean success -> invert it
	my $retval = ! $?; 

	# log
	if ($retval) {
	    logger ("Removing backups older than $client_keep days sccesseded!");
	} else {
	    logger ("Failed removing backups older than $client_keep.");
	}
    }    

    # run rdiff-backup for client $key
    my $output .= `$execstr 2>&1`;
    logger ("\n$output");
    
    # 0 mean success -> invert it
    my $retval = ! $?; 

    # log
    if ($retval) {
	logger ("Successfully finished backing up client $key");
    } else {
	logger ("Failed backing up client $key");
    }
}

logger ("Finished slbackup.");
close (LOG);


sub logger {
    my ($comment) = @_;
    my $now = strftime "%b %d %H:%M:%S", localtime;
    printflush LOG ("$now - $comment\n");
}



1;

