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=bmbou...@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, "v...@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...");