Author: arkurth
Date: Tue Jun  4 17:53:56 2013
New Revision: 1489534

URL: http://svn.apache.org/r1489534
Log:
VCL-630
Updated VMware code which copies and moves/renames virtual disks. If the name 
of the vmdk had to be shortened, the target vmdk is now renamed back to the 
originally requested name by the move_vmdk subroutine. Changed the 
copy_virtual_disk and move_virtual_disk subroutines in vSphere_SDK.pm to return 
a string containing the resulting vmdk file path. This is used by the caller to 
determine if the name had to be changed.

Updated VMware.pm::does_image_exist to search for both a vmdk named after the 
original image name as well as the shortened name. Moved _clean_vm_name from 
vSphere_SDK.pm to VMware.pm so it can be called from does_image_exist. This 
fixes issues in environments where images with the different names exist in 
different datastores/repositories.


Modified:
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm?rev=1489534&r1=1489533&r2=1489534&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm Tue 
Jun  4 17:53:56 2013
@@ -291,6 +291,7 @@ sub initialize {
                notify($ERRORS{'DEBUG'}, 0, "vSphere SDK object will be used to 
control the VM host $vmhost_computer_name and the VM: $vm_computer_name");
                
                $self->set_vmhost_os($vmware_api);
+               $vmware_api->set_vmhost_os($vmware_api);
        }
        else {
                # SSH access to the VM host OS is required if the vSphere SDK 
can't be used
@@ -3292,7 +3293,7 @@ sub set_vmx_file_path {
 
 =head2 get_reference_vmx_file_name
 
- Parameters  : none
+ Parameters  : $image_name (optional)
  Returns     : string
  Description : Returns the name of the reference vmx file that was used when 
the
                image was captured.
@@ -3306,67 +3307,8 @@ sub get_reference_vmx_file_name {
                return;
        }
        
-       return $ENV{reference_vmx_file_name} if 
defined($ENV{reference_vmx_file_name});
-       
-       my $image_name = $self->data->get_image_name() || return;
-       
-       $ENV{reference_vmx_file_name} = "$image_name.vmx.reference";
-       return $ENV{reference_vmx_file_name};
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_reference_vmx_file_path
-
- Parameters  : none
- Returns     : string
- Description : Returns the path to the reference vmx file that was used when 
the
-               image was captured.
-
-=cut
-
-sub get_reference_vmx_file_path {
-       my $self = shift;
-       if (ref($self) !~ /vmware/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       return $ENV{reference_vmx_file_path} if 
defined($ENV{reference_vmx_file_path});
-       
-       my $vmdk_directory_path_shared = 
$self->get_vmdk_directory_path_shared();
-       if (!$vmdk_directory_path_shared) {
-               notify($ERRORS{'WARNING'}, 0, "unable to construct reference 
vmx file path, shared vmdk directory path could not be determined");
-               return;
-       }
-       
-       my $reference_vmx_file_name = $self->get_reference_vmx_file_name();
-       if (!$reference_vmx_file_name) {
-               notify($ERRORS{'WARNING'}, 0, "unable to construct reference 
vmx file path, reference vmx file name could not be determined");
-               return;
-       }
-       
-       my $reference_vmx_file_path = 
"$vmdk_directory_path_shared/$reference_vmx_file_name";
-       
-       if ($self->vmhost_os->file_exists($reference_vmx_file_path)) {
-               $ENV{reference_vmx_file_path} = $reference_vmx_file_path;
-               notify($ERRORS{'DEBUG'}, 0, "determined reference vmx file 
path: $ENV{reference_vmx_file_path}");
-               return $ENV{reference_vmx_file_path};
-       }
-       
-       my $repository_vmdk_file_path = $self->get_repository_vmdk_file_path();
-       if ($self->is_repository_mounted_on_vmhost()) {
-               if ($self->vmhost_os->file_exists($repository_vmdk_file_path)) {
-                       $ENV{reference_vmx_file_path} = 
$repository_vmdk_file_path;
-                       notify($ERRORS{'DEBUG'}, 0, "determined reference vmx 
file path: $ENV{reference_vmx_file_path}");
-                       return $ENV{reference_vmx_file_path};
-               }
-       }
-       else {
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "determined reference vmx file path: 
$ENV{reference_vmx_file_path}");
-       return $ENV{reference_vmx_file_path};
+       my $image_name = shift || $self->data->get_image_name();
+       return "$image_name.vmx.reference";
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -4573,6 +4515,8 @@ sub does_image_exist {
                return;
        }
        
+       my $image_name = $self->data->get_image_name();
+       my $image_name_truncated = $self->_clean_vm_name($image_name);
        my $vmhost_name = $self->data->get_vmhost_short_name() || return;
        my $management_node_hostname = 
$self->data->get_management_node_short_name() || 'management node';
        
@@ -4585,11 +4529,22 @@ sub does_image_exist {
        
        # Check if the vmdk file already exists on the VM host
        if ($self->vmhost_os->file_exists($vmhost_vmdk_file_path_shared)) {
-               notify($ERRORS{'OK'}, 0, "image exists in the shared directory 
on the VM host: $vmhost_vmdk_file_path_shared");
+               notify($ERRORS{'OK'}, 0, "image exists in datastore on VM host 
$vmhost_name: $vmhost_vmdk_file_path_shared");
+               return 1;
+       }
+       else {
+               notify($ERRORS{'DEBUG'}, 0, "image does NOT exist in datastore 
on VM host $vmhost_name: $vmhost_vmdk_file_path_shared");
+       }
+       
+       # Check if the truncated vmdk file already exists on the VM host
+       (my $vmhost_vmdk_file_path_shared_truncated = 
$vmhost_vmdk_file_path_shared) =~ s/$image_name/$image_name_truncated/g;
+       if 
($self->vmhost_os->file_exists($vmhost_vmdk_file_path_shared_truncated)) {
+               notify($ERRORS{'OK'}, 0, "image exists with truncated name in 
datastore on VM host $vmhost_name: $vmhost_vmdk_file_path_shared_truncated");
+               $self->data->set_image_name($image_name_truncated);
                return 1;
        }
        else {
-               notify($ERRORS{'DEBUG'}, 0, "image does not exist in the shared 
directory on the VM host");
+               notify($ERRORS{'DEBUG'}, 0, "image does NOT exist with 
truncated name in datastore on VM host $vmhost_name: 
$vmhost_vmdk_file_path_shared_truncated");
        }
        
        # Get the image repository file path
@@ -4599,44 +4554,46 @@ sub does_image_exist {
                return 0;
        }
        
+       (my $repository_vmdk_file_path_truncated = $repository_vmdk_file_path) 
=~ s/$image_name/$image_name_truncated/g;
+       
        if ($self->is_repository_mounted_on_vmhost()) {
-               notify($ERRORS{'DEBUG'}, 0, "checking if vmdk file exists in 
image repository mounted on VM host: $vmhost_name:$repository_vmdk_file_path");
                if ($self->vmhost_os->file_exists($repository_vmdk_file_path)) {
-                       notify($ERRORS{'DEBUG'}, 0, "vmdk file exists in image 
repository mounted on VM host: $vmhost_name:$repository_vmdk_file_path");
+                       notify($ERRORS{'DEBUG'}, 0, "image exists in image 
repository mounted on VM host: $vmhost_name:$repository_vmdk_file_path");
                        return 1;
                }
                else {
-                       notify($ERRORS{'DEBUG'}, 0, "vmdk file does not exist 
in image repository mounted on VM host: 
$vmhost_name:$repository_vmdk_file_path");
-                       return 0;
+                       notify($ERRORS{'DEBUG'}, 0, "image does NOT exist in 
image repository mounted on VM host: $vmhost_name:$repository_vmdk_file_path");
+               }
+               
+               if 
($self->vmhost_os->file_exists($repository_vmdk_file_path_truncated)) {
+                       notify($ERRORS{'DEBUG'}, 0, "image exists with 
truncated name in image repository mounted on VM host $vmhost_name: 
$repository_vmdk_file_path_truncated");
+                       $self->data->set_image_name($image_name_truncated);
+                       return 1;
+               }
+               else {
+                       notify($ERRORS{'DEBUG'}, 0, "image does NOT exist with 
truncated name in image repository mounted on VM host $vmhost_name: 
$repository_vmdk_file_path_truncated");
                }
        }
        else {
-               notify($ERRORS{'DEBUG'}, 0, "checking if vmdk file exists in 
image repository on managment node $management_node_hostname: 
$repository_vmdk_file_path");
-               
-               # Escape all spaces in the path
-               my $escaped_repository_vmdk_file_path = 
escape_file_path($repository_vmdk_file_path);
-               
-               # Check if the file or directory exists
-               # Do not enclose the path in quotes or else wildcards won't work
-               my $command = "stat $escaped_repository_vmdk_file_path";
-               my ($exit_status, $output) = run_command($command, 1);
-               if (!defined($output)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to run command to 
determine if vmdk file exists on management node:\npath: 
'$repository_vmdk_file_path'\ncommand: '$command'");
-                       return;
+               if ($self->mn_os->file_exists($repository_vmdk_file_path)) {
+                       notify($ERRORS{'DEBUG'}, 0, "image exists in image 
repository mounted on management node: $repository_vmdk_file_path");
+                       return 1;
                }
-               elsif (grep(/no such file/i, @$output)) {
-                       notify($ERRORS{'DEBUG'}, 0, "vmdk file does not exist 
on management node: '$repository_vmdk_file_path'");
-                       return 0;
+               else {
+                       notify($ERRORS{'DEBUG'}, 0, "image does NOT exist in 
image repository mounted on management node: $repository_vmdk_file_path");
                }
-               elsif (grep(/^\s*Size:.*file$/i, @$output)) {
-                       notify($ERRORS{'DEBUG'}, 0, "vmdk file exists on 
management node: '$repository_vmdk_file_path'");
+               
+               if 
($self->mn_os->file_exists($repository_vmdk_file_path_truncated)) {
+                       notify($ERRORS{'DEBUG'}, 0, "image exists with 
truncated name in image repository mounted on management node: 
$repository_vmdk_file_path_truncated");
+                       $self->data->set_image_name($image_name_truncated);
                        return 1;
                }
                else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to determine if 
vmdk file exists on management node:\npath: 
'$repository_vmdk_file_path'\ncommand: '$command'\nexit status: $exit_status, 
output:\n" . join("\n", @$output));
-                       return;
+                       notify($ERRORS{'DEBUG'}, 0, "image does NOT exist with 
truncated name in image repository mounted on management node: 
$repository_vmdk_file_path_truncated");
                }
        }
+       
+       return 0;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -5776,11 +5733,16 @@ sub copy_vmdk {
        my $source_directory_path = 
$self->_get_parent_directory_normal_path($source_vmdk_file_path) || return;
        my $destination_directory_path = 
$self->_get_parent_directory_normal_path($destination_vmdk_file_path) || return;
        
+       my $source_vmdk_file_base_name = 
$self->_get_file_base_name($source_vmdk_file_path) || return;
+       my $destination_vmdk_file_base_name = 
$self->_get_file_base_name($destination_vmdk_file_path) || return;
+       
        # Construct the source and destination reference vmx file paths
        # The reference vmx file is copied to the vmdk directory if it exists
-       my $reference_vmx_file_name = $self->get_reference_vmx_file_name();
-       my $source_reference_vmx_file_path = 
"$source_directory_path/$reference_vmx_file_name";
-       my $destination_reference_vmx_file_path = 
"$destination_directory_path/$reference_vmx_file_name";
+       my $source_reference_vmx_file_name = 
$self->get_reference_vmx_file_name($source_vmdk_file_base_name);
+       my $source_reference_vmx_file_path = 
"$source_directory_path/$source_reference_vmx_file_name";
+       
+       my $destination_reference_vmx_file_name = 
$self->get_reference_vmx_file_name($destination_vmdk_file_base_name);
+       my $destination_reference_vmx_file_path = 
"$destination_directory_path/$destination_reference_vmx_file_name";
        
        # Set the default virtual disk type if the argument was not specified
        if (!$virtual_disk_type) {
@@ -5811,27 +5773,33 @@ sub copy_vmdk {
        }
        
        my $start_time = time;
-       my $copy_result = 0;
-
+       my $end_time;
        # Attempt to use the API's copy_virtual_disk subroutine
        if ($self->api->can('copy_virtual_disk')) {
-               my $image_name = $self->data->get_image_name();
-               # Initialize this with the image name
-               $self->api->{new_image_name} = $image_name;
-               if ($self->api->copy_virtual_disk($source_vmdk_file_path, 
$destination_vmdk_file_path, $virtual_disk_type)) {
-                       notify($ERRORS{'OK'}, 0, "copied vmdk using API's 
copy_virtual_disk subroutine");
-                       # If the new VM name is longer than 29 chars, it may be 
truncated.
-                       # In that case, update the image name in the database, 
but only do this
-                       # if the API changes the value of new_image_name.
-                       my $request_state_name = 
$self->data->get_request_state_name();
-                       if ($request_state_name eq 'image' && 
$self->api->{new_image_name} ne $image_name) {
-                               my $image_id = $self->data->get_image_id();
-                               my $imagerevision_id = 
$self->data->get_imagerevision_id();
-                               update_image_name($image_id, $imagerevision_id, 
$self->api->{new_image_name});
-                               
$self->data->set_image_name($self->api->{new_image_name});
-                               notify($ERRORS{'DEBUG'}, 0, "updated image name 
to ".$self->api->{new_image_name});
+               my $copied_destination_vmdk_file_path = 
$self->api->copy_virtual_disk($source_vmdk_file_path, 
$destination_vmdk_file_path, $virtual_disk_type);
+               if ($copied_destination_vmdk_file_path) {
+                       $end_time = time;
+                       $copied_destination_vmdk_file_path = 
$self->_get_normal_path($copied_destination_vmdk_file_path);
+                       if ($copied_destination_vmdk_file_path ne 
$destination_vmdk_file_path) {
+                               notify($ERRORS{'DEBUG'}, 0, "copied vmdk using 
API's copy_virtual_disk subroutine but destination path was changed:\n" .
+                                       "intended destination path: 
$destination_vmdk_file_path\n" .
+                                       "copied destination path: 
$copied_destination_vmdk_file_path\n" .
+                                       "attempting to move copied vmdk to 
intended path"
+                               );
+                               
+                               if 
($self->move_vmdk($copied_destination_vmdk_file_path, 
$destination_vmdk_file_path)) {
+                                       my $copied_destination_directory_path = 
$self->_get_parent_directory_normal_path($copied_destination_vmdk_file_path);
+                                       
$self->vmhost_os->delete_file($copied_destination_directory_path);
+                               }
+                               else {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to move vmdk which was copied by API's copy_virtual_disk subroutine with a 
different name to the correct path");
+                                       
$self->vmhost_os->delete_file($copied_destination_vmdk_file_path);
+                                       return;
+                               }
+                       }
+                       else {
+                               notify($ERRORS{'OK'}, 0, "copied vmdk using 
API's copy_virtual_disk subroutine");
                        }
-                       $copy_result = 1;
                }
                else {
                        notify($ERRORS{'WARNING'}, 0, "failed to copy vmdk 
using API's copy_virtual_disk subroutine");
@@ -5840,19 +5808,18 @@ sub copy_vmdk {
        }
        
        # Make sure VM host OS object implements 'execute' before attempting to 
call utilities
-       if (!$copy_result && !$self->vmhost_os->can('execute')) {
+       if (!$end_time && !$self->vmhost_os->can('execute')) {
                notify($ERRORS{'WARNING'}, 0, "failed to copy vmdk on VM host 
$vmhost_name, unable to copy using API's copy_virtual_disk subroutine and an 
'execute' subroutine is not implemented by the VM host OS object");
                return;
        }
-       elsif (!$copy_result) {
+       
+       if (!$end_time) {
                # Create the destination directory
                if 
(!$self->vmhost_os->create_directory($destination_directory_path)) {
                        notify($ERRORS{'WARNING'}, 0, "unable to copy vmdk, 
destination directory could not be created on VM host $vmhost_name: 
$destination_directory_path");
                        return;
                }
-       }
-       
-       if (!$copy_result) {
+               
                # Try to use vmkfstools
                my $command = "vmkfstools -i \"$source_vmdk_file_path\" 
\"$destination_vmdk_file_path\" -d $virtual_disk_type";
                notify($ERRORS{'DEBUG'}, 0, "attempting to copy virtual disk 
using vmkfstools, disk type: $virtual_disk_type:\n'$source_vmdk_file_path' --> 
'$destination_vmdk_file_path'");
@@ -5903,12 +5870,12 @@ sub copy_vmdk {
                        notify($ERRORS{'WARNING'}, 0, "failed to copy virtual 
disk\ncommand: '$command'\noutput:\n" . join("\n", @$output));
                }
                else {
+                       $end_time = time;
                        notify($ERRORS{'OK'}, 0, "copied virtual disk on VM 
host using vmkfstools, destination disk type: 
$virtual_disk_type:\n'$source_vmdk_file_path' --> 
'$destination_vmdk_file_path'");
-                       $copy_result = 1;
                }
        }
        
-       if (!$copy_result) {
+       if (!$end_time) {
                # Try to use vmware-vdiskmanager
                # Use disk type  = 1 (2GB sparse)
                my $vdisk_command = "vmware-vdiskmanager -r 
\"$source_vmdk_file_path\" -t 1 \"$destination_vmdk_file_path\"";
@@ -5999,7 +5966,7 @@ sub copy_vmdk {
                        elsif ($partial_chains_error) {
                                # Had to make a copy of the original master 
vmdk earlier, not the desired source vmdk
                                # Still need to merge the delta vmdk into this 
copy
-                               $copy_result = 1;
+                               $end_time = time;
                                
                                # Determine the .vmsd file path
                                my $vmx_file_path = $self->get_vmx_file_path();
@@ -6016,12 +5983,12 @@ sub copy_vmdk {
                                        my ($sed_exit_status, $sed_output) = 
$self->vmhost_os->execute($sed_command);
                                        if (!defined($sed_output)) {
                                                notify($ERRORS{'WARNING'}, 0, 
"failed to execute command to replace original vmdk file path with copied vmdk 
file path in $replace_file_path");
-                                               $copy_result = 0;
+                                               undef $end_time;
                                                last;
                                        }
                                        elsif (grep(/sed: /, @$sed_output)) {
                                                notify($ERRORS{'WARNING'}, 0, 
"failed to replace original vmdk file path with copied vmdk file path in 
'$replace_file_path'\n'$source_vmdk_file_path' --> 
'$destination_vmdk_file_path'\ncommand: '$sed_command'\noutput:\n" . join("\n", 
@$sed_output));
-                                               $copy_result = 0;
+                                               undef $end_time;
                                                last;
                                        }
                                        else {
@@ -6030,7 +5997,7 @@ sub copy_vmdk {
                                }
                                
                                # Remove the VM's snapshots, this merges the 
delta vmdk into the copy of the original master vmdk
-                               if ($copy_result) {
+                               if ($end_time) {
                                        if 
($self->api->remove_snapshots($vmx_file_path)) {
                                                notify($ERRORS{'DEBUG'}, 0, 
"removed snapshots from VM, the merged delta vmdk '$delta_vmdk_file_path' with 
destination vmdk '$destination_vmdk_file_path'");
                                        }
@@ -6042,13 +6009,13 @@ sub copy_vmdk {
                        }
                        else {
                                notify($ERRORS{'OK'}, 0, "copied virtual disk 
on VM host $vmhost_name using vmware-vdiskmanager:\n'$source_vmdk_file_path' 
--> '$destination_vmdk_file_path'");
-                               $copy_result = 1;
+                               $end_time = time;
                        }
                }
        }
        
        # Check if any of the methods was successful
-       if (!$copy_result) {
+       if (!$end_time) {
                notify($ERRORS{'WARNING'}, 0, "failed to copy virtual disk on 
VM host $vmhost_name using any available methods:\n'$source_vmdk_file_path' --> 
'$destination_vmdk_file_path'");
                
                # Delete the destination directory
@@ -6058,12 +6025,11 @@ sub copy_vmdk {
                elsif 
(!$self->vmhost_os->delete_file($destination_directory_path)) {
                        notify($ERRORS{'WARNING'}, 0, "failed to delete 
destination directory after failing to copy virtual disk on VM host 
$vmhost_name: $destination_directory_path");
                }
-               
                return;
        }
        
        # Calculate how long it took to copy
-       my $duration_seconds = (time - $start_time);
+       my $duration_seconds = ($end_time - $start_time);
        my $minutes = ($duration_seconds / 60);
        $minutes =~ s/\..*//g;
        my $seconds = ($duration_seconds - ($minutes * 60));
@@ -6091,7 +6057,7 @@ sub copy_vmdk {
        $search_path =~ s/(\.vmdk)$/\*$1/i;
        my $image_size_bytes = $self->vmhost_os->get_file_size($search_path);
        if (!defined($image_size_bytes) || $image_size_bytes !~ /^\d+$/) {
-               notify($ERRORS{'WARNING'}, 0, "copied vmdk on VM host 
$vmhost_name but failed to retrieve destination file 
size:\n'$source_vmdk_file_path' --> '$destination_vmdk_file_path'");
+               notify($ERRORS{'WARNING'}, 0, "copied vmdk on VM host 
$vmhost_name but failed to retrieve destination file size:\nsource: 
'$source_vmdk_file_path'\ndestination: '$destination_vmdk_file_path'");
                return 1;
        }
        
@@ -6121,7 +6087,9 @@ sub copy_vmdk {
        my $gb_per_minute = ($image_size_gb / $duration_seconds * 60);
        
        
-       notify($ERRORS{'OK'}, 0, "copied vmdk on VM host $vmhost_name: 
'$source_vmdk_file_path' --> '$destination_vmdk_file_path'\n" .
+       notify($ERRORS{'OK'}, 0, "copied vmdk on VM host $vmhost_name:\n" .
+               "source: '$source_vmdk_file_path'\n" .
+               "destination: '$destination_vmdk_file_path'\n" .
                "time to copy: $minutes:$seconds (" . 
format_number($duration_seconds) . " seconds)\n" .
                "---\n" .
                "bits copied:  " . format_number($image_size_bits) . " 
($image_size_bits)\n" .
@@ -6198,37 +6166,15 @@ sub move_vmdk {
        $self->vmhost_os->create_directory($destination_vmdk_directory_path) || 
return;
        
        # Check if the API object has implented a move_virtual_disk subroutine
-       if ($self->api->can("move_virtual_disk")) {
-               notify($ERRORS{'OK'}, 0, "attempting to move vmdk file using 
API's 'move_virtual_disk' subroutine: $source_vmdk_file_path --> 
$destination_vmdk_file_path");
-               
-               my $image_name = $self->data->get_image_name();
-               $self->api->{new_image_name} = $image_name;
+       if ($self->api->can('move_virtual_disk')) {
                if ($self->api->move_virtual_disk($source_vmdk_file_path, 
$destination_vmdk_file_path)) {
-                       notify($ERRORS{'OK'}, 0, "moved vmdk using API's 
'move_virtual_disk' subroutine: '$source_vmdk_file_path' --> 
'$destination_vmdk_file_path'");
-                       # If the new VM name is longer than 29 chars, it may be 
truncated.
-                       # In that case, update the image name in the database, 
but only do this
-                       # if the API changes the value of {new_image_name}
-                       my $request_state_name = 
$self->data->get_request_state_name();
-                       if ($request_state_name eq 'image' && 
$self->api->{new_image_name} ne $image_name) {
-                               my $image_id = $self->data->get_image_id();
-                               my $imagerevision_id = 
$self->data->get_imagerevision_id();
-                               update_image_name($image_id, $imagerevision_id, 
$self->api->{new_image_name});
-                               
$self->data->set_image_name($self->api->{new_image_name});
-                               notify($ERRORS{'DEBUG'}, 0, "updated image name 
to ".$self->api->{new_image_name});
-                       }
+                       notify($ERRORS{'OK'}, 0, "moved vmdk using API's 
move_virtual_disk subroutine");
                        return 1;
                }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "failed to move vmdk using 
API's 'move_virtual_disk' subroutine");
-               }
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "'move_virtual_disk' subroutine has 
not been implemented by the API: " . ref($self->api));
        }
        
        # Check if the VM host OS object implements an execute subroutine and 
attempt to run vmware-vdiskmanager
        if ($self->vmhost_os->can("execute")) {
-               
                # Try vmware-vdiskmanager
                notify($ERRORS{'OK'}, 0, "attempting to move vmdk file using 
vmware-vdiskmanager: $source_vmdk_file_path --> $destination_vmdk_file_path");
                my $vdisk_command = "vmware-vdiskmanager -n 
\"$source_vmdk_file_path\" \"$destination_vmdk_file_path\"";
@@ -6421,10 +6367,9 @@ sub move_vmdk {
                notify($ERRORS{'WARNING'}, 0, "failed to move vmdk using any 
available methods: '$source_vmdk_file_path' --> '$destination_vmdk_file_path'");
                return;
        }
-       else {
-               notify($ERRORS{'OK'}, 0, "moved vmdk file: 
'$source_vmdk_file_path' --> '$destination_vmdk_file_path'");
-               return 1;
-       }
+       
+       notify($ERRORS{'OK'}, 0, "moved vmdk file: '$source_vmdk_file_path' --> 
'$destination_vmdk_file_path'");
+       return 1;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -6754,7 +6699,7 @@ sub get_datastore_info {
                return;
        }
        else {
-               notify($ERRORS{'DEBUG'}, 0, "retrieved datastore info from VM 
host:\n" . format_data($datastore_info));
+               notify($ERRORS{'DEBUG'}, 0, "retrieved datastore info from VM 
host: " . join(", ", sort keys %$datastore_info));
                $self->{datastore_info} = $datastore_info;
                return $datastore_info;
        }
@@ -7409,6 +7354,56 @@ sub _get_vmx_file_path_computer_name {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 _clean_vm_name
+ Parameters  : $vm_name
+ Returns     : string
+ Description : VMWare vCenter supports VM Names of up to 80 characters, but if
+               the name is greater than 29 characters, it will truncate the 
+               corresponding name and enclosing directory of the virtual disks.
+
+=cut
+
+sub _clean_vm_name {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $vm_name = shift || return;
+       
+       # if the length of the name is > 29, then truncate it in such a way that
+       # the image name remains unique in the VCL database
+       my $MAX_VMNAME_LEN = 29;
+       if (length $vm_name > $MAX_VMNAME_LEN) {
+               notify($ERRORS{'DEBUG'}, 0, "truncating VM name $vm_name");
+               my $newname = "";
+               if ($vm_name =~ m/^(\w+)-(\w+?)(\d*)-(v\d+)$/) {
+                       my $base = $1;
+                       my $name = $2;
+                       my $imgid = $3;
+                       my $version = $4;
+                       my $shortened = substr($name, 0, $MAX_VMNAME_LEN - 2 - 
length($imgid) - length($base) - length($version));
+                       $newname = $base . "-" . $shortened . $imgid . "-" . 
$version; 
+               }
+               else {
+                       my ($pre_len, $post_len) = ($MAX_VMNAME_LEN - 10, 10);
+                       my ($pre, $post) = $vm_name =~ 
m/^(.{$pre_len}).*(.{$post_len})$/;
+                       $newname = $pre . $post;
+               }
+               if (get_image_info($newname, 0, 1)) {
+                       notify($ERRORS{'WARNING'}, 0, "Naming conflict: 
$newname already exists in the database");
+               }
+               else {
+                       notify($ERRORS{'DEBUG'}, 0, "Changed image name to: 
$newname");
+                       $vm_name = $newname;
+               }
+       }
+       return $vm_name;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 _check_datastore_paths
 
  Parameters  : @check_paths (optional)

Modified: 
vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm?rev=1489534&r1=1489533&r2=1489534&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm 
Tue Jun  4 17:53:56 2013
@@ -164,7 +164,7 @@ sub initialize {
                        last;
                }
        }
-
+       
        if (!$vim) {
                notify($ERRORS{'DEBUG'}, 0, "failed to connect to VM host 
$vmhost_hostname");
                return;
@@ -320,6 +320,10 @@ sub vm_unregister {
        else {
                $vm_name = $argument;
                $vm_view = $self->_get_vm_view($argument);
+               if (!$vm_view) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to unregister VM, 
VM view object could not be retrieved for argument: '$argument'");
+                       return;
+               }
        }
        
        my $vmx_path = $vm_view->{summary}{config}{vmPathName};
@@ -485,65 +489,20 @@ sub get_vm_power_state {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _clean_vm_name
- Parameters  : $vm_name
- Returns     : string
- Description : VMWare vCenter supports VM Names of up to 80 characters, but if
-               the name is greater than 29 characters, it will truncate the 
-               corresponding name and enclosing directory of the virtual disks.
-
-=cut
-
-sub _clean_vm_name {
-       my $self = shift;
-       if (ref($self) !~ /VCL::Module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $vm_name = shift || return;
-       
-       # if the length of the name is > 29, then truncate it in such a way that
-       # the image name remains unique in the VCL database
-       my $MAX_VMNAME_LEN = 29;
-       if (length $vm_name > $MAX_VMNAME_LEN) {
-               notify($ERRORS{'DEBUG'}, 0, "truncating VM name $vm_name");
-               my $newname = "";
-               if ($vm_name =~ m/^(\w+)-(\w+?)(\d*)-(v\d+)$/) {
-                       my $base = $1;
-                       my $name = $2;
-                       my $imgid = $3;
-                       my $version = $4;
-                       my $shortened = substr($name, 0, $MAX_VMNAME_LEN - 2 - 
length($imgid) - length($base) - length($version));
-                       $newname = $base . "-" . $shortened . $imgid . "-" . 
$version; 
-               }
-               else {
-                       my ($pre_len, $post_len) = ($MAX_VMNAME_LEN - 10, 10);
-                       my ($pre, $post) = $vm_name =~ 
m/^(.{$pre_len}).*(.{$post_len})$/;
-                       $newname = $pre . $post;
-               }
-               if (get_image_info($newname, 0, 1)) {
-                       notify($ERRORS{'WARNING'}, 0, "Naming conflict: 
$newname already exists in the database");
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "Changed image name to: 
$newname");
-                       $vm_name = $newname;
-               }
-       }
-       return $vm_name;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 copy_virtual_disk
 
  Parameters  : $source_vmdk_file_path, $destination_vmdk_file_path, $disk_type 
(optional), $adapter_type (optional)
- Returns     : boolean
+ Returns     : string
  Description : Copies a virtual disk (set of vmdk files). This subroutine 
allows
                a virtual disk to be converted to a different disk type or
                adapter type. The source and destination vmdk file path 
arguments
                are required.
                
+               A string is returned containing the destination vmdk file path.
+               This may not be the same as the $destination_vmdk_file_path
+               argument if the name had to be truncated to adhere to SDK naming
+               restrictions.
+               
                The disk type argument is optional and may be one of the
                following values:
                -eagerZeroedThick
@@ -743,7 +702,7 @@ sub copy_virtual_disk {
        }
        else {
                notify($ERRORS{'OK'}, 0, "copied vmdk on VM host $vmhost_name 
using CopyVirtualDisk function:\n" . format_data($copy_virtual_disk_result));
-               return 1;
+               return $destination_path;
        }
        
        my $resource_pool_view = $self->_get_resource_pool_view() || return;
@@ -757,6 +716,12 @@ sub copy_virtual_disk {
        my $source_vm_name = 
$self->_clean_vm_name("source-$request_id\_$destination_base_name");
        my $clone_vm_name = $self->_clean_vm_name($destination_base_name);
        
+       if ($clone_vm_name ne $destination_base_name) {
+               notify($ERRORS{'OK'}, 0, "virtual disk name 
shortened:\noriginal: $destination_base_name --> modified: $clone_vm_name");
+               $destination_base_name = $clone_vm_name;
+               $destination_path = "[$destination_datastore_name] 
$clone_vm_name/$clone_vm_name.vmdk";
+       }
+       
        my $source_vm_directory_path = "[$source_datastore_name] 
$source_vm_name";
        my $clone_vm_directory_path = "[$destination_datastore_name] 
$clone_vm_name";
        
@@ -771,7 +736,8 @@ sub copy_virtual_disk {
                        );
                        
                        # Unregister the VM, don't attempt to delete it or else 
the source vmdk may be deleted
-                       return unless 
$self->vm_unregister($existing_vmx_file_path);
+                       # Don't fail if VM can't be unregistered, it may not be 
registered
+                       $self->vm_unregister($existing_vmx_file_path);
                }
                elsif ($existing_vmx_directory_path eq 
$clone_vm_directory_path) {
                        notify($ERRORS{'WARNING'}, 0, "existing VM using the 
directory of the VM clone will be deleted:\n" .
@@ -922,7 +888,7 @@ EOF
                );
                if ($clone_vm) {
                        $clone_vm_view = Vim::get_view(mo_ref => $clone_vm);
-                       notify($ERRORS{'DEBUG'}, 0, "cloned VM: $source_vm_name 
--> $clone_vm_name" . format_data($clone_vm_view));
+                       notify($ERRORS{'DEBUG'}, 0, "cloned VM: $source_vm_name 
--> $clone_vm_name");
                }
                else {
                        notify($ERRORS{'WARNING'}, 0, "failed to clone VM: 
$source_vm_name --> $clone_vm_name");
@@ -960,9 +926,8 @@ EOF
        # Set this as a class value so that it is retrievable from within 
        # the calling context, i.e. capture(), routine. This way, in case 
        # the name changes, it is possible to update the database with the new 
value.
-       $self->{new_image_name} = $clone_vm_name;
        notify($ERRORS{'OK'}, 0, "copied virtual disk on VM host $vmhost_name: 
'$source_path' --> '$destination_path'");
-       return 1;
+       return $destination_path;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -970,7 +935,7 @@ EOF
 =head2 move_virtual_disk
 
  Parameters  : $source_path, $destination_path
- Returns     : boolean
+ Returns     : string
  Description : Moves or renames a virtual disk (set of vmdk files).
 
 =cut
@@ -1000,6 +965,8 @@ sub move_virtual_disk {
                return;
        }
        
+       my $source_parent_directory_path = 
$self->_get_parent_directory_datastore_path($source_path) || return;
+       
        # Make sure the destination file does not exist
        if ($self->file_exists($destination_path)) {
                notify($ERRORS{'WARNING'}, 0, "destination file already exists 
on VM host $vmhost_name: '$destination_path'");
@@ -1036,47 +1003,26 @@ sub move_virtual_disk {
                # A FileNotFound fault will be generated if the source vmdk 
file exists but there is a problem with it
                if ($fault->isa('SoapFault') && ref($fault->detail) eq 
'FileNotFound' && defined($source_file_info->{type}) && 
$source_file_info->{type} !~ /vmdisk/i) {
                        notify($ERRORS{'WARNING'}, 0, "failed to move virtual 
disk on VM host $vmhost_name, source file is either not a virtual disk file or 
there is a problem with its configuration, check the 'Extent description' 
section of the vmdk file: '$source_path'\nsource file info:\n" . 
format_data($source_file_info));
-            return;
                }
                elsif ($fault =~ /No space left/i) {
                        notify($ERRORS{'CRITICAL'}, 0, "failed to move virtual 
disk on VM host $vmhost_name, no space is left on the destination device: 
'$destination_path'\nerror:\n$fault");
-            return;
                }
-        elsif ($fault =~ /not implemented/i){
-            notify($ERRORS{'DEBUG'}, 0, "unable to move vmdk using 
MoveVirtualDisk function, VM host $vmhost_name does not implement the 
MoveVirtualDisk function");
-            $self->delete_file($destination_parent_directory_path);
-        }
+               elsif ($fault =~ /not implemented/i) {
+                       notify($ERRORS{'DEBUG'}, 0, "unable to move vmdk using 
MoveVirtualDisk function, VM host $vmhost_name does not implement the 
MoveVirtualDisk function");
+                       $self->delete_file($destination_parent_directory_path);
+               }
                elsif ($source_file_info) {
                        notify($ERRORS{'WARNING'}, 0, "failed to move virtual 
disk on VM host $vmhost_name:\n'$source_path' --> '$destination_path'\nsource 
file info:\n" . format_data($source_file_info) . "\n$fault");
-            return;
                }
                else {
                        notify($ERRORS{'WARNING'}, 0, "failed to move virtual 
disk on VM host $vmhost_name:\n'$source_path' --> '$destination_path'\nsource 
file info: unavailable\n$fault");
-            return;
                }
-               
-       } else {
-        notify($ERRORS{'OK'}, 0, "moved virtual disk on VM host 
$vmhost_name:\n'$source_path' --> '$destination_path'");
-        return 1;
-    }
-    
-    # This section should apply only to vCenter hosts, i.e. hosts for which the
-    # MoveVirtualDisk method is not implemented. Instead, use the 
copy_virtual_disk
-    # method (where the CloneVM method is used) and cleanup source files 
afterward. 
-    if($self->copy_virtual_disk($source_path, $destination_path)){
-        my $file_manager = $self->_get_file_manager_view() || return;
-        my $source_parent_directory_path = 
$self->_get_parent_directory_datastore_path($source_path) || return;
-        notify($ERRORS{'DEBUG'}, 0, "Removing source directory: 
$source_parent_directory_path");
-        $file_manager->DeleteDatastoreFile(
-                    name => $source_parent_directory_path,
-                    datacenter => $datacenter);
-        
-        notify($ERRORS{'OK'}, 0, "moved virtual disk on VM host 
$vmhost_name:\n'$source_path' --> '$destination_path'");
-        return 1; 
-    } else {
-        notify($ERRORS{'WARNING'}, 0, "Unable to move virtual disk from 
$vmhost_name: '$source_path' --> '$destination_path'");
-        return 0;
-    }
+               return;
+       }
+       else {
+               notify($ERRORS{'OK'}, 0, "moved virtual disk on VM host 
$vmhost_name:\n'$source_path' --> '$destination_path'");
+               return $destination_path;
+       }
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -1825,7 +1771,6 @@ sub copy_file_from {
 
 }
 
-
 #/////////////////////////////////////////////////////////////////////////////
 
 =head2 get_file_contents
@@ -2852,10 +2797,10 @@ sub _get_resource_pool_view {
                        $potential_matches{$resource_pool_path} = 
$resource_pool;
                }
                else {
-                       notify($ERRORS{'DEBUG'}, 0, "resource pool on VM host 
$vmhost_name does NOT match VM host profile resource path:\n" .
-                               "path on VM host: '$resource_pool_path'\n" .
-                               "VM profile path: 
'$vmhost_profile_resource_path'"
-                       );
+                       #notify($ERRORS{'DEBUG'}, 0, "resource pool on VM host 
$vmhost_name does NOT match VM host profile resource path:\n" .
+                       #       "path on VM host: '$resource_pool_path'\n" .
+                       #       "VM profile path: 
'$vmhost_profile_resource_path'"
+                       #);
                }
        }
        


Reply via email to