Chinaunix首页 | 论坛 | 博客
  • 博客访问: 247524
  • 博文数量: 44
  • 博客积分: 1795
  • 博客等级: 上尉
  • 技术积分: 465
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-04 12:02
文章分类

全部博文(44)

文章存档

2015年(1)

2011年(1)

2009年(7)

2008年(2)

2007年(7)

2006年(26)

我的朋友

分类:

2007-11-19 14:30:50

use File::Basename;
use Getopt::Std;
use Getopt::Long;
use Term::ANSIColor;
use Time::localtime;
use POSIX qw(strftime);
use Expect;

$USER = "root";
$PASSWORD = "password";
$BACKUP_DST_DIR = "/bang"; #it should be the absolute directory.
$OLDSPVOL = "";
$NEWSPVOL = "";
$ORGVOL = "";
$OLDSPSIZE = "";
$NEWSPSIZE = "";
$SNAPSHOTNAME = "";
$SERVER_URL = "";
$SPPERCENT = "20.00";
$SIZEPERCENT = 2;
$FILESYSCMD = "mke2fs ";

sub check_env
{
    my $cmd = "which lvm";
    my ($result, $lvmPath) = exec_cmd($cmd);
    if (0 != $result)
    {
        warn2sum("Could not find lvm, please check whether lvm is installed or not manually\n");
        exit 1;   
    }
}

sub warn2sum
{
    my @params;
    push(@params, "WARNING:");
    foreach (@_) { push @params, $_; }
    print color("yellow"), "@params", color("reset");           # to screen
}

sub fail2sum
{
    my @params;
    push(@params, "FAILED: ");
    foreach (@_) { push @params, $_; }
    print color("red"), "@params", color("reset");           # to screen
}

sub succ2sum
{
    my @params;
    push(@params, "PASSED: ");
    foreach (@_) { push @params, $_; }
    print color("green"), "@params", color("reset");           # to screen
}

sub get_cmd_output
{
    my ($full_cmd) = @_;
    my $output = "./output.tmp";
    my $result = 256;
    $result = system("$full_cmd > $output");
   
    my @Temp = "";
    if (0 == $result)
    {
        open LINES, "$output" or die "Could not open file $output";
        while()
        {
            $_ =~ s/\s*$//;
            push(@Temp, $_);
        }
        close LINES;

        $result = system("rm -f $output");
    }

    return ($result, \@Temp);
}

sub exec_cmd
{
    my ($cmd) = @_;

    my @ops = "";
    print("full cmd is $cmd \n");
    my ($result, $output) = get_cmd_output($cmd);

    foreach my $op (@$output)
    {
        push(@ops, $op);
    }

    return ($result, \@ops);
}

sub exec_auto
{

}

sub create_pv
{
    my ($dev) = @_;
    my $cmd .= "pvcreate ";

    if ("" eq $dev)
    {
        fail2sum("Invalid device parameter, device should not be null\n");
        exit 1;
    }

    $cmd .= $dev;
    my ($result, $output) = exec_cmd($cmd);
}

sub create_vg
{
    my ($dev, $volGroup) = @_;
    my $cmd = "vgcreate ";

    if ("" eq $volGroup)
    {
        fail2sum("Invalid name parameter, volume group name should not be null\n");
        exit 1;
    }
    if ("" eq $dev)
    {
        fail2sum("Invalid device parameter, device should not be null\n");
        exit 1;
    }
    
    $cmd .= "$volGroup". " " . "$dev";
    my ($result, $output) = exec_cmd($cmd);
}

sub create_lv
{
    my ($orgVol, $volGroup, $size) = @_;
    my $cmd .= "lvcreate ";
    if ("" eq $orgVol)
    {
        fail2sum("Invalid name parameter, logical volume name should not be null\n");
        exit 1;
    }
    if ("" eq $volGroup)
    {
        fail2sum("Invalid name parameter, volume group name should not be null\n");
        exit 1;
    }
    if ("" eq $size)
    {
        fail2sum("Invalid size parameter, the size of logical volume should not be null\n");
        exit 1;
    }

    $cmd .= "-L " . $size . " " . "-n " . $orgVol . " " . $volGroup;
    my ($result, $output) = exec_cmd($cmd);
}

sub mount_volume
{
    my ($vgName, $volName) = @_;

    my $srcVolABDir = "/dev/$vgName/$volName";
    my $dstVolABDir = "/mnt/$volName";
    my $cmd = "";
    my $result = "";

    if (-e $srcVolABDir)
    {
        if (!(-e $dstVolABDir))
        {
            $cmd .= "mkdir $dstVolABDir";
            exec_cmd($cmd);
        }
        $cmd = "$FILESYSCMD /dev/$vgName/$volName";
        exec_cmd($cmd);
        $cmd = "mount $srcVolABDir $dstVolABDir";
        exec_cmd($cmd);
        $result = $dstVolABDir;
    }
    else
    {
        fail2sum("mount volume $volName, $srcVolABDir not exists\n");
    }

    return $result;
}

sub unmount_volume
{
    my ($volName) = @_;
    my $dstVolABDir = "/mnt/$volName";
    my $cmd = "";

    if (-e $dstVolABDir)
    {
        $cmd .= "umount $dstVolABDir";
        exec_cmd($cmd);
    }
}

sub create_sp
{
    my ($volGroup, $orgVol, $snapshot, $size, $location, $first) = @_;
    my $cmd .= "lvcreate ";
    if ("" eq $size)
    {
        fail2sum("Invalid size parameter, the size of snapshot volume should not be null\n");
        exit 1;
    }
    elsif ("" eq $snapshot)
    {
        fail2sum("Invalid snapshot name parameter, snapshot volume name should not be null\n");
        exit 1;
    }
    elsif ("" eq $orgVol)
    {
        fail2sum("Invalid logical volume name parameter, the name of original logical volume of snapshot $snapshot should not be null\n");
        exit 1;
    }
    elsif ("" eq $volGroup)
    {
        fail2sum("Invalid volume group name parameter, volume group name should not be null\n");
        exit 1;
    }

    $cmd .= "--size " . $size . " --snapshot --name " . $snapshot . " " . "/dev/$volGroup/$orgVol";
    my ($result, $output) = exec_cmd($cmd);
    if ($first)
    {
        mount_volume($volGroup, $orgVol);
    }

    my $dir = mount_volume($volGroup, $snapshot);
    
    my ($result, $output) = backup_action($dir, $location);
    interval_backup($snapshot, $location);
}

sub create_action
{
    my ($dev, $orgVol, $snapshot, $size, $type, $volGroup, $location) = @_;
    my $invalidPara = 0;

    if ("" eq $type)
    {
        fail2sum("invalid type parameter, type should not be null\n");
        usage();
    }
    else
    {
        if ("pv" eq $type)
        {
            create_pv($dev);
        }
        elsif ("vg" eq $type)
        {
            create_vg($dev, $volGroup);
        }
        elsif ("lv" eq $type)
        {
            create_lv($orgVol, $volGroup, $size);
        }
        elsif ("sp" eq $type)
        {
            create_sp($volGroup, $orgVol, $snapshot, $size, $location, 1);
        }
        else
        {
            fail2sum("Invalid type parameter, we could not support to create $type\n");
            usage();
        }
    }
}

sub query_action
{
    my ($type, $name) = @_;
    my $cmd = "";
    my $des = "";
    if ("" eq $type)
    {
        print("------------------------------");
        print("All physical volumes ");
        print("------------------------------\n");
        $cmd = "pvdisplay";
        my ($result, $output) = exec_cmd($cmd);
        foreach my $op (@$output) { print("$op\n"); }
        print("---------------------------------------------------------------------------------\n\n");
        print("------------------------------");
        print("All volume groups    ");
        print("------------------------------\n");
        $cmd = "vgdisplay";
        exec_cmd($cmd);
        foreach my $op (@$output) { print("$op\n"); }
        print("---------------------------------------------------------------------------------\n\n");
        print("------------------------------");
        print("All logical volumes  ");
        print("------------------------------\n");
        $cmd = "lvdisplay";
        exec_cmd($cmd);
        foreach my $op (@$output) { print("$op\n"); }
        print("---------------------------------------------------------------------------------\n\n");
    }
    else
    {
        if ("pv" eq $type)
        {
            $cmd = "pvdisplay";
            $des ="All physical volumes ";
        }
        elsif ("vg" eq $type)
        {
            $cmd = "vgdisplay";
            $des = "All volume groups   ";
        }
        elsif ("lv" eq $type)
        {
            $cmd = "lvdisplay";
            $des = "All logical volumes ";
        }
        elsif ("sp" eq $type)
        {
            if ("" eq $snapshot)
            {
                $cmd = "lvdisplay";
                $des = "All logical volumes ";
            }
            else
            {
                $cmd = "lvdisplay -v $snapshot";
                $des = "snapshot volume view";
            }
        }
        else
        {
            print("Could not support this type $type\n");
            usage();
        }
        print("------------------------------");
        print($des);
        print("------------------------------\n");
        my ($result, $output) = exec_cmd($cmd);
        foreach my $op (@$output) { print("$op\n"); }
        print("---------------------------------------------------------------------------------\n\n");
    }
}

sub delete_snapshot
{
    my ($volGroup, $spName) = @_;
    my $cmd = "lvremove -f /dev/$volGroup/$spName";
    exec_cmd($cmd);
}

sub scp_file
{
    my ($file, $server_url) = @_;

    my $timeout = 300;
    my $command = "/usr/bin/scp";
    my @parms = ($file, "root\@$server_url");

    my $exp = Expect->spawn($command, @parms);
    $exp->expect($timeout,
        [
        "[Pp]assword:" =>
        sub {
            my $exp = shift;
            $exp->send("password\n"); #send password;
        }
        ]
    );

    $exp->soft_close();
}

sub interval_backup
{
    my ($oldsp, $location) = @_;

    while(1)
    {
        my ($itsTime, $volGroup, $spsize, $orgVol) = time_to_create_snapshot($oldsp);
        my ($iSize, $fSize) = split(/\./, $spsize);
        my $newSize = $iSize * $SIZEPERCENT;
        $newSize = $newSize + ($fSize * $SIZEPERCENT) / 100;
        $newSize = "$newSize"."g";
        if (1 == $itsTime)
        {
            unmount_volume($oldsp);
            delete_snapshot($volGroup, $oldsp);
            create_sp($volGroup, $orgVol, $oldsp, $newSize, $location, 0);
        }
        else
        {
            sleep(10);
        }
    }
}

sub backup_action
{
    my ($dev, $location) = @_;
    my $cmd = "";
    my $invalidPara = 0;
    
    if ("" eq $dev)
    {
        fail2sum("Invalid device parameter, Device should not be null\n");
        $invalidPara = 1;
    }
    elsif ("" eq $location)
    {
        fail2sum("Invalid remote url parameter, it should not be null\n");
        $invalidPara = 1;
    }

    if ($invalidPara)
    {
        usage();
    }
    else
    {
        my $time_str = get_date_str();
        my $file = "snap_$time_str.tar.gz";
        $cmd = "tar zcvf $file" . " $dev";
        exec_cmd($cmd);
        scp_file($file, $location);
        $cmd = "rm -rf $file";
        exec_cmd($cmd);
    }
}

sub get_date
{
    my $timeStr;
    my $tm = localtime();
    $timeStr = strftime("%Y-%m-%d.%H:%M:%S",
        $tm->sec(), $tm->min(), $tm->hour(),
        $tm->mday(), $tm->mon(), $tm->year()
    );

    return $timeStr;
}

sub get_date_str
{
    my $timeStr;
    my $tm = localtime();
    $timeStr = strftime("%Y_%m_%d_%H_%M_%S",
            $tm->sec(), $tm->min(), $tm->hour(),
            $tm->mday(), $tm->mon(), $tm->year()
            );

    return $timeStr;
}

sub split_date
{
    my ($timeStr) = @_;
    my ($y_m_d, $h_m_s) = split(/\./, $timeStr);
    my ($year, $mon, $day) = split(/-/, $y_m_d);
    my ($hour, $min, $second) = split(/:/, $h_m_s);

    return ($year, $mon, $day, $hour, $min, $second);
}

sub check_date
{
   my ($timeStr) = @_;
   my ($year, $mon, $day, $hour, $min, $second) = split_date($time);
   my $isValid = 0;

   if ( ("" eq $year) || ("" eq $mon) || ("" eq $day) ||
        ("" eq $hour) || ("" eq $min) || ("" eq $second) )
   {
       $isValid = 1;
   }

   return $isValid;
}

sub compare_date
{
    my ($time1, $time2) = @_;
    my $isEqual = 0;

    my ($year1, $mon1, $day1, $hour1, $min1, $second1) = split_date($time1);
    my ($year2, $mon2, $day2, $hour2, $min2, $second2) = split_date($time2);
    if ( ($year1 == $year2) && ($mon1 == $mon2) && ($day1 == $day2) &&
         ($hour1 == $hour2) && ($min1 == $min2) ) #&& ($second1 == $second2) )
    {
       $isEqual = 1;
    }

    return $isEqual;
}

sub time_to_create_snapshot
{
    my ($oldsp) = @_;
    my $cmd = "lvs";
    my ($result, $output) = exec_cmd($cmd);
    my $spSize = 0;
    my $orgVol = "";
    my $itsTime = 0;
    my $volGroup = "";

    foreach my $op (@$output)
    {
        if ($op =~ /$oldsp/)
        {
            print("$op\n");
            my ($tmp1, $tmp2, $vg, $tmp4, $spsize, $orgvol, $sppercent) = split(/ +/, $op);
            $volGroup = $vg;
            $spsize =~ tr/G//d;
            $spSize = $spsize;
            $orgVol = $orgvol;
            if ($sppercent >= $SPPERCENT)
            {
                $itsTime = 1;
            }
            else
            {
                $itsTime = 0;
            }
        }
    }

     return ($itsTime, $volGroup, $spSize, $orgVol);
}

sub backup_timer
{
    my ($dev, $location, $orgVol, $time_str) = @_;
    my ($isValid) = check_date($time_str);
    my $curr_time = get_date();
    if (0 == $isValid)
    {
        fail2sum("Invalid time string format, please input the time string likes $curr_time\n");
    }
    
    my $isTrue = 1;

    while(1 == $isTrue)
    {
        if (compare_date($time_str, $curr_time))
        {
            $isTure = 0;
            backup_action($dev, $location);
            last;
        }
        else
        {
            sleep(10);
        }
        $curr_time = get_date();
    }
}

sub merge_vg
{
    my ($vg) = @_;
    my ($vg1, $vg2) = split(/,/, $vg);
    if ( ("" eq $vg1) || ("" eq $vg2) )
    {
        fail2sum("Two volume group must be given\n");
        usage();
        exit 1;
    }
    my $cmd = "vgmerge $vg1 $vg2";
    my ($result, $output) = exec_cmd($cmd);
    foreach my $op (@$output)
    {
        print("$op\n");
    }
}

sub extend_lv
{
    my ($vg, $lv, $size) = @_;
    if ("" eq $vg)
    {
        fail2sum("Volume group name must be given, which used to locate the logical volume\n");
        usage();
    }
    if ("" eq $lv)
    {
        fail2sum("Logical volume name must be given\n");
    }
    if ("" eq $size)
    {
        fail2sum("Size could not be NULL\n");
    }
    
    my $cmd = "lvextend -L+$size /dev/$vg/$lv";
    my ($result, $output) = exec_cmd($cmd);
    foreach my $op (@$output)
    {
        print("$op\n");
    }
}

sub reduce_lv
{
    my ($vg, $lv, $size) = @_;
    if ("" eq $vg)
    {
        fail2sum("Volume group name must be given, which used to locate the logical volume\n");
        usage();
    }
    if ("" eq $lv)
    {
        fail2sum("Logical volume name must be given\n");
    }
    if ("" eq $size)
    {
        fail2sum("Size could not be NULL\n");
    }
    
    my $cmd = "lvreduce -L-$size /dev/$vg/$lv";
    my ($result, $output) = exec_cmd($cmd);
    foreach my $op (@$output)
    {
        print("$op\n");
    }
}

sub do_action
{
    my ($action, $dev, $location, $orgVol, $snapshot, $size, $type, $volGroup, $time_str) = @_;
    if ("create" eq $action)
    {
        create_action($dev, $orgVol, $snapshot, $size, $type, $volGroup, $location);
    }
    elsif ("show" eq $action)
    {
        query_action($type, $snapshot);
    }
    elsif ("backup" eq $action)
    {
        if ("" eq $time_str)
        {
            backup_action($dev, $location);
        }
        else
        {
            backup_timer($dev, $location, $orgVol, $time_str);
        }
    }
    elsif ("merge" eq $action)
    {
        merge_vg($volGroup);
    }
    elsif ("extend" eq $action)
    {
        extend_lv($volGroup, $orgVol, $size);
    }
    elsif ("reduce" eq $action)
    {
        reduce_lv($volGroup, $orgVol, $size);
    }
    else
    {
        print("Could not support this action, please see the help\n");
        usage();
    }
}

sub usage
{
    print("------------------------");
    print("Remote back the snapshot");
    print("------------------------\n");
    print("create --type|-t[pv,vg,lv,sp] --device|-d[device] --, example, /dev/sdb\n");
    print("1 Examples for creating:\n\n");
    print("1.1 Creating physical volume:\n");
    print("perl back_snapshot.pl -a create -t pv -d /dev/sdb\n\n");
    print("1.2 Creating volume group:\n");
    print("perl back_snapshot.pl -a create -t vg -v volgroup -d /dev/sdb\n\n");
    print("1.3 Creating logical volume:\n");
    print("perl back_snapshot.pl -a create -t lv -v volgroup -o orgvolume -s 10G\n\n");
    print("1.4 Creating snapshot:\n");
    print("perl back_snapshot.pl -a create -t sp -p spvolume -o orgvolume -v volgroup -s 2g -l 192.168.252.165:/bang\n\n");

    print("2 Examples for showing:\n\n");
    print("2.1 All devices show:\n");
    print("perl back_snapshot.pl -a show\n\n");
    print("2.2 Physical Volume show:\n");
    print("perl back_snapshot.pl -a show -t pv\n\n");
    print("2.3 Volume Group show:\n");
    print("perl back_snapshot.pl -a show -t vg\n\n");
    print("2.4 Logical Volume show:\n");
    print("perl back_snapshot.pl -a show -t lv\n\n");
    print("2.5 Snapshot show:\n");
    print("perl back_snapshot.pl -a show -t sp\n\n");

    print("3 Merge volume groups example:\n");
    print("perl back_snapshot.pl -a merge -v vg1,vg2\n\n");

    print("4 Extend logical volume size example:\n");
    print("perl back_snapshot.pl -a extend -v volgroup -o orgvolume -s 1g\n\n");

    print("5 Reduce logical volume size example:\n");
    print("perl back_snapshot.pl -a reduce -v volgroup -o orgvolume -s 1g\n\n");
    exit 0;
}

sub test
{
    my $itsTime = time_to_create_snapshot("snapvolume");
}

sub main
{
    my $COMMAND_LINE = "$0";
    foreach my $arg(@ARGV) {
        $COMMAND_LINE .= " " . $arg;
    }
    $PROGRAM = basename($0, ".pl");

    my $action = "";
    my $dev = "";
    my $location = "";
    my $orgVol = "";
    my $snapshot = "";
    my $size = "";
    my $type = "";
    my $volGroup = "";

    my $time_str = "";

    GetOptions
    (
        'action|a=s'         => \$action,
        'device|d=s'         => \$dev,
        'help|h'             => sub { usage(); },
        'location|l=s'       => \$location,
        'timer|m=s'          => \$time_str,
        'orgvol|o=s'         => \$orgVol,
        'snapshot|p=s'         => \$snapshot,
        'size|s=s'           => \$size,
        'type|t=s'           => \$type,
        'volumegroup|v=s'    => \$volGroup,
        'test|e'             => sub { test(); },
    );

    check_env();
    do_action($action, $dev, $location, $orgVol, $snapshot, $size, $type, $volGroup, $time_str);
}

END
{
    print color("reset");
}

exit main;

main();

阅读(1554) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~