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/25 22:16:17 UTC
svn commit: r829652 -
/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm
Author: bmbouter
Date: Sun Oct 25 21:16:16 2009
New Revision: 829652
URL: http://svn.apache.org/viewvc?rev=829652&view=rev
Log:
This includes clone monitoring and management of thin versus thick efficiency. This functionality will be explained in a future commit to the esxthin.README file. This code has been tested and works.
Modified:
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm
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=829652&r1=829651&r2=829652&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm Sun Oct 25 21:16:16 2009
@@ -259,6 +259,15 @@
} ## 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) {
+ 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)
+ } else {
+ notify($ERRORS{'DEBUG'}, 0, "The image library volume $volume_path is $density_percentage % dense");
+ }
+
# Remove old vm folder
netapp_delete_dir($s,"$volume_path/inuse/$computer_shortname");
@@ -268,12 +277,48 @@
# clone vmdk file from golden to inuse
my $from = "$volume_path/golden/$image_name/image.vmdk";
my $to = "$volume_path/inuse/$computer_shortname/image.vmdk";
- netapp_fileclone($s,$from,$to);
+ # 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);
# Copy the (large) -flat.vmdk file
- $from = "$volume_path/golden/$image_name/image-flat.vmdk";
$to = "$volume_path/inuse/$computer_shortname/image-flat.vmdk";
- netapp_fileclone($s,$from,$to);
+ 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";
+ } 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) {
+ # 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.");
+ }
+ } 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;
@@ -885,6 +930,40 @@
#/////////////////////////////////////////////////////////////////////////
+=head2 netapp_is_file
+
+ Parameters : $s, $file_path
+ Returns : 1($file_path exists) or 0($file_path doesn't exist)
+ Description : Determines if the file $file_path exists on the NetApp
+ backed by $s. Note, $file_path must begin with /vol and
+ should no contain a trailing slash.
+
+=cut
+
+sub netapp_is_file
+{
+ my $s = $_[0];
+ my $file_path = $_[1];
+
+ # Check if $file_path a directory or a file
+ my $in = NaElement->new("file-get-file-info");
+ $in->child_add_string("path",$file_path);
+ my $out = $s->invoke_elem($in);
+ if($out->results_status() eq "failed") {
+ #notify($ERRORS{'CRITICAL'}, 0, $out->results_reason() ."\n");
+ return 0;
+ } else {
+ my $file_type = $out->child_get("file-info")->child_get_string("file-type");
+ # Is this a file?
+ if ($file_type eq "file") {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#/////////////////////////////////////////////////////////////////////////
+
=head2 netapp_get_size
Parameters : $s, $path
@@ -914,6 +993,42 @@
#/////////////////////////////////////////////////////////////////////////
+=head2 netapp_get_vol_density_percentage
+
+ 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:
+ 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
+{
+ my $s = $_[0];
+ my $vol = $_[1];
+
+ # Check if $path a directory or a file
+ my $in = NaElement->new("volume-list-info");
+ $in->child_add_string("volume",$vol);
+ my $out = $s->invoke_elem($in);
+ if($out->results_status() eq "failed") {
+ #notify($ERRORS{'CRITICAL'}, 0, $out->results_reason() ."\n");
+ return 0;
+ } 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;
+ }
+}
+#/////////////////////////////////////////////////////////////////////////
+
=head2 netapp_delete_empty_dir
Parameters : $s, $dir_path
@@ -974,12 +1089,53 @@
#/////////////////////////////////////////////////////////////////////////
-=head2 netapp_fileclone
+=head2 netapp_copy
- Parameters : $s, $source_path, $dest_path
+ Parameters : $s, $from_path, $to_path, $netapp_identity_file
Returns : 1(success) or 0(failure)
+ Description : copies the item at $from_path to $to_path on the NetApp
+ backing $s. The identity_file should be passed in from above
+ and likelky comes from $self->data->get_image_identity
+ NOTE: The to_path actually names the directory for the thick
+ copy to live in. The file is located inside this directory
+ by its same name.
+
+=cut
+
+sub netapp_copy
+{
+ my $s = $_[0];
+ my $from_path = $_[1];
+ my $to_path = $_[2];
+ my $netapp_identity_file = $_[3];
+
+ my $user = $s->{user};
+ my $netapp_ip = $s->{server};
+
+ notify($ERRORS{'DEBUG'}, 0, "Doing an ndmpcopy on NetApp ($netapp_ip) of $from_path to $to_path");
+ if (!run_ssh_command($netapp_ip, $netapp_identity_file, "ndmpcopy $from_path $to_path", $user)) {
+ notify($ERRORS{'CRITICAL'}, 0, "Could not copy file on NetApp via SSH!");
+ return 0;
+ }
+ return 1;
+
+}
+
+#/////////////////////////////////////////////////////////////////////////
+
+=head2 netapp_fileclone
+
+ Parameters : $s, $source_path, $dest_path, $ignore_thick (boolean)
+ 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
+ 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.
=cut
@@ -988,23 +1144,81 @@
my $s = $_[0];
my $source_path = $_[1];
my $dest_path = $_[2];
+ my $ignore_thick = 0;
+ if (defined($_[3])) {
+ $ignore_thick = $_[3];
+ }
+
+ #The number of seconds to sleep before retrying if there are too many clones occurring
+ my $retry = 5;
+
+ my $too_many_clones_occurring = 0;
+ do {
+ my $in = NaElement->new("clone-start");
+ $in->child_add_string("source-path",$source_path);
+ $in->child_add_string("destination-path",$dest_path);
+ $in->child_add_string("no-snap","false");
- my $in = NaElement->new("clone-start");
- $in->child_add_string("source-path",$source_path);
- $in->child_add_string("destination-path",$dest_path);
- $in->child_add_string("no-snap","false");
-
- #
- # Invoke clone-start API
- #
- my $out = $s->invoke_elem($in);
-
- if($out->results_status() eq "failed") {
- notify($ERRORS{'CRITICAL'}, 0, $out->results_reason() ."\n");
- return 0;
- } else {
- return 1;
- }
+ my $out = $s->invoke_elem($in);
+
+ if($out->results_status() eq "failed") {
+ if ($out->results_errno() == 14611) {
+ notify($ERRORS{'DEBUG'}, 0, "Too Many Clones Currently Occuring ... will try again in $retry seconds");
+ sleep($retry);
+ $too_many_clones_occurring = 1;
+ } else {
+ notify($ERRORS{'CRITICAL'}, 0, $out->results_reason() ."\n");
+ return 0;
+ }
+ } else {
+ # The clone operation has begun
+ my $clone_status = "";
+ # Grab the volume uuid and clone_op_id specifying this clone operation
+ my $volume_uuid = $out->child_get("clone-id")->child_get("clone-id-info")->child_get_string("volume-uuid");
+ my $clone_op_id = $out->child_get("clone-id")->child_get("clone-id-info")->child_get_string("clone-op-id");
+
+ # Bundle a new clone-list-status request about the current clone operation
+ my $in = NaElement->new("clone-list-status");
+ my $clone_id = NaElement->new("clone-id");
+ my $clone_id_info = NaElement->new("clone-id-info");
+ $clone_id_info->child_add_string("clone-op-id",$clone_op_id);
+ $clone_id_info->child_add_string("volume-uuid",$volume_uuid);
+ $clone_id->child_add($clone_id_info);
+ $in->child_add($clone_id);
+ # send the clone-list-status request
+ 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($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...");
+ notify($ERRORS{'DEBUG'}, 0, "The clone for $dest_path will now be cancelled");
+ # Bundle a new clone-stop request to stop the current clone operation
+ my $stop_in = NaElement->new("clone-stop");
+ my $stop_clone_id = NaElement->new("clone-id");
+ my $stop_clone_id_info = NaElement->new("clone-id-info");
+ $stop_clone_id_info->child_add_string("clone-op-id",$clone_op_id);
+ $stop_clone_id_info->child_add_string("volume-uuid",$volume_uuid);
+ $stop_clone_id->child_add($stop_clone_id_info);
+ $stop_in->child_add($stop_clone_id);
+ # send the clone-stop request
+ my $stop_output = $s->invoke_elem($stop_in);
+ if($stop_output->results_status() eq "failed") {
+ notify($ERRORS{'CRITICAL'}, 0, $stop_output->results_reason() ."\n");
+ return 0;
+ } else {
+ notify($ERRORS{'DEBUG'}, 0, "The clone for $dest_path has successfully been cancelled");
+ return -1;
+ }
+ }
+ }
+ sleep(2);
+ $out = $s->invoke_elem($in);
+ }
+ return 1;
+ }
+ } while($too_many_clones_occurring);
}
#/////////////////////////////////////////////////////////////////////////////