#!/usr/bin/perl
use strict;

##########
#
# RawDR script for asynchronous replication via lzop to store snapshot on non-zfs storage (e.g. external USB-drives)
#
# Version: 0.0.7
# License: GPL
# Author: Heiko Schramm
#
# USAGE: "perl rawdr-snap.pl g1/s1 /tmp/cifs INC|FULL|FULLONLY"
#
# PARAMETER 1: SILO
# PARAMETER 2: Destination directory
# PARAMETER 3: INC|FULL|FULLONLY
#              "INC" to get an INC snapshot
#              "FULL" to get an additional full snapshot stream after the INC snapshot, "perl rawdr-snap.pl x y FULL"
#              "FULLONLY" to bypass the incremental snap und only get a FULL snap. (WARNING: THIS WILL BREAK THE PREVIOUS CHAIN)

#############################
########## to be SET ########

#my $rawdr_silo = 'g1/s1';
#my $local_mountpoint = '/tmp/cifs';

my $rawdr_silo = $ARGV[0];
my $local_mountpoint = $ARGV[1];

####### end of settings #####
#############################

if ( ($ARGV[0] eq '') || ($ARGV[1] eq '') || ( $ARGV[2] ne 'INC' && $ARGV[2] ne 'FULL' && $ARGV[2] ne 'FULLONLY' ) ) {
    &error_exit("invalid syntax. See comments within script.");
}



my $command;
my $output;
my $date_string = &date_format();


my $rawdr_silo_joined = $rawdr_silo;
$rawdr_silo_joined =~ s/\///ig;

#mount NFS target
#$command = 'mount -t nfs '.$nfs_target.' '.$local_mountpoint;
#system ($command);

#check for parallel SNAPSHOTS
$command = 'find '.$local_mountpoint.' -name "'.$rawdr_silo_joined.'_*snap-*.LOCK"';
$output = `$command`;
my $parallel_snapshot_exist = 'y';
if ($output eq '') {$parallel_snapshot_exist = 'n';}

#check that a previos snapshot exists
$command = 'zfs list -t snapshot | grep "'.$rawdr_silo.'@autosnap-"';
$output = `$command`;
my @snap_count = split(/\n/,$output);

#check that the target-directory is mounted, there is exactly 1 previous snapshot and there is no parallel snapshot in progress
if ( (-e $local_mountpoint.'/isMounted') && (@snap_count==1) && ($parallel_snapshot_exist eq 'n') ) {
    #

    #determine last snapshot
    my $last_snapshot;
    $command = 'zfs list -t snapshot | grep "'.$rawdr_silo.'@autosnap"';
    $output = `$command`;
    my @t_output_1 = split (/\n/,$output);
    foreach my $tmp (@t_output_1) {
        my @snaps_elements = split (/ /,$tmp);
        $last_snapshot = $snaps_elements[0];
    }

    #print $last_snapshot."\n";

    #create new snapshot
    $command = 'zfs snapshot '.$rawdr_silo.'@'.'autosnap-'.$date_string;
    #print $command."\n";
    $output = `$command`;
    if ($output ne '') {&error_exit('zfs snapshot: '.$output);}

    if ( ($ARGV[2] eq 'FULL') || ($ARGV[2] eq 'INC') ) {
        # fuer FULL und normal wird der inkremntelle Snapshots erstellt
        # create new incremental compressed snapshot stream
        $command = 'zfs send -i '.$last_snapshot.' '.$rawdr_silo.'@autosnap-'.$date_string.' | /usr/local/bin/lzop > '.$local_mountpoint.'/'.$rawdr_silo_joined.'_autosnap-'.$date_string.'.lzop.LOCK';
        #print $command."\n";
        $output = `$command`;
        if ($output ne '') {&error_exit('zfs send: '.$output);}

        # remove LOCK
        $command = 'mv '.$local_mountpoint.'/'.$rawdr_silo_joined.'_autosnap-'.$date_string.'.lzop.LOCK'.' '.$local_mountpoint.'/'.$rawdr_silo_joined.'_autosnap-'.$date_string.'.lzop';
        #print $command."\n";
        $output = `$command`;
        if ($output ne '') {&error_exit('move/unlock: '.$output);}

    }


    if ( ($ARGV[2] eq 'FULL') || ($ARGV[2] eq 'FULLONLY') ) {
        # create a full snapshot stream
        $command = 'zfs send '.$rawdr_silo.'@autosnap-'.$date_string.' | /usr/local/bin/lzop > '.$local_mountpoint.'/'.$rawdr_silo_joined.'_FULL-autosnap-'.$date_string.'.lzop.LOCK';
        $output = `$command`;
        if ($output ne '') {&error_exit('zfs send FULL: '.$output);}

        $command = 'mv '.$local_mountpoint.'/'.$rawdr_silo_joined.'_FULL-autosnap-'.$date_string.'.lzop.LOCK'.' '.$local_mountpoint.'/'.$rawdr_silo_joined.'_FULL-autosnap-'.$date_string.'.lzop';
        #print $command."\n";
        $output = `$command`;
        if ($output ne '') {&error_exit('move/unlock FULL: '.$output);}

    }
    
    #delete the previous snapshot if the snapshot was created succesfully
    if (-e $local_mountpoint.'/'.$rawdr_silo_joined.'_autosnap-'.$date_string.'.lzop') {
	$command = 'zfs destroy '.$last_snapshot;
	#print $command."\n";
	$output = `$command`;
	if ($output ne '') {&error_exit('zfs snapshot: '.$output);}
    }

    # umount nfs target dir
    #$command = 'umount '.$local_mountpoint;
    #system ($command);
} else {
    &error_exit("Please check, that source and destination exists,  there is no concurrent snapshot in progress and there is exactly 1 previos snapshot existing");
}


sub error_exit() {
    # TO BE DONE (tbd)
    # further error handling, e.g. removal of temporary lock files or snapshots that were not transmitted


    #$command = 'umount '.$local_mountpoint;
    #system ($command);
    print 'ERROR: '.$_[0]."\n";
    die;
}


sub date_format
{
    my @months = qw(01 02 03 04 05 06 07 08 09 10 11 12);
    my @days = qw(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag);
    my $ss;
    my $mm;
    my $hh;
    my $dd;
    my $month;
    my $yy;
    my $yyyy;
    my $wday;

    ($ss,$mm,$hh,$dd,$month,$yy,$wday) = localtime(time);
    $wday = @days[$wday];
    $month = @months[$month];
    $yyyy = $yy + 1900;
    if ($ss<10)
    {$ss = "0$ss";}
    if($mm<10)
    {$mm = "0$mm";}
    if($hh<10)
    {$hh = "0$hh";}
    if($dd<10)
    {$dd = "0$dd";}
    #my $ret_string = $dd.'.'.$month.'.'.$yyyy.' '.$hh.':'.$mm.':00';
    my $ret_string = $yyyy.$month.$dd.'-'.$hh.$mm;
    return $ret_string;
}


