#!/usr/bin/perl
#
# Copyright (c) 2006 Zmanda Inc.  All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
#
# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120
# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
#

use strict;
use warnings;
use Getopt::Long;
use lib '/usr/lib/mysql-zrm';
use ZRM::SnapshotCommon;


$SIG{'TERM'} = sub { &printAndDie("TERM signal"); };

my $ZFS      = "/usr/sbin/zfs";
my $fileSystemName;
my $snapName;

# Uses zfs list to check if file system name and snap names are valid. 
# $_[0] directory name
# $_[1] snapshot name
sub getSnapshotDeviceDetails()
{
        my $fileSystemName = $_[0];
        #Check if given directory is valid      
        my @ret = `/bin/df $_[0]`;
        if( $? != 0 ) {
                &printAndDie( "Failed to find database : $fileSystemName");
        }
	chomp @ret;
	@ret = split /:/, $ret[0];
	
	my $mntPoint = "undefined";
	my $dev = "undefined";
	if( $ret[0] =~ /(\S*)(\s*)(\()(\S*)(\s*)(\))$/ ){
        	$mntPoint = $1;
        	$dev = $4;
	}
        if(($mntPoint =~ /undefined/) || ($dev =~ /undefined/)) {

         	&printAndDie( "Failed to find mount point for database : $fileSystemName");

        }


	my $snapshotName = '/'.$dev."@".$_[1];
	#ZFS snapshot mountpoint will be in <directry>/.zfs/snapshot/<snapshotname> format
        my $snapDevName = "$mntPoint/.zfs/snapshot/$_[1]"; 

        @ret = `sudo $ZFS list $dev 2>&1`;
        if( $? == 0 ) {
		print "device=$dev\n";
		print "snapshot-device=$snapshotName\n";
		print "device-mount-point=$mntPoint\n";
		print "filesystem-type=ZFS\n";
		my $str = &getCommonDetails( $_[0], $_[1], $mntPoint );
                my @s = split /\n/, $str;
                print "$s[1]\n";
                print "snapshot-mount-point=$snapDevName\n";
	}else {

         	&printAndDie( "Failed to get ZFS list info for $dev, may not be on ZFS file system");

	}
}

sub doGetSnapshotdeviceDetails()
{
	if( !defined $opt{"directory"} ){
		&printAndDie( "Please supply --directory" );
	} 
	if( !defined  $opt{"sname"} ) {
		&printAndDie( "Please supply --sname" );
	}
	&getSnapshotDeviceDetails( $opt{"directory"}, $opt{"sname"} );
}


sub doCreateSnapshot()
{
	if( !defined $opt{"dev"} ){
		&printAndDie( "Please input --dev" );
	}
	if( !defined $opt{"sname"} ){
		&printAndDie( "Please input --sname" );
	}
        #opt{"dev"}     -->  /mountPoint/fileSystemName
        #opt{"sname"}   -->  snapshot name 

        my $snapName = $opt{"sname"};
	my @a = split /@/, $snapName;
        $snapName = $a[1];
        $fileSystemName  = $opt{"dev"};

        # Remove the leading "/" from the volume name.

        if ( $fileSystemName =~ /^\// ) {
                $fileSystemName = $';        
        }

        # command syntax : zfs snapshot <FSNAME>@<SNAPNAME>
	# example : zfs snapshot testpool/testfs@snap1
        my $sname = $fileSystemName."@".$snapName;
	my $result = `sudo $ZFS snapshot $sname 2>&1`;
        if ($? != 0 ) {
		&printAndDie("Failed to create ZFS snapshot for $fileSystemName,$result");
	} 
}

sub doMount()
{
	#No need to implement Mount and un mount for ZFS, After snapshot creation 
	#snapshot data is available as readonly. 

	return;

}

sub doUmount()
{
	#No need to implement Mount and un mount for ZFS, After snapshot creation 
	#snapshot data is available as readonly. 

      	return;

}


# To remove the snapshot from the system, we need to supply the filesystem name
# along with snapshot name.
# $_[0] will have snapshot name : opt{"dev"} 
# opt{"dev"} should have snapshot name  in the format <fileSystemName@snapName>
sub doRemoveSnapshot()
{
	if( !defined $opt{"dev"} ){
		&printAndDie( "Please input --dev" );
	}
 
        my $fileSystemName = $opt{"dev"};        

        #remove leading "/" if contains in the input.
        if ( $fileSystemName =~ /^\// ) {
                $fileSystemName = $';        
        }

	my $result = `sudo $ZFS destroy $fileSystemName 2>&1`;
        if ($? != 0 ) {
		&printAndDie("Failed to remove ZFS snapshot $fileSystemName,$result");
	} 
}

&initSnapshotPlugin();

if( $action eq "get-vm-device-details" ){
	&doGetSnapshotdeviceDetails();
}elsif( $action eq "create-snapshot" ){
	&doCreateSnapshot();
}elsif( $action eq "mount" ){
	&doMount();
}elsif( $action eq "umount" ){
	&doUmount();
}elsif( $action eq "remove-snapshot" ){
	&doRemoveSnapshot();
}
exit( 0 );
