You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by bm...@apache.org on 2009/10/27 02:26:42 UTC

svn commit: r830043 - in /incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning: esxthin.README esxthin.pm

Author: bmbouter
Date: Tue Oct 27 01:26:41 2009
New Revision: 830043

URL: http://svn.apache.org/viewvc?rev=830043&view=rev
Log:
refactored clone management logic, includes more configuration parameters in the config section, more testing, and updated documentation

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README
    incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README?rev=830043&r1=830042&r2=830043&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README Tue Oct 27 01:26:41 2009
@@ -14,12 +14,18 @@
 		...
 
 The Config File:
-Place a config file named esxthin.conf in the same directory as esxthin.pm (<location of vcld>/../lib/Module/Provisioning/esxthin.conf)  Each line of this config file has the form key=value.  There are 4 possible keys to use {'ip','user','pass','https'}  'ip', 'user', and 'pass' should each be set to the correct string, but https only accepts values 'on' and 'off'  Here is an example config file:
+Place a config file named esxthin.conf in the same directory as esxthin.pm (<location of vcld binary>/../lib/Module/Provisioning/esxthin.conf)  Each line of this config file has the form key=value.  There are 8 possible keys to use {'ip','user','pass','https','admin_email','density_limit','density_alert_threshold','block_copy_limit'}  'ip', 'user', and 'pass' should each be set to the correct string.  'https' only accepts values 'on' and 'off.'  Admin E-mail should be set to the storage administrator or VCL administrator's e-mail.  'density_limit' is measured in blocks, and specifies the number maximum density allowed on a given volume.  Volume density are a per-controller, NetApp variable which you should ask NetApp what the correct value is for your hardware.
+
+Here is an example config file:
 
 ip=10.0.3.4
 user=vclnetappuser
 pass=f84uhkgh8
 https=on
+admin_email=bmbouter@gmail.com
+density_limit=14293651161088
+density_alert_threshold=0.9
+block_copy_limit=64
 
 
 Image requirements:

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm?rev=830043&r1=830042&r2=830043&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm Tue Oct 27 01:26:41 2009
@@ -75,6 +75,9 @@
 use NaServer;
 use NaElement;
 
+# The below variable indicates the full path to the NetApp config file
+my $NETAPP_CONFIG_PATH = "$FindBin::Bin/../lib/VCL/Module/Provisioning/esxthin.conf";
+
 ##############################################################################
 
 =head1 CLASS ATTRIBUTES
@@ -259,11 +262,37 @@
 
 	} ## end if ($vminfo_output =~ /^Information of Virtual Machine $computer_shortname/m)
 
-	my $density_percentage = netapp_get_vol_density_percentage($s,$volume_path);
-	if ($density_percentage > 0.9) {
+	
+	# Read the config file for configs used in the density calculation
+	my $storage_admin_email;
+	my $density_limit = 14293651161088;
+	my $density_alert_threshold = 0.9;
+	my $block_copy_limit = 0;
+
+        open(NETAPPCONF, $NETAPP_CONFIG_PATH);
+	while (<NETAPPCONF>)
+	{
+		chomp($_);
+		if ($_ =~ /^admin_email=(.*)/) {
+			$storage_admin_email = $1;
+		} elsif ($_ =~ /^density_limit=(.*)/) { 
+			$density_limit = int $1;
+		} elsif ($_ =~ /^density_alert_threshold=(.*)/) { 
+			$density_alert_threshold = $1;
+		} elsif ($_ =~ /^block_copy_limit=(.*)/) { 
+			$block_copy_limit = int $1;
+		}
+	}
+	close(NETAPPCONF);
+
+	my $dense_blocks = netapp_get_vol_density($s,$volume_path);
+	my $density_percentage = $dense_blocks / $density_limit;
+	if ($density_percentage >= $density_alert_threshold) {
 		notify($ERRORS{'CRITICAL'}, 0, "The image library volume $volume_path is too dense, and requires administrative attention IMMEDIATELY!!!");
-		notify($ERRORS{'CRITICAL'}, 0, "The volume $volume_path is currently $density_percentage % dense");
-		#mail($to,$subject,$mailstring, $from)
+		notify($ERRORS{'CRITICAL'}, 0, "The image library volume $volume_path is $density_percentage % dense");
+		my $netapp_ip = $s->{server};
+		my $mailmessage = "The Volume $volume_path on NetApp at $netapp_ip is dangerously dense with $density_percentage above the set alert threshold.  A VCL installation relies on this volume.  ACTION REQUIRED: administrativly create and configure another VCL image library volume to distribute the density demands of the VCL installation.";
+		mail($storage_admin_email,"Volume $volume_path on NetApp at $netapp_ip Dangerously Dense: Administrative Action Required!!!",$mailmessage, "vcl\@localhost.com");
 	} else {
 		notify($ERRORS{'DEBUG'}, 0, "The image library volume $volume_path is $density_percentage % dense");
 	}
@@ -278,47 +307,58 @@
 	my $from = "$volume_path/golden/$image_name/image.vmdk";
 	my $to   = "$volume_path/inuse/$computer_shortname/image.vmdk";
 	# Call the fileclone.  The 1 at the end tells the function to ignore a slow, thick copy (should it need to be a thick copy)
-	netapp_fileclone($s,$from,$to,1);
+	netapp_fileclone($s,$from,$to,1,$block_copy_limit);
 
 	# Copy the (large) -flat.vmdk file
+	# See esxthin.README for some explanation of the logic implemented in this section
 	$to   = "$volume_path/inuse/$computer_shortname/image-flat.vmdk";
 	my $continue = "true";
 	for (my $count = 0; $continue eq "true"; $count++) {
 		# Setup the $from to try to pack the clones densely from the parent goldens
 		if ($count == 0) {
 			$from = "$volume_path/golden/$image_name/image-flat.vmdk";
+			# Call the fileclone.
+			# The 0 at the end will cause the clone opeartion to stop with a -1 return code if the clone becomes thick.
+			my $clone_status = netapp_fileclone($s,$from,$to,0,$block_copy_limit);
+			if ($clone_status == 0) {
+				# A Clone error occured.  Provisioning cannot continue
+				return 0;
+			} elsif ($clone_status == -1) {
+				# The original vmdk parent is fully saturated
+				notify($ERRORS{'DEBUG'}, 0, "The original vmdk parent $from is saturated in its ability to produce new clones");
+			} elsif ($clone_status == 1) {
+				# The thin-clone has been successfully completed
+				notify($ERRORS{'DEBUG'}, 0, "$to has been thinly cloned successfully");
+				$continue = "false";
+			}
 		} else {
-			$from = "$volume_path/golden/$image_name/image-flat$count.vmdk/image-flat$count.vmdk";
-		}
-
-		# Make the Clone request
-		my $clone_status = netapp_fileclone($s,$from,$to,0);
-
-		if ($clone_status == 0) {
-			# A Clone error occured.  Provisioning cannot continue
-			return 0;
-		} elsif ($clone_status == -1) {
-			# The clone was thick and was cancelled.
-			# Now, check if the next one exists
-			my $next_count = $count + 1;
-			my $next_path = "$volume_path/golden/$image_name/image-flat$next_count.vmdk/image-flat.vmdk";
-			if (netapp_is_file($s,$next_path) != 1) {
+			my $parent = "$volume_path/golden/$image_name/image-flat1.vmdk/image-flat.vmdk";
+			# Determine if parent file exists
+			if (netapp_is_file($s,$parent) != 1) {
 				# The next clone parent file needs to be created
 				# TODO: Fix the race condition on this copy if multiple threads do an ndmpcopy over each other
-				my $copy_from = "$volume_path/golden/$image_name/image-flat.vmdk";
-				my $copy_to = "$volume_path/golden/$image_name/image-flat$next_count.vmdk";
-				notify($ERRORS{'DEBUG'}, 0, "Going to thick copy $copy_from to $copy_to");
-				netapp_copy($s,$copy_from,$copy_to,$image_identity);
-			} else {
-				notify($ERRORS{'DEBUG'}, 0, "Parent $next_path exists, the clone will use it.");
+				notify($ERRORS{'DEBUG'}, 0, "Thick copying $from to $parent");
+				my $ndmpcopy_to = "$volume_path/golden/$image_name/image-flat1.vmdk";
+				netapp_copy($s,$from,$ndmpcopy_to,$image_identity);
+			}
+			# Call the fileclone.
+			# The 0 at the end will cause the clone opeartion to stop with a -1 return code if the clone becomes thick.
+			my $clone_status = netapp_fileclone($s,$parent,$to,0,$block_copy_limit);
+			if ($clone_status == 0) {
+				# A Clone error occured.  Provisioning cannot continue
+				return 0;
+			} elsif ($clone_status == -1) {
+				# Clones of this $parent are coming out thick.  The parent needs to be removed
+				notify($ERRORS{'DEBUG'}, 0, "The thick, temporary cloning parent $parent is saturated in its ability to produce new thin clones");
+				notify($ERRORS{'DEBUG'}, 0, "$parent must be deleted");
+				netapp_delete_dir($s,"$volume_path/golden/$image_name/image-flat1.vmdk");
+			} elsif ($clone_status == 1) {
+				# The thin-clone has been successfully completed
+				notify($ERRORS{'DEBUG'}, 0, "$to has been thinly cloned successfully");
+				$continue = "false";
 			}
-		} elsif ($clone_status == 1) {
-			# The thin-clone has been successfully completed
-			notify($ERRORS{'DEBUG'}, 0, "$to has been thinly cloned successfully");
-			$continue = "false";
 		}
 	}
-	# Call the fileclone.  The 0 at the end will cause the clone opeartion to stop with a -1 return code if the clone becomes thick.
 
 	# Author new VMX file, output to temporary file (will file-write-file it below)
 	my @vmxfile;
@@ -654,7 +694,7 @@
 	my $ip;
 	my $use_https = 'off';
 
-        open(NETAPPCONF, "$FindBin::Bin/../lib/VCL/Module/Provisioning/esxthin.conf");
+        open(NETAPPCONF, $NETAPP_CONFIG_PATH);
 	while (<NETAPPCONF>)
 	{
 		chomp($_);
@@ -838,7 +878,7 @@
 	$in->child_add_string("path",$dir_path);
 	my $out = $s->invoke_elem($in);
 	if($out->results_status() eq "failed") {
-		notify($ERRORS{'CRITICAL'}, 0, $out->results_reason() ."\n");
+		notify($ERRORS{'DEBUG'}, 0, $out->results_reason() ."\n");
 		return 0;
 	} else {
 		my $file_type = $out->child_get("file-info")->child_get_string("file-type");
@@ -993,21 +1033,19 @@
 
 #/////////////////////////////////////////////////////////////////////////
 
-=head2 netapp_get_vol_density_percentage
+=head2 netapp_get_vol_density
 
  Parameters  : $s, $vol
- Returns     : A float between 0.0 <= 1.0 representing percentage
-               of density this volume currently experiences
- Description : Determines the percentage of indirection $vol already has on
-               the NetApp backed by $s.  The percentage is calculculated against
-               32TB (14293651161088 Bytes).  If percentage goes to 1.0 bad things
-               happen.  This function calculates density according to the formula:
+ Returns     : The number of dense blocks currently on the volume
+ Description : Reports the number of dense blocks volume $vol already has on
+               the NetApp backed by $s.  This function calculates density
+               according to the formula:
                density = <volume-info><size-used> + <volume-info><sis><size-shared>
                NOTE: $vol must start with /vol/ and must not contain a trailing slash.
 
 =cut
 
-sub netapp_get_vol_density_percentage
+sub netapp_get_vol_density
 {
 	my $s = $_[0];
 	my $vol = $_[1];
@@ -1022,9 +1060,7 @@
 	} else {
 		my $size_used = $out->child_get("volumes")->child_get("volume-info")->child_get_string("size-used");
 		my $sis_size_shared = $out->child_get("volumes")->child_get("volume-info")->child_get("sis")->child_get("sis-info")->child_get_string("size-shared");
-		my $total = $size_used + $sis_size_shared;
-		my $percent = $total / 14293651161088;
-		return $percent;
+		return $size_used + $sis_size_shared;
 	}
 }
 #/////////////////////////////////////////////////////////////////////////
@@ -1125,17 +1161,20 @@
 
 =head2 netapp_fileclone
 
- Parameters  : $s, $source_path, $dest_path, $ignore_thick (boolean)
+ Parameters  : $s, $source_path, $dest_path, $ignore_thick (boolean),
+               $block_copy_limit (int)
  Returns     : 1(success), 0(general failure), or -1 (clone was cancelled
                because it was thick)
  Description : clones the file $source_path to $dest_path on a NetApp
                storage system backing $s.  This is a blocking call, it waits
                for the clone operation to indicate the clone is 'complete'
                before returning '1'  Also, while $ignore_thick is true
-               if the clone copies any thick blocks then the function
-               stops the clone operation and returns '-1'  Note: $ignore_thick
-               is 0 by default making the function cancel thick file copies
-               the default behavior.
+               if the clone copies at least $block_copy_limit number of
+               thick blocks then the function stops the clone operation and
+               returns '-1'  Note: $ignore_thick is optional and 0 by default
+               making the function cancel thick file copies the default
+               behavior. $block_copy_limit is 0 by defualt, and sets the threshold
+               of thick blocks copied before a thin clone is considered thick to 0.
 
 =cut
 
@@ -1148,6 +1187,10 @@
 	if (defined($_[3])) {
 		$ignore_thick = $_[3];
 	}
+	my $block_copy_limit = 0;
+	if (defined($_[4])) {
+		$block_copy_limit = $_[4];
+	}
 
 	#The number of seconds to sleep before retrying if there are too many clones occurring
 	my $retry = 5;
@@ -1189,7 +1232,7 @@
 			my $out = $s->invoke_elem($in);
 			while($out->child_get("status")->child_get("ops-info")->child_get_string("clone-state") ne "completed") {
 				notify($ERRORS{'DEBUG'}, 0, "Waiting for clone $dest_path to finish...");
-				if($ignore_thick == 0 && $out->child_get("status")->child_get("ops-info")->child_get_string("blocks-copied") != 0) {
+				if($ignore_thick == 0 && $out->child_get("status")->child_get("ops-info")->child_get_string("blocks-copied") > $block_copy_limit) {
 					if($out->child_get("status")->child_get("ops-info")->child_get_string("percent-done") < 99) {
 						#cancel clone operation
 						notify($ERRORS{'DEBUG'}, 0, "The clone $dest_path is being inneficiently copied instead of being cloned...");