May 18, 2012

Refreshing Test Dev SQL Environments using NetApp Technologies

Putting it all together, here’s the entire code in one segment.

#!/usr/bin/perl
#===============================================================#
#
# $ID$
#
# RefreshSQL.pl	
#
# Copyright 2010, Rajeev Karamchedu, Ltd. All rights reserved. 
#
# This work is licensed under the Creative Commons 
# Attribution-Noncommercial-Share Alike 3.0 United States License. 
# To view a copy of this license, visit 
# http://creativecommons.org/licenses/by-nc-sa/3.0/us/ or send a 
# letter to Creative Commons, 171 Second Street, Suite 300, 
# San Francisco, California, 94105, USA.
#
#===============================================================#
 
require 5.6.1;
use lib './manage-ontap-sdk-3.5.1/lib/perl/NetApp/';
use lib './lib';
use POSIX qw/strftime/;
use NaServer;
use NaElement;
use NaErrno;
use Simple;
 
# Configuration
my $filer_hostname = "simtap2";
my $filer_username = "root";
my $filer_password = "netapp";
my $sqlserver_hostname = "win2k8";
my $db_name = "AdventureWorksDW";
my $db_datafile = "W:\\AdventureWorksDW_Data.mdf";
my $db_logfile = "X:\\AdventureWorksDW_Log.ldf";
my $db_datalun_filerpath = "/vol/vol1/sqlproddata";
my $db_loglun_filerpath = "/vol/vol2/sqlprodlogs";
my $clone_suffix = "clone";
my $snapshot_name = "clonesnap";
my $igroup = "viaRPC.iqn.1991-05.com.microsoft:win2k8";
 
main();
 
 
##############################
#
# Subroutines
#
##############################
 
 
 
sub main() {
 
	my $s = NaServer->new ($filer_hostname, 1, 3);
	my $resp = $s->set_style(LOGIN);
	if (ref ($resp) eq "NaElement" && $resp->results_errno != 0) {
		my $r = $resp->results_reason();
		print "Failed to set authentication style $r\n";
		exit 2;
	}
 
	$s->set_admin_user($filer_username, $filer_password);
 
	$resp = $s->set_transport_type(HTTP);
	if (ref ($resp) eq "NaElement" && $resp->results_errno != 0) {
		my $r = $resp->results_reason();
		print "Unable to set HTTP transport $r\n";
		exit 2;
	}
 
	# Begin 
	# begin_process($s);
 
	print "Detaching the database ($db_name)....";
	detach_database();
	print "Done\n";
 
	refresh_luns($s, "data");
	refresh_luns($s, "logs");
 
	print "Attaching the database ($db_name)....";
	attach_database($sqlserver_hostname,$db_name, $db_datafile, $db_logfile);
	print "Done\n";
	# End 
	# end_process($s);
 
	exit 0;	
}
 
sub detach_database {
	my $sqlcmd = "sqlcmd -d master -E -Q \"exec sp_detach_db $db_name\" ";
	print "Executing SQL Command: \"$sqlcmd\"\n";
	system($sqlcmd);
}
 
sub attach_database {
	my $sqlcmd = "sqlcmd -d master -E -Q \"exec sp_attach_db '$db_name', '$db_datafile', '$db_logfile'\" ";
	system($sqlcmd);
}
 
sub refresh_luns {
 
	my ($s, $lun_type) = @_;
	if ($lun_type eq "data") {
		@filer_volpath_splits = split("/", $db_datalun_filerpath);
		$file_path = $db_datafile;
		my @drive_splits = split(":", $db_datafile);
		$sd_lun_mount_point = $drive_splits[0];
 
	}
	elsif ($lun_type eq "logs") {
		@filer_volpath_splits = split("/", $db_loglun_filerpath);
		$file_path = $db_logfile;
		my @drive_splits = split(":", $db_logfile);
		$sd_lun_mount_point = $drive_splits[0];
	}
	else {
		print "Functionality not yet implemented\n";
		return (-1);
	}
 
	my $parent_vol_name = $filer_volpath_splits[2];
	$clone_vol_name = "${parent_vol_name}_${clone_suffix}";
	$cloned_lun_path = "/vol/$clone_vol_name/$filer_volpath_splits[3]";
	my $sd_lun_path = "$filer_hostname:$cloned_lun_path";
 
	print "Disconnecting LUN: $sd_lun_mount_point....";
	my $sys_cmd = "sdcli disk disconnect -m $sqlserver_hostname -d $sd_lun_mount_point";
 
	system($sys_cmd);
	print "Done\n";
 
	# Offline and Destroy the old clone volume
	prep_volumes($s, $clone_vol_name);
 
	# create a flexclone of that volume
	create_flexclone2($s, $parent_vol_name, $clone_vol_name);
 
	# Modify LUN and online
	#online_lun($s, $cloned_lun_path, $old_map, $igroup);
 
	# Connect the LUN
	print "Connecting LUN: $sd_lun_path\n";
	$sys_cmd = "sdcli  disk connect -p $sd_lun_path -d $sd_lun_mount_point -IG $sqlserver_hostname $igroup -dtype dedicated";
	print $sys_cmd . "\n";
	system ($sys_cmd);
}
 
 
sub prep_volumes {
 
	#4. set the serial number (fancy stuff)
	#5. map the luns and mount the luns from this vol
 
	my ($s, $clone_vol_name) = @_;
 
	# offline the volume
	print "Offlining previous clone volume $clone_vol_name...";
	my $result = $s->invoke("volume-offline", "name", $clone_vol_name);
	if (($result->results_errno != 0) && ($result->results_errno != 13042) ) {
		print "Error Code: " . $result->results_errno . " - " . $result->results_reason() . "\n";
	}
	else {
		print "Done\n";
		print "Destroying previous clone volume $clone_vol_name...";
		# Volume offlined - Now destroy it
		my $result = $s->invoke("volume-destroy", 
					"name", $clone_vol_name); 
		if ($result->results_errno != 0) {
			print "Error Code: " . $result->results_errno . " - " . $result->results_reason() . "\n";
		}
		else {
			print "Done\n";
			print "Volume $clone_vol_name has been offlined and destroyed\n";
		}
	}
}
 
sub create_flexclone2 {
	my ($s, $parent_vol_name, $clone_vol_name) = @_;
	print "Finding the latest snapshot in the volume '$parent_vol_name'\n";
	my $result = $s->invoke("snapshot-list-info", "volume", $parent_vol_name);
	if ($result->results_errno != 0) {
		print "\nError Code: " . $result->results_errno . " - " . $result->results_reason() . "\n";
		return (-1);
	}
	my $snapshotlist = $result->child_get("snapshots");
	if (!defined($snapshotlist) || ($snapshotlist eq "")) {
		# no snapshots to report
		printf("No snapshots on volume %s\n\n", $parent_vol_name);
		return (-1);
	}
	my @snapshots = $snapshotlist->children_get();
	my $tmp = 0;
	my $snapshot;
	my $snap;
	foreach my $ss (@snapshots) {
		if ($ss->child_get_int("access-time", 0) > $tmp) {
			$tmp = $ss->child_get_int("access-time", 0);
			$snapshot =  $ss->child_get_string("name");
			$snap = $ss;
		}
	}
	printf("Latest snapshot name is %s\n", $snap->child_get_string("name"));
	print "Creating a FlexClone volume....";
	my $result = $s->invoke("volume-clone-create", 
				"parent-volume", $parent_vol_name,
				"parent-snapshot", $snap->child_get_string("name"),
				"volume", $clone_vol_name);
	if ($result->results_errno != 0 ) {
		print "\nError Code: " . $result->results_errno . " - " . $result->results_reason() . "\n";
		return (-1);
	}
	print "Done\n";
}

Enhancements
Those who are adept at perl programming and solution deployment will notice a few things right away – that I am not a very adept perl programmer and there’s a room for improvement (that’s where the license comes in).

License
Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.

Download
Download the perl script.

References

Pages: 1 2 3

Comments

  1. V Ravi says:

    Hi Rajeev,

    I am very much impressed with your technical knowledge and articles on this blog. Keep doing your good work for the IT comunity.

    Thanks,
    Ravi

Speak Your Mind

*