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();
阅读(1593) | 评论(0) | 转发(0) |