Author: arkurth
Date: Wed Apr 22 19:59:24 2015
New Revision: 1675483
URL: http://svn.apache.org/r1675483
Log:
VCL-844
Added subroutines to VMware.pm:
* get_vmx_url_base_directory_path
* get_vmx_intermediate_directory_path
* _get_datastore_url
* _get_url_path
* configure_vmhost_ssh_keys
* copy_vmhost_ssh_public_key_to_another_host
* copy_file_to_another_host
* setup_migrate_vm
* migrate_vm
* migrate_revert_source
Added subroutines to utils.pm:
* update_computer_vmhost_id.
* setup_get_hash_multiple_choice.
Updated Module.pm::new to call initialize on ManagementNode.pm objects even if
$SETUP_MODE is true.
Updated Module.pm::create_object to accept an additional argument which allows
arguments to be passed to the constructor of the object being created as well
as the DataStructure.pm object.
Updated Module.pm::create_vmhost_os_object to accept an argument specifying
which VM host to create an object for.
Updated DataStructure.pm to accept a vmhost_identifier argument rather than use
a vmhost_id argument.
Changed where cached data is stored from %ENV to $self in order to allow it to
work with multiple VMware.pm objects.
VCL-851
Added check to skip the attempt to use vSphere_SDK.pm if vmprofile.password is
not configured.
Modified:
vcl/trunk/managementnode/lib/VCL/DataStructure.pm
vcl/trunk/managementnode/lib/VCL/Module.pm
vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
vcl/trunk/managementnode/lib/VCL/utils.pm
Modified: vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1675483&r1=1675482&r2=1675483&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/DataStructure.pm Wed Apr 22 19:59:24 2015
@@ -579,14 +579,14 @@ my @blockrequest_data : Field : Arg('Nam
my @computer_identifier : Field : Arg('Name' => 'computer_identifier') :
Type(scalar) : Get('Name' => 'computer_identifier', 'Private' => 1);
-=head3 @vmhost_id
+=head3 @vmhost_identifier
Data type : array of scalars
Description :
=cut
-my @vmhost_id : Field : Arg('Name' => 'vmhost_id') : Type(scalar) : Get('Name'
=> 'vmhost_id', 'Private' => 1);
+my @vmhost_identifier : Field : Arg('Name' => 'vmhost_identifier') :
Type(scalar) : Get('Name' => 'vmhost_identifier', 'Private' => 1);
=head3 @image_identifier
@@ -658,7 +658,7 @@ sub _initialize : Init {
}
my $computer_identifier = $self->computer_identifier;
- my $vmhost_id = $self->vmhost_id;
+ my $vmhost_identifier = $self->vmhost_identifier;
my $image_identifier = $self->image_identifier;
my $imagerevision_identifier = $self->imagerevision_identifier;
@@ -677,15 +677,15 @@ sub _initialize : Init {
$self->request_data->{reservation}{$self->reservation_id}{computer} =
$computer_info;
}
- # Get the VM host info if the vmhost_id argument was specified and add
it to this object
- if ($vmhost_id) {
- notify($ERRORS{'DEBUG'}, 0, "VM host identifier argument was
specified, retrieving data for VM host: $vmhost_id");
- my $vmhost_info = get_vmhost_info($vmhost_id, 1);
+ # Get the VM host info if the $vmhost_identifier argument was specified
and add it to this object
+ if ($vmhost_identifier) {
+ notify($ERRORS{'DEBUG'}, 0, "VM host identifier argument was
specified, retrieving data for VM host: $vmhost_identifier");
+ my $vmhost_info = get_vmhost_info($vmhost_identifier, 1);
if (!$vmhost_info) {
- notify($ERRORS{'WARNING'}, 0, "DataStructure object
could not be initialized, failed to retrieve data for VM host: $vmhost_id");
+ notify($ERRORS{'WARNING'}, 0, "DataStructure object
could not be initialized, failed to retrieve data for VM host:
$vmhost_identifier");
# Throw an exception because simply returning undefined
(return;) does not result in this DataStructure object being undefined
- Exception::Class::Base->throw( error => "DataStructure
object could not be initialized, failed to retrieve data for VM host:
$vmhost_id");
+ Exception::Class::Base->throw( error => "DataStructure
object could not be initialized, failed to retrieve data for VM host:
$vmhost_identifier");
return;
}
$self->request_data->{reservation}{$self->reservation_id}{computer}{vmhost} =
$vmhost_info;
Modified: vcl/trunk/managementnode/lib/VCL/Module.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module.pm?rev=1675483&r1=1675482&r2=1675483&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module.pm Wed Apr 22 19:59:24 2015
@@ -178,26 +178,28 @@ sub new {
# Get the memory address of this newly created object - useful for
debugging object creation problems
my $address = sprintf('%x', $self);
+ my $type = ref($self);
+
# Display a message based on the type of object created
if ($self->isa('VCL::Module::State')) {
my $request_state_name = $self->data->get_request_state_name(0)
|| '<not set>';
- notify($ERRORS{'DEBUG'}, 0, ref($self) . " object created for
state $request_state_name, address: $address");
+ notify($ERRORS{'DEBUG'}, 0, "$type object created for state
$request_state_name, address: $address");
}
elsif ($self->isa('VCL::Module::OS') &&
!$self->isa('VCL::Module::OS::Linux::ManagementNode')) {
my $image_name = $self->data->get_image_name(0) || '<not set>';
- notify($ERRORS{'DEBUG'}, 0, ref($self) . " object created for
image $image_name, address: $address");
+ notify($ERRORS{'DEBUG'}, 0, "$type object created for image
$image_name, address: $address");
}
elsif ($self->isa('VCL::Module::Provisioning')) {
my $computer_name = $self->data->get_computer_short_name(0) ||
'<not set>';
- notify($ERRORS{'DEBUG'}, 0, ref($self) . " object created for
computer $computer_name, address: $address");
+ notify($ERRORS{'DEBUG'}, 0, "$type object created for computer
$computer_name, address: $address");
}
else {
- notify($ERRORS{'DEBUG'}, 0, ref($self) . " object created,
address: $address");
+ notify($ERRORS{'DEBUG'}, 0, "$type object created, address:
$address");
}
# Create a management node OS object
# Check to make sure the object currently being created is not a MN OS
object to avoid endless loop
- if (!$self->isa('VCL::Module::OS::Linux::ManagementNode')) {
+ if (!$self->isa('VCL::Module::OS::Linux::ManagementNode') &&
!$self->isa('VCL::Module::State')) {
my $mn_os;
# Check if the mn_os argument was provided
if ($args->{mn_os}) {
@@ -221,10 +223,15 @@ sub new {
}
# Check if not running in setup mode and if initialize() subroutine is
defined for this module
- if (!$SETUP_MODE && $self->can("initialize")) {
- # Call the initialize() subroutine, if it returns 0, return 0
- # If it doesn't return 0, return the object reference
- return if (!$self->initialize($args));
+ if (!$SETUP_MODE ||
$self->isa('VCL::Module::OS::Linux::ManagementNode')) {
+ if ($self->can("initialize")) {
+ # Call the initialize() subroutine, if it returns 0,
return 0
+ # If it doesn't return 0, return the object reference
+ return if (!$self->initialize($args));
+ }
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "initialize not called for $type
object ($address) because \$SETUP_MODE is true");
}
return $self;
@@ -289,7 +296,7 @@ sub create_datastructure_object {
=head2 create_object
- Parameters : $perl_package, $data_structure_arguments (optional)
+ Parameters : $perl_package, $data_structure_arguments (optional),
$object_argument_hashref (optional)
Returns : VCL::Module object reference
Description : This is a general constructor to create VCL::Module objects. It
contains the code to call 'use $perl_package', instantiate an
@@ -321,8 +328,14 @@ sub create_object {
my $data;
my $data_structure_arguments = shift;
if ($data_structure_arguments) {
- notify($ERRORS{'DEBUG'}, 0, "new DataStructure object will be
created for the $perl_package object, data structure arguments passed:\n" .
format_data($data_structure_arguments));
- $data = create_datastructure_object($data_structure_arguments);
+ if (ref($data_structure_arguments) &&
ref($data_structure_arguments) =~ /DataStructure/) {
+ notify($ERRORS{'DEBUG'}, 0, "DataStructure object
argument will be passed to the new $perl_package object");
+ $data = $data_structure_arguments;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "new DataStructure object
will be created for the $perl_package object, data structure arguments
passed:\n" . format_data($data_structure_arguments));
+ $data =
create_datastructure_object($data_structure_arguments);
+ }
}
elsif (!$self) {
notify($ERRORS{'DEBUG'}, 0, "new DataStructure object will be
created for the $perl_package object, data structure arguments not passed and
not called as an object reference");
@@ -332,6 +345,20 @@ sub create_object {
notify($ERRORS{'DEBUG'}, 0, "existing DataStructure object will
be passed to the new $perl_package object");
$data = $self->data;
}
+
+ my $object_argument_hashref = shift;
+ if ($object_argument_hashref) {
+ my $type = ref($object_argument_hashref);
+ if (!$type) {
+ notify($ERRORS{'WARNING'}, 0, "3rd argument is not a
reference, it must be a hash reference: $object_argument_hashref");
+ return;
+ }
+ elsif ($type ne 'HASH') {
+ notify($ERRORS{'WARNING'}, 0, "3rd argument is a $type
reference, it must be a hash reference");
+ return;
+ }
+ }
+ $object_argument_hashref->{data_structure} = $data;
# Attempt to load the module
eval "use $perl_package";
@@ -344,7 +371,7 @@ sub create_object {
# Attempt to create the object
my $object;
eval {
- $object = ($perl_package)->new({data_structure => $data})
+ $object = ($perl_package)->new($object_argument_hashref)
};
if ($EVAL_ERROR) {
@@ -500,7 +527,7 @@ sub create_mn_os_object {
=head2 create_vmhost_os_object
- Parameters : none
+ Parameters : $vmhost_identifier (optional)
Returns : boolean
Description : Creates an OS object for the VM host.
@@ -513,9 +540,15 @@ sub create_vmhost_os_object {
return;
}
- # Check if an OS object has already been stored in the calling object
- if (my $vmhost_os = $self->vmhost_os(0)) {
- return $vmhost_os;
+ my $vmhost_identifier = shift;
+
+ if (!$vmhost_identifier) {
+ # Check if an OS object has already been stored in the calling
object
+ if (my $vmhost_os = $self->vmhost_os(0)) {
+ my $address = sprintf('%x', $vmhost_os);
+ notify($ERRORS{'DEBUG'}, 0, "returning existing VM host
OS object ($address)");
+ return $vmhost_os;
+ }
}
# Make sure calling object isn't an OS module to avoid an infinite loop
@@ -526,20 +559,56 @@ sub create_vmhost_os_object {
my $request_data = $self->data->get_request_data();
my $reservation_id = $self->data->get_reservation_id();
- my $vmhost_computer_id = $self->data->get_vmhost_computer_id();
- my $vmhost_hostname = $self->data->get_vmhost_hostname();
- my $vmhost_profile_image_id =
$self->data->get_vmhost_profile_image_id();
+
+ my $vmhost_computer_id;
+ my $vmhost_hostname;
+ my $vmhost_profile_image_id;
+ if ($vmhost_identifier) {
+ my $vmhost_info = get_vmhost_info($vmhost_identifier);
+ if (!$vmhost_info) {
+ notify($ERRORS{'WARNING'}, 0, "unable to create VM host
OS object for host specified by argument: $vmhost_identifier, VM host info
could not be retrieved");
+ return;
+ }
+
+ $vmhost_computer_id = $vmhost_info->{computerid};
+ if (!$vmhost_computer_id) {
+ notify($ERRORS{'WARNING'}, 0, "unable to create VM host
OS object for host specified by argument: $vmhost_identifier, VM host computer
ID could not be determined from VM host info:\n" . format_data($vmhost_info));
+ return;
+ }
+
+ $vmhost_hostname = $vmhost_info->{computer}{hostname};
+ if (!$vmhost_hostname) {
+ notify($ERRORS{'WARNING'}, 0, "unable to create VM host
OS object for host specified by argument: $vmhost_identifier, VM host computer
hostname could not be determined from VM host info:\n" .
format_data($vmhost_info));
+ return;
+ }
+
+ $vmhost_profile_image_id = $vmhost_info->{vmprofile}{imageid};
+ if (!$vmhost_profile_image_id) {
+ notify($ERRORS{'WARNING'}, 0, "unable to create VM host
OS object for host specified by argument: $vmhost_identifier, VM host profile
image ID could not be determined from VM host info:\n" .
format_data($vmhost_info));
+ return;
+ }
+ }
+ else {
+ # Argument was not supplied, use reservation data
+ $vmhost_computer_id = $self->data->get_vmhost_computer_id();
+ $vmhost_hostname = $self->data->get_vmhost_hostname();
+ $vmhost_profile_image_id =
$self->data->get_vmhost_profile_image_id();
+ if (!$vmhost_computer_id || !$vmhost_hostname ||
!defined($vmhost_profile_image_id)) {
+ notify($ERRORS{'WARNING'}, 0, "unable to create VM host
OS object, VM host computer ID, hostname, and profile image ID could not be
determined from reservation data");
+ return;
+ }
+ }
# Create a DataStructure object containing computer data for the VM host
my $vmhost_data;
eval {
$vmhost_data = new VCL::DataStructure({
-
request_data => $request_data,
-
reservation_id => $reservation_id,
-
computer_identifier =>
$vmhost_computer_id,
-
image_identifier =>
$vmhost_profile_image_id
-
}
-
);
+ request_data => $request_data,
+ reservation_id => $reservation_id,
+ computer_identifier => $vmhost_computer_id,
+ image_identifier => $vmhost_profile_image_id
+ }
+ );
};
if ($EVAL_ERROR) {
Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm?rev=1675483&r1=1675482&r2=1675483&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm Wed
Apr 22 19:59:24 2015
@@ -1068,7 +1068,7 @@ sub get_registered_vms {
}
# Get the vmx path values for each VM
- my @vmx_paths = values(%$vm_list);
+ my @vmx_paths = sort { lc($a) cmp lc($b) } values(%$vm_list);
notify($ERRORS{'DEBUG'}, 0, "found " . scalar(@vmx_paths) . "
registered VMs");
return @vmx_paths;
@@ -1302,7 +1302,7 @@ sub vm_power_off {
Parameters : $vmx_file_path
Returns : boolean
- Description : Powers off the VM indicated by the vmx file path argument.
+ Description : Suspends the VM indicated by the vmx file path argument.
=cut
@@ -1340,6 +1340,8 @@ sub vm_suspend {
return;
}
+ notify($ERRORS{'DEBUG'}, 0, "suspending VM: $vmx_file_path ($vm_id)");
+ my $start_time = time;
my $vim_cmd_arguments = "vmsvc/power.suspend $vm_id";
my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments,
400);
return if !$output;
@@ -1365,7 +1367,8 @@ sub vm_suspend {
# Wait for the task to complete
if ($self->_wait_for_task($task_ids[0])) {
- notify($ERRORS{'OK'}, 0, "suspended VM: $vmx_file_path");
+ my $duration = (time - $start_time);
+ notify($ERRORS{'OK'}, 0, "suspended VM: $vmx_file_path, took
$duration seconds");
return 1;
}
else {
@@ -2702,9 +2705,17 @@ sub _parse_vim_cmd_output {
# Remove trailing newlines
$line =~ s/\n+$//g;
- # Remove class names at beginning of line surrounded by
parenthesis
+ # Remove class names in parenthesis from beginning class name
of indented lines
+ # ' (vim.vm.device.xxx) {' --> ' {'
+ $line =~ s/^(\s+)\([^\)]*\)\s*/$1/g;
+
+ # Remove class names at beginning of a line surrounded by
parenthesis
# '(vim.vm.device.VirtualPointingDevice) {' --> '{'
- $line =~ s/^(\s*)\([^\)]*\)\s*/$1/g;
+ $line =~ s/^\(([^\)]+)\)\s*{/'$1' => {/gx;
+
+ # Add comma to lines containing a closing curly bracket
+ # ' }' --> ' },'
+ $line =~ s/^(\s*)}\s*$/$1},/g;
# Remove class names after an equals sign
# 'backing = (vim.vm.device.VirtualDevice.BackingInfo) null,'
--> 'backing = null'
@@ -2729,6 +2740,9 @@ sub _parse_vim_cmd_output {
$numbered_statement .= "$line_number:$line\n";
}
+ # Enclose the entire statement in curly brackets
+ $statement = "{\n$statement\n}";
+
# The statement variable should contain a valid definition
my $result = eval($statement);
if ($EVAL_ERROR) {
@@ -2743,6 +2757,169 @@ sub _parse_vim_cmd_output {
#/////////////////////////////////////////////////////////////////////////////
+=head2 _get_vm_virtual_disk_file_layout
+
+ Parameters : $vmx_file_path
+ Returns : hash reference
+ Description : Retrieves a VM's virtual disk file layout as reported by:
+ vim-cmd vmsvc/get.filelayout <VM ID>
+ A hash reference is returned:
+ {
+ "vim.vm.FileInfo" => {
+ "dynamicType" => "<unset>",
+ "ftMetadataDirectory" => "<unset>",
+ "logDirectory" => "[blade1e1-10-vmpath] arkvmm160_3868-v0",
+ "snapshotDirectory" => "[blade1e1-10-vmpath]
arkvmm160_3868-v0",
+ "suspendDirectory" => "[blade1e1-10-vmpath]
arkvmm160_3868-v0",
+ "vmPathName" => "[blade1e1-10-vmpath]
arkvmm160_3868-v0/arkvmm160_3868-v0.vmx"
+ },
+ "vim.vm.FileLayout" => {
+ "configFile" => [
+ "arkvmm160_3868-v0.vmxf",
+ "nvram",
+ "arkvmm160_3868-v0.vmsd"
+ ],
+ "disk" => [
+ {
+ "diskFile" => [
+ "[datastore-compressed]
vmwarewinxp-xpsp33868-v0/vmwarewinxp-xpsp33868-v0.vmdk",
+ "[blade1e1-10-vmpath]
arkvmm160_3868-v0/vmwarewinxp-xpsp33868-v0-000001.vmdk"
+ ],
+ "dynamicType" => "<unset>",
+ "key" => 3000
+ },
+ {
+ "diskFile" => [
+ "[blade1e1-10-vmpath]
arkvmm160_3868-v0/arkvmm160_3868-v0.vmdk"
+ ],
+ "dynamicType" => "<unset>",
+ "key" => 2000
+ }
+ ],
+ "dynamicType" => "<unset>",
+ "logFile" => [
+ "vmware-1.log",
+ "vmware-2.log",
+ "vmware-3.log",
+ "vmware.log"
+ ],
+ "snapshot" => [
+ {
+ "dynamicType" => "<unset>",
+ "key" => "'vim.vm.Snapshot:576-snapshot-1'",
+ "snapshotFile" => [
+ "[blade1e1-10-vmpath]
arkvmm160_3868-v0/arkvmm160_3868-v0-Snapshot1.vmsn",
+ "[datastore-compressed]
vmwarewinxp-xpsp33868-v0/vmwarewinxp-xpsp33868-v0.vmdk"
+ ]
+ }
+ ],
+ "swapFile" => "<unset>"
+ }
+ }
+
+=cut
+
+sub _get_vm_virtual_disk_file_layout {
+ 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 $vmx_file_path = shift;
+ if (!$vmx_file_path) {
+ notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not
specified");
+ return;
+ }
+
+ # Get the VM ID
+ my $vm_id = $self->_get_vm_id($vmx_file_path);
+ if (!defined($vm_id)) {
+ notify($ERRORS{'WARNING'}, 0, "unable to power off VM because
VM ID could not be determined");
+ return;
+ }
+
+ my $vim_cmd_arguments = "vmsvc/get.filelayout $vm_id";
+ my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
+ return if !$output;
+
+ my $virtual_disk_file_layout = $self->_parse_vim_cmd_output($output);
+ if ($virtual_disk_file_layout) {
+ notify($ERRORS{'DEBUG'}, 0, "retrieved virtual disk file layout
for VM $vm_id ($vmx_file_path)\n" . format_data($virtual_disk_file_layout));
+ return $virtual_disk_file_layout;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to retrieve virtual disk
file layout for VM $vm_id ($vmx_file_path)");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_vm_virtual_disk_file_paths
+
+ Parameters : $vmx_file_path
+ Returns : array reference
+ Description : Retrieves a VM's virtual disk file layout and returns an array
+ reference. Each top-level array element represent entire virtual
+ disk and contains an array reference containing the virtual
+ disk's files:
+ [
+ [
+
"/vmfs/volumes/datastore/vmwarewin7-bare3844-v1/vmwarewin7-bare3844-v1.vmdk",
+
"/vmfs/volumes/blade-vmpath/vm170_3844-v1/vmwarewin7-bare3844-v1-000001.vmdk",
+
"/vmfs/volumes/blade-vmpath/vm170_3844-v1/vmwarewin7-bare3844-v1-000002.vmdk",
+
"/vmfs/volumes/blade-vmpath/vm170_3844-v1/vmwarewin7-bare3844-v1-000003.vmdk"
+ ],
+ [
+
"/vmfs/volumes/blade-vmpath/vm170_3844-v1/vm170_3844-v1.vmdk"
+ ]
+ ]
+
+=cut
+
+sub get_vm_virtual_disk_file_paths {
+ 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 $vmx_file_path = shift;
+ if (!$vmx_file_path) {
+ notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not
specified");
+ return;
+ }
+
+ my $virtual_disk_file_layout =
$self->_get_vm_virtual_disk_file_layout($vmx_file_path) || return;
+
+ my $virtual_disk_array_ref =
$virtual_disk_file_layout->{'vim.vm.FileLayout'}{'disk'};
+ if (!$virtual_disk_array_ref) {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine virtual disk
file paths, failed to retrieve {'vim.vm.FileLayout'}{'disk'} array reference
from virtual disk file layout:\n" . format_data($virtual_disk_file_layout));
+ return;
+ }
+ elsif (!ref($virtual_disk_array_ref) || ref($virtual_disk_array_ref) ne
'ARRAY') {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine virtual disk
file paths, virtual disk file layout {'vim.vm.FileLayout'}{'disk'} key does not
contain an array reference:\n" . format_data($virtual_disk_array_ref));
+ return;
+ }
+
+ my @virtual_disks;
+ for my $virtual_disk_ref (@$virtual_disk_array_ref) {
+ my $disk_file_array_ref = $virtual_disk_ref->{'diskFile'};
+ my @virtual_disk_file_paths;
+ for my $virtual_disk_file_path (@$disk_file_array_ref) {
+ push @virtual_disk_file_paths,
$self->_get_normal_path($virtual_disk_file_path);
+ }
+ push @virtual_disks, \@virtual_disk_file_paths;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "retrieved virtual disk file paths for
$vmx_file_path:\n" . format_data(\@virtual_disks));
+ return @virtual_disks;
+}
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 DESTROY
Parameters : none