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