# snpashotautomation.pl # # by Vijayababu Dandi # Version 1.0 # October 24, 2008 ############################################################################################## # Perl must be installed and running on the Linux server where this utility will be used. # NSS must be installed to get the VFS support. # (The SDK for this API set can be downloaded from http://developer.novell.com/wiki/index.php/# Virtual_File_Services_for_NetWare.) ############################################################################################## # # This is used to take snapshot on particular pool in regular intervals.. # ############################################################################################## use warnings; use integer; my %opts; use Getopt::Long qw(:config no_ignore_case bundling); my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); my @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun); use IO::File; my $snap_log_fh = new IO::File; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst); if ( ! -e "/tmp/snap_logs" ) { `touch /tmp/snap_logs`; } sub Usage(;$) { my $err = 0; if (@_) { my $warning = shift; print {*STDERR} "$warning\n" if $warning; $err = 1; } print {$err ? *STDERR : *STDOUT} < -s -D -P -n -N Options: -h | --help -t | --time Periodicity of snapshots( In seconds ) -s | --size Size to allocate for pool snapshot (in MB) -D | --device Device on which the partition need to be created (Eg : sda,sdb..) -n | --name Name of the pool snapshot ( Dont put any special characters ) -N | --noofsnapshots Maximum number of snapshots ( 15 snapshots on OES 2 Linux on any given stored-on partition ) -P | --pool Pool Name ( on which pool needs to take snapshot eg: POOL1, POOL2 ...) EOF exit($err); } sub ParseOpts { my $time; eval { GetOptions("t|time=s" => \$opts{'time'}, "h|help" => \$opts{'help'}, "s|size=s" => \$opts{'size'}, "D|device=s" => \$opts{'device'}, "P|pool=s" => \$opts{'pool'}, "n|name=s" => \$opts{'name'}, "N|noofsnapshots=s" => \$opts{'noofsnapshots'}) or Usage(''); }; Usage("Couldn't parse options: $@\n") if $@; Usage if $opts{'help'}; while(1) { my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); my $year = 1900 + $yearOffset; my $theTime = $hour*60+$minute; $theTime = abs $theTime; sleep($opts{'time'}); my @pools = ListSnapshots(); if ( $#pools >= $opts{'noofsnapshots'} ) { print "No of Snapshots : $#pools\n";; foreach my $v (@pools) { $v =~ m/(\d+)/; my $time1 = $1; my $c =-1; foreach my $x (@pools) { $x =~ m/(\d+)/; my $time2 = $1; if ($time1 <= $time2 ) { $c++; if ($c == $#pools) { # print "Lowest value is $c : $v\n"; DeleteSnapshot($v); } } } } } AddSnapshot("$opts{'pool'}","$opts{'device'}","$opts{'size'}","$opts{'name'}$theTime"); } #while(1) #{ #} } # AddSnapshot("$opts{'pool'}","$opts{'device'}","$opts{'size'}","$opts{'name'}"); sub SetDataStream($*) { my $fh = $_[0]; my $datastream = $_[1]; my $command; my $result; my $error; $command = ""; seek $fh, 0, 0; if (!syswrite($fh, $command, length($command))) { $result .= "Unable to send datastream command to NDS management. "; seek $fh, 0, 0; if (sysread($fh,$error, 1000)) { $result .= $error; } $result .= "\n"; } return $result; } sub WriteCommand($*) { my $fh = $_[0]; my $result; my $reply; my $error; my $command = $_[1]; #print("command=$command\n"); seek $fh, 0, 0; if (!syswrite($fh, $command, length($command))) { $result .= "Unable to send command to virtual file. "; seek $fh, 0, 0; if (sysread($fh, $error, 1000)) { $result .= $error; } $result .= "\n"; } else { seek $fh, 0, 0; my $readLen = 999; while ($readLen) { $readLen = sysread($fh, $reply, 1000); $result .= $reply; } } #print("result=$result\n"); return $result; } sub AddSnapshot($$$$) { my $poolName = $_[0]; my $partitionID = $_[1]; my $size = "2048*$_[2]"; my $snapName = $_[3]; my $result = ""; my $ret =""; my $nssResult; #print "Creating snapshot with name $snapName\n"; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); open($snap_log_fh, '>>',"/tmp/snap_logs"); printf $snap_log_fh "%02d-%02d-%4d %02d:%02d:%02d %s\n",$mday,$mon+1,$year+1900,$hour,$min,$sec,"Creating snapshot with name $snapName"; open(FILE,'+>', "/_admin/Manage_NSS/manage.cmd") or die "Error opening NSS management file ($!) on server"; my $command = "/dev/evms/$poolName". "$partitionID". "$size". "$snapName"; $command = "$command"; if (!($ret = SetDataStream(FILE, "command"))) { #$result .= $ret; $nssResult = WriteCommand(FILE,"$command"); } print errorHandle($nssResult,$snapName); printf $snap_log_fh errorHandle($nssResult,$snapName); #return $nssResult; } sub errorHandle($$) { my $xml = $_[0]; my $snapName = $_[1]; my $result; my @xml; my $ret; my $state; my $size; my $mount; my $name = ""; my $description; my $reporter = ""; if (@xml = $xml =~ /(.*?)<\/addPoolSnapshot>/gs) { foreach $result (@xml) { if ($result =~ /(.*?)<\/description>/gs) { $description = $1; } if ($result =~ /(.*?)<\/reporter>/gs) { $reporter = $1; } if ($result =~ //s) { if ($1 != 0) { return "----------------------------------------\n". "Error No :$1 \n". "Description :$description \n". "Reporter :$reporter \n". "----------------------------------------\n"; } else { return "----------------------------------------------\n". "pool snapshot $snapName Successfully Created\n". "---------------------------------------------\n"; } } } } if (@xml = $xml =~ /(.*?)<\/removePoolSnapshot>/gs) { foreach $result (@xml) { if ($result =~ /(.*?)<\/description>/gs) { $description = $1; } if ($result =~ /(.*?)<\/reporter>/gs) { $reporter = $1; } if ($result =~ //s) { if ($1 != 0) { return "----------------------------------------\n". "Error No :$1 \n". "Description :$description \n". "Reporter :$reporter \n". "----------------------------------------\n"; } else { return "---------------------------------------------\n". "pool snapshot $snapName Successfully Deleted\n". "--------------------------------------------\n"; } } } } } sub ListSnapshots { #my $command = $_[0]; #my $showdetails = $_[1]; my $result; my @poolss = (); my $ret; my $nssResult; #my $server = $_[0]; #$command = "$command"; open(FILE,'+>', "/_admin/Manage_NSS/manage.cmd") or die "Error opening NSS management file ($!) on server"; my $command = ""; if (!($ret = SetDataStream(FILE, "command"))) { #$result .= $ret; $nssResult = WriteCommand(FILE,"$command"); } @poolss = parseResult ($nssResult); return @poolss; } sub parseResult($) { my $xml = $_[0]; #my $showdetails = $_[1]; my $result; my @xml; my $ret; my $state; my $size; my $mount; my $name = ""; my $poolName = ""; my @poolss = (); my $numpools = -1; #print "ndsResult xml= $xml\n"; @xml = $xml =~ /(.*?)<\/poolSnapshotInfo>/gs; foreach $result (@xml) { if ($result =~ //s) { if ($1 != 0) { return "Error $1 getting Snapshot Info\n"; } } if ($result =~ /(.*?)<\/snapName>/s) { $name = $1; $poolss[++$numpools] = $name; } } return @poolss; } sub DeleteSnapshot($) { my $snapName = $_[0]; my $result; my $ret; my $nssResult; #my $server = $_[0]; print "Deleting snpashot $snapName.........\n"; my $command = "$snapName". ""; $command = "$command"; open(FILE,'+>', "/_admin/Manage_NSS/manage.cmd") or die "Error opening NSS management file ($!) on server"; if (!($ret = SetDataStream(FILE, "command"))) { #$result .= $ret; $nssResult = WriteCommand(FILE,"$command"); } print errorHandle($nssResult,$snapName); #return $nssResult; } ParseOpts();