You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2013/06/04 19:54:13 UTC

svn commit: r1489534 - in /vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware: VMware.pm vSphere_SDK.pm

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'"
+			#);
 		}
 	}