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...");


Reply via email to