Author: arkurth
Date: Thu Aug  4 17:02:25 2011
New Revision: 1153929

URL: http://svn.apache.org/viewvc?rev=1153929&view=rev
Log:
VCL-470
Added code contributed by Aaron Coburn included in the Jira issue to add a 
vSphere_SDK.pm::get_total_space subroutine.

VCL-471
Updated VMware.pm::_get_parent_directory_normal_path() to allow non-datastore 
paths to be specified. This solves a problem where a path residing on the 
management node is passed, but the subroutine fails.

VCL-450
Fixed a problem where vSphere_SDK.pm::copy_virtual_disk failed because the vmdk 
adapter type is not listed in the typical info if a snapshot has been created.

Updated vSphere.pm to cache most of the SDK object types it uses including 
host, vm, datastore. This prevents the code from having to fetch a new object 
every time, greatly increasing speed. This also reduced a lot of duplicated 
code.

Fixed problem in VMware.pm::node_status. It was not accounting for VMs loaded 
before the snapshot functionality was added which were using nonpersistent mode.


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

Modified: 
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm?rev=1153929&r1=1153928&r2=1153929&view=diff
==============================================================================
--- 
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm 
(original)
+++ 
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm 
Thu Aug  4 17:02:25 2011
@@ -1008,6 +1008,7 @@ sub node_status {
        my $reservation_id = $self->data->get_reservation_id();
        my $computer_name = $self->data->get_computer_node_name();
        my $image_name = $self->data->get_image_name();
+       my $request_forimaging = $self->data->get_request_forimaging();
        
        notify($ERRORS{'DEBUG'}, 0, "attempting to check the status of computer 
$computer_name, image: $image_name");
        
@@ -1068,7 +1069,8 @@ sub node_status {
        }
        
        # If the VM is dedicated, check if the vmdk of the VM already loaded is 
shared or dedicated
-       if ($self->is_vm_dedicated()) {
+       my $is_vm_dedicated = $self->is_vm_dedicated();
+       if ($request_forimaging || $is_vm_dedicated) {
                # Determine the vmx file path actively being used by the VM
                my $vmx_file_path = $self->get_active_vmx_file_path();
                if (!$vmx_file_path) {
@@ -1102,7 +1104,6 @@ sub node_status {
                        notify($ERRORS{'WARNING'}, 0, "vmdk file path was not 
found in the vmx file info, returning 'RELOAD':\n" . format_data($vmx_info));
                        return $status;
                }
-               notify($ERRORS{'DEBUG'}, 0, "vmdk file path used by the VM 
already loaded: $vmdk_file_path");
                
                # Get the vmdk mode from the vmx information and make sure it 
is not nonpersistent
                my $vmdk_mode = $vmx_info->{vmdk}{$vmdk_identifiers[0]}{mode};
@@ -1111,17 +1112,22 @@ sub node_status {
                        return $status;
                }
                
+               notify($ERRORS{'DEBUG'}, 0, "vmdk file path used by the VM 
already loaded: $vmdk_file_path, mode: $vmdk_mode");
+               
+               # Can't use if nonpersistent
                if ($vmdk_mode =~ /nonpersistent/i) {
                        notify($ERRORS{'OK'}, 0, "VM already loaded may NOT be 
used, vmdk mode: '$vmdk_mode', returning 'RELOAD'");
                        return $status;
                }
                
-               if ($self->is_vmdk_shared($vmdk_file_path)) {
-                       notify($ERRORS{'OK'}, 0, "VM already loaded may NOT be 
used, the vmdk appears to be shared");
-                       return $status;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "VM already loaded may be 
used, the vmdk does NOT appear to be shared");
+               if ($is_vm_dedicated) {
+                       if ($self->is_vmdk_shared($vmdk_file_path)) {
+                               notify($ERRORS{'OK'}, 0, "VM already loaded may 
NOT be used, the vmdk appears to be shared");
+                               return $status;
+                       }
+                       else {
+                               notify($ERRORS{'DEBUG'}, 0, "VM already loaded 
may be used, the vmdk does NOT appear to be shared");
+                       }
                }
        }
        
@@ -3082,9 +3088,9 @@ sub get_reference_vmx_file_path {
        
        return $ENV{reference_vmx_file_path} if 
defined($ENV{reference_vmx_file_path});
        
-       my $vmdk_directory_path = $self->get_vmdk_directory_path();
-       if (!$vmdk_directory_path) {
-               notify($ERRORS{'WARNING'}, 0, "unable to construct reference 
vmx file path, vmdk directory path could not be determined");
+       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;
        }
        
@@ -3094,7 +3100,7 @@ sub get_reference_vmx_file_path {
                return;
        }
        
-       $ENV{reference_vmx_file_path} = 
"$vmdk_directory_path/$reference_vmx_file_name";
+       $ENV{reference_vmx_file_path} = 
"$vmdk_directory_path_shared/$reference_vmx_file_name";
        notify($ERRORS{'DEBUG'}, 0, "determined reference vmx file path: 
$ENV{reference_vmx_file_path}");
        return $ENV{reference_vmx_file_path};
 }
@@ -6019,7 +6025,7 @@ sub get_datastore_info {
                return;
        }
        else {
-               notify($ERRORS{'DEBUG'}, 0, "retrieved datastore info from VM 
host:\n" . join("\n", sort keys(%$datastore_info)));
+               notify($ERRORS{'DEBUG'}, 0, "retrieved datastore info from VM 
host:\n" . join(", ", sort keys(%$datastore_info)));
                $self->{datastore_info} = $datastore_info;
                return $datastore_info;
        }
@@ -6366,6 +6372,13 @@ sub _get_parent_directory_normal_path {
                return;
        }
        
+       # If this is a normal path - remove the part after the last '/'
+       if ($path_argument !~ /\[.+\]/) {
+               $path_argument =~ s/[^\/]*\/?$//g;
+               return $self->_get_normal_path($path_argument);
+       }
+       
+       # Datastore path was passed, call datastore sub and return normal path
        my $parent_directory_datastore_path = 
$self->_get_parent_directory_datastore_path($path_argument);
        if (!$parent_directory_datastore_path) {
                notify($ERRORS{'WARNING'}, 0, "unable to determine parent 
directory normal path, parent directory datastore path could not be determined 
on which the normal path is based: '$path_argument'");

Modified: 
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm?rev=1153929&r1=1153928&r2=1153929&view=diff
==============================================================================
--- 
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm
 (original)
+++ 
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm
 Thu Aug  4 17:02:25 2011
@@ -122,12 +122,12 @@ sub vm_register {
        # Get the vmx path argument and convert it to a datastore path
        my $vmx_path = $self->_get_datastore_path(shift) || return;
        
-       my $host_view = VIExt::get_host_view(1) || return;
-       my $datacenter = Vim::find_entity_view (view_type => 'Datacenter') || 
return;
+       my $host_view = $self->_get_host_view() || return;
+       my $datacenter = $self->_get_datacenter_view() || return;
        my $vm_folder = Vim::get_view(mo_ref => $datacenter->{vmFolder}) || 
return;
    my $resource_pool = Vim::find_entity_view(view_type => 'ResourcePool') || 
return;
    
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
        
        my $vm_mo_ref;
@@ -181,12 +181,7 @@ sub vm_unregister {
        # Override the die handler
        local $SIG{__DIE__} = sub{};
        
-   my $vm;
-       eval { $vm = Vim::find_entity_view(view_type => 'VirtualMachine', 
filter => {'config.files.vmPathName' => $vmx_path}); };
-       if (!$vm) {
-               notify($ERRORS{'DEBUG'}, 0, "VM is not registered: $vmx_path");
-               return 1;
-   }
+   my $vm = $self->_get_vm_view($vmx_path) || return;
        
        # Make sure the VM is powered off or unregister will fail
        $self->vm_power_off($vmx_path) || return;
@@ -197,6 +192,9 @@ sub vm_unregister {
                return;
        }
        
+       # Delete the cached VM object
+       delete $self->{vm_view_objects}{$vmx_path};
+       
        notify($ERRORS{'DEBUG'}, 0, "unregistered VM: $vmx_path");
        return 1;
 }
@@ -226,12 +224,7 @@ sub vm_power_on {
        # Override the die handler
        local $SIG{__DIE__} = sub{};
        
-       my $vm;
-       eval { $vm = Vim::find_entity_view(view_type => 'VirtualMachine', 
filter => {'config.files.vmPathName' => $vmx_path}); };
-       if (!$vm) {
-               notify($ERRORS{'WARNING'}, 0, "unable to power on VM because it 
is not registered: $vmx_path");
-               return;
-   }
+       my $vm = $self->_get_vm_view($vmx_path) || return;
        
        eval { $vm->PowerOnVM(); };
        if ($@) {
@@ -273,15 +266,10 @@ sub vm_power_off {
        # Get the vmx path argument and convert it to a datastore path
        my $vmx_path = $self->_get_datastore_path(shift) || return;
        
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
        
-       my $vm;
-       eval { $vm = Vim::find_entity_view(view_type => 'VirtualMachine', 
filter => {'config.files.vmPathName' => $vmx_path}); };
-       if (!$vm) {
-               notify($ERRORS{'WARNING'}, 0, "unable to power off VM because 
it is not registered: $vmx_path");
-               return;
-   }
+       my $vm = $self->_get_vm_view($vmx_path) || return;
        
        eval { $vm->PowerOffVM(); };
        if ($@) {
@@ -326,15 +314,10 @@ sub get_vm_power_state {
        # Get the vmx path argument and convert it to a datastore path
        my $vmx_path = $self->_get_datastore_path(shift) || return;
        
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
        
-       my $vm;
-       eval { $vm = Vim::find_entity_view(view_type => 'VirtualMachine', 
filter => {'config.files.vmPathName' => $vmx_path}); };
-       if (!$vm) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve power state 
of VM because it is not registered: $vmx_path");
-               return;
-   }
+       my $vm = $self->_get_vm_view($vmx_path) || return;
        
        my $power_state = $vm->runtime->powerState->val;
        
@@ -457,40 +440,28 @@ sub copy_virtual_disk {
                return;
        }
        
-       my $destination_adapter_type = shift;
+       my $adapter_type = shift;
        
        # If the adapter type was not specified, retrieve it from the source 
vmdk file
-       if (!$destination_adapter_type) {
-               $destination_adapter_type = 
$self->get_virtual_disk_controller_type($source_path);
-               if (!$destination_adapter_type) {
-                       notify($ERRORS{'WARNING'}, 0, "destination adapter type 
argument was not specifed and unable to retrieve adapter type from source vmdk 
file: $source_path, using lsiLogic");
-                       $destination_adapter_type = 'lsiLogic';
+       if (!$adapter_type) {
+               $adapter_type = $self->get_vm_disk_adapter_type($source_path);
+               if (!$adapter_type) {
+                       notify($ERRORS{'WARNING'}, 0, "adapter type argument 
was not specifed and unable to retrieve adapter type from source vmdk file: 
$source_path, using lsiLogic");
+                       $adapter_type = 'lsiLogic';
                }
        }
        
-       # Check the adapter type argument, the string must match exactly or the 
copy will fail
-       my @valid_adapter_types = qw( busLogic lsiLogic ide );
-       if (!grep(/^$destination_adapter_type$/, @valid_adapter_types)) {
-               notify($ERRORS{'WARNING'}, 0, "adapter type argument is not 
valid: '$destination_adapter_type', it must exactly match (case sensitive) one 
of the following strings:\n" . join("\n", @valid_adapter_types));
-               return;
-       }
-       
        my $vmhost_name = $self->data->get_vmhost_hostname();
        
        # Get a virtual disk manager object
-       my $service_content = Vim::get_service_content() || return;
-       if (!$service_content->{virtualDiskManager}) {
-               notify($ERRORS{'WARNING'}, 0, "unable to copy virtual disk on 
VM host $vmhost_name, virtual disk manager is not available through the vSphere 
SDK");
-               return;
-       }
-       my $virtual_disk_manager = Vim::get_view(mo_ref => 
$service_content->{virtualDiskManager}) || return;
+       my $virtual_disk_manager = $self->_get_virtual_disk_manager_view() || 
return;
        
        # Get the destination partent directory path and create the directory
        my $destination_directory_path = 
$self->_get_parent_directory_datastore_path($destination_path) || return;
        $self->create_directory($destination_directory_path) || return;
        
        # Create a virtual disk spec object
-       my $virtual_disk_spec = VirtualDiskSpec->new(adapterType => 
$destination_adapter_type,
+       my $virtual_disk_spec = VirtualDiskSpec->new(adapterType => 
$adapter_type,
                                                                                
                                                diskType => 
$destination_disk_type,
        );
        
@@ -500,10 +471,9 @@ sub copy_virtual_disk {
        my @file_names = keys(%{$source_info});
        my $info_file_name = $file_names[0];
        
-       my $source_adapter_type = 
$source_info->{$info_file_name}{controllerType};
-       my $source_disk_type = $source_info->{$info_file_name}{diskType};
-       my $source_file_size_bytes = $source_info->{$info_file_name}{fileSize};
-       if ($source_adapter_type !~ /\w/ || $source_disk_type !~ /\w/ || 
$source_file_size_bytes !~ /\d/) {
+       my $source_disk_type = $source_info->{$info_file_name}{diskType} || 
'unknown';
+       my $source_file_size_bytes = $source_info->{$info_file_name}{fileSize} 
|| 'unknown';
+       if ($adapter_type !~ /\w/ || $source_disk_type !~ /\w/ || 
$source_file_size_bytes !~ /\d/) {
                notify($ERRORS{'WARNING'}, 0, "unable to retrieve adapter type, 
disk type, and file size of source file on VM host $vmhost_name: 
'$source_path', file info:\n" . format_data($source_info));
                return;
        }
@@ -513,7 +483,7 @@ sub copy_virtual_disk {
        
        # Attempt to copy the file
        notify($ERRORS{'DEBUG'}, 0, "attempting to copy file on VM host 
$vmhost_name: '$source_path' --> '$destination_path'
-                        adapter type: $source_adapter_type --> 
$destination_adapter_type
+                        adapter type: $adapter_type
                         disk type: $source_disk_type --> $destination_disk_type
                         source file size: " . 
format_number($source_file_size_bytes));
        
@@ -590,27 +560,10 @@ sub move_virtual_disk {
        $self->create_directory($destination_parent_directory_path) || return;
        
        # Check if a virtual disk manager object is available
-       my $service_content = Vim::get_service_content() || return;
-       
-       # Check if the virtual disk manager is available
-       if (!$service_content->{virtualDiskManager}) {
-               notify($ERRORS{'OK'}, 0, "unable to move virtual disk using 
vSphere SDK because virtual disk manager object is not available on VM host 
$vmhost_name");
-               return 0;
-       }
-       
-       # Create a virtual disk manager object
-       my $virtual_disk_manager = Vim::get_view(mo_ref => 
$service_content->{virtualDiskManager});
-       if (!$virtual_disk_manager) {
-               notify($ERRORS{'WARNING'}, 0, "failed to create vSphere SDK 
virtual disk manager object on VM host $vmhost_name");
-               return;
-       }
+       my $virtual_disk_manager = $self->_get_virtual_disk_manager_view() || 
return;
        
        # Create a datacenter object
-       my $datacenter = Vim::find_entity_view(view_type => 'Datacenter');
-       if (!$datacenter) {
-               notify($ERRORS{'WARNING'}, 0, "failed to create vSphere SDK 
datacenter object on VM host $vmhost_name");
-               return;
-       }
+       my $datacenter = $self->_get_datacenter_view() || return;
        
        # Override the die handler
        local $SIG{__DIE__} = sub{};
@@ -835,7 +788,7 @@ sub get_virtual_disk_controller_type {
        
        # Check if the controllerType key exists in the vmdk file info
        if (!defined($vmdk_file_info->{controllerType}) || 
!$vmdk_file_info->{controllerType}) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve 
controllerType value from file info: $vmdk_file_path\n" . 
format_data($vmdk_file_info));
+               notify($ERRORS{'DEBUG'}, 0, "unable to retrieve controllerType 
value from file info: $vmdk_file_path\n" . format_data($vmdk_file_info));
                return;
        }
        
@@ -980,7 +933,7 @@ sub get_vmware_product_name {
        my $vmhost_hostname = $self->data->get_vmhost_hostname();
        
        # Get the host view
-       my $host_view = VIExt::get_host_view(1);
+       my $host_view = $self->_get_host_view();
        my $product_name = $host_view->config->product->fullName;
        
        if ($product_name) {
@@ -1017,7 +970,7 @@ sub get_vmware_product_version {
        my $vmhost_hostname = $self->data->get_vmhost_hostname();
        
        # Get the host view
-       my $host_view = VIExt::get_host_view(1);
+       my $host_view = $self->_get_host_view();
        my $product_version = $host_view->config->product->version;
        
        if ($product_version) {
@@ -1049,7 +1002,7 @@ sub get_network_names {
        }
        
        # Get the host view
-       my $host_view = VIExt::get_host_view(1);
+       my $host_view = $self->_get_host_view();
        
        # Retrieve the network info, check if each network is accessible
        my @network_names;
@@ -1160,8 +1113,7 @@ sub create_directory {
        my $vmhost_hostname = $self->data->get_vmhost_hostname();
        
        # Get a fileManager object
-       my $service_content = Vim::get_service_content() || return;
-       my $file_manager = Vim::get_view(mo_ref => 
$service_content->{fileManager}) || return;
+       my $file_manager = $self->_get_file_manager_view() || return;
        
        # Override the die handler because MakeDirectory may call it
        local $SIG{__DIE__} = sub{};
@@ -1226,10 +1178,9 @@ sub delete_file {
        }
        
        # Get a fileManager object
-       my $service_content = Vim::get_service_content() || return;
-       my $file_manager = Vim::get_view(mo_ref => 
$service_content->{fileManager}) || return;
+       my $file_manager = $self->_get_file_manager_view() || return;
        
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
 
        # Attempt to delete the file
@@ -1282,11 +1233,10 @@ sub copy_file {
        $self->create_directory($destination_directory_path) || return;
        
        # Get a fileManager object
-       my $service_content = Vim::get_service_content() || return;
-       my $file_manager = Vim::get_view(mo_ref => 
$service_content->{fileManager}) || return;
-       my $datacenter = Vim::find_entity_view(view_type => 'Datacenter') || 
return;
+       my $file_manager = $self->_get_file_manager_view() || return;
+       my $datacenter = $self->_get_datacenter_view() || return;
        
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
        
        # Attempt to copy the file
@@ -1540,11 +1490,10 @@ sub move_file {
        $self->create_directory($destination_directory_path) || return;
        
        # Get a fileManager and Datacenter object
-       my $service_content = Vim::get_service_content() || return;
-       my $file_manager = Vim::get_view(mo_ref => 
$service_content->{fileManager}) || return;
-       my $datacenter = Vim::find_entity_view(view_type => 'Datacenter') || 
return;
+       my $file_manager = $self->_get_file_manager_view() || return;
+       my $datacenter = $self->_get_datacenter_view() || return;
        
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
 
        # Attempt to copy the file
@@ -1753,6 +1702,50 @@ sub find_files {
 }
 
 #/////////////////////////////////////////////////////////////////////////////
+ 
+=head2 get_total_space 
+
+ Parameters  : $path 
+ Returns     : integer 
+ Description : Returns the total size (in bytes) of the volume specified by the
+               argument. 
+
+=cut 
+
+sub get_total_space { 
+       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; 
+       } 
+       
+       # Get the path argument 
+       my $path = shift; 
+       if (!$path) { 
+               notify($ERRORS{'WARNING'}, 0, "path argument was not 
specified"); 
+               return; 
+       } 
+       
+       # Get the datastore name 
+       my $datastore_name = $self->_get_datastore_name($path) || return; 
+       
+       my $vmhost_hostname = $self->data->get_vmhost_hostname(); 
+       
+       # Get the datastore info hash 
+       my $datastore_info = $self->_get_datastore_info() || return; 
+       
+       my $total_bytes = $datastore_info->{$datastore_name}{capacity}; 
+       if (!defined($total_bytes)) { 
+               notify($ERRORS{'WARNING'}, 0, "datastore $datastore_name 
capacity key does not exist in datastore info:\n" . 
format_data($datastore_info));
+               return; 
+       } 
+       
+       notify($ERRORS{'DEBUG'}, 0, "capacity of $datastore_name datastore on 
$vmhost_hostname: " . get_file_size_info_string($total_bytes));
+       return $total_bytes; 
+} 
+
+
+#/////////////////////////////////////////////////////////////////////////////
 
 =head2 get_available_space
 
@@ -1783,7 +1776,7 @@ sub get_available_space {
        my $vmhost_hostname = $self->data->get_vmhost_hostname();
        
        # Get the datastore info hash
-       my $datastore_info = $self->_get_datastore_info() || return;
+       my $datastore_info = $self->_get_datastore_info(1) || return;
        
        my $available_bytes = $datastore_info->{$datastore_name}{freeSpace};
        if (!defined($available_bytes)) {
@@ -1791,7 +1784,7 @@ sub get_available_space {
                return;
        }
        
-       notify($ERRORS{'DEBUG'}, 0, "space available in $datastore_name 
datastore on $vmhost_hostname: " . format_number($available_bytes) . " bytes");
+       notify($ERRORS{'DEBUG'}, 0, "space available in $datastore_name 
datastore on $vmhost_hostname: " . get_file_size_info_string($available_bytes));
        return $available_bytes;
 }
 
@@ -1996,7 +1989,7 @@ sub _get_file_info {
                query => [@file_queries],
        );
        
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
        
        # Searches the folder specified by the datastore path and all 
subfolders based on the searchSpec
@@ -2056,12 +2049,168 @@ sub _get_file_info {
                }
        }
        
-       #notify($ERRORS{'DEBUG'}, 0, "retrieved info for " . 
scalar(keys(%file_info)) . " matching files:\n" . format_data(\%file_info));
+       notify($ERRORS{'DEBUG'}, 0, "retrieved info for " . 
scalar(keys(%file_info)) . " matching files:\n" . format_data(\%file_info));
        return \%file_info;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 _get_host_view
+
+ Parameters  : 
+ Returns     : vSphere SDK host object
+ Description : Retrieves a host object.
+
+=cut
+
+sub _get_host_view {
+       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;
+       }
+       
+       return $self->{host_view_object} if $self->{host_view_object};
+       
+       # Get the host view
+       $self->{host_view_object} = VIExt::get_host_view(1);
+       return $self->{host_view_object};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_datacenter_view
+
+ Parameters  : 
+ Returns     : vSphere SDK datacenter view object
+ Description : Retrieves a vSphere SDK datacenter view object.
+
+=cut
+
+sub _get_datacenter_view {
+       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;
+       }
+       
+       return $self->{datacenter_view_object} if 
$self->{datacenter_view_object};
+       
+       # Get the host view
+       my $datacenter = Vim::find_entity_view(view_type => 'Datacenter');
+       if (!$datacenter) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve datacenter 
view object");
+               return;
+       }
+       else {
+               $self->{datacenter_view_object} = $datacenter;
+               return $self->{datacenter_view_object};
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_vm_view
+
+ Parameters  : $vmx_file_path (optional)
+ Returns     : 
+ Description : 
+
+=cut
+
+sub _get_vm_view {
+       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;
+       }
+       
+       # Get the vmx path argument and convert it to a datastore path
+       my $vmx_path = shift || $self->get_vmx_file_path();
+       $vmx_path = $self->_get_datastore_path($vmx_path);
+       
+       # Override the die handler
+       local $SIG{__DIE__} = sub{};
+       
+       my $vm_view;
+       eval { $vm_view = Vim::find_entity_view(view_type => 'VirtualMachine', 
filter => {'config.files.vmPathName' => $vmx_path}); };
+       if (!$vm_view) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve view object 
for VM: $vmx_path");
+               return;
+   }
+       
+       $self->{vm_view_objects}{$vmx_path} = $vm_view;
+       return $self->{vm_view_objects}{$vmx_path};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_virtual_disk_manager_view
+
+ Parameters  : 
+ Returns     : vSphere SDK virtual disk manager view object
+ Description : Retrieves a vSphere SDK virtual disk manager view object.
+
+=cut
+
+sub _get_virtual_disk_manager_view {
+       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;
+       }
+       
+       return $self->{virtual_disk_manager_object} if 
$self->{virtual_disk_manager_object};
+       
+       # Get a virtual disk manager object
+       my $service_content = Vim::get_service_content() || return;
+       if (!$service_content->{virtualDiskManager}) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve virtual disk 
manager object, it is not available via the vSphere SDK");
+               return;
+       }
+       
+       my $virtual_disk_manager = Vim::get_view(mo_ref => 
$service_content->{virtualDiskManager});
+       if (!$virtual_disk_manager) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve virtual disk 
manager object");
+               return;
+       }
+       
+       $self->{virtual_disk_manager_object} = $virtual_disk_manager;
+       return $self->{virtual_disk_manager_object};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_file_manager_view
+
+ Parameters  : 
+ Returns     : vSphere SDK file manager view object
+ Description : Retrieves a vSphere SDK file manager view object.
+
+=cut
+
+sub _get_file_manager_view {
+       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;
+       }
+       
+       return $self->{file_manager_object} if $self->{file_manager_object};
+       
+       my $service_content = Vim::get_service_content() || return;
+       my $file_manager = Vim::get_view(mo_ref => 
$service_content->{fileManager});
+       if (!$file_manager) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve file manager 
object");
+               return;
+       }
+       
+       $self->{file_manager_object} = $file_manager;
+       return $self->{file_manager_object};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 _get_datastore_object
 
  Parameters  : $datastore_name
@@ -2079,14 +2228,16 @@ sub _get_datastore_object {
        }
        
        # Get the datastore name argument
-       my $datastore_name = shift;
-       if (!$datastore_name) {
+       my $datastore_name_argument = shift;
+       if (!$datastore_name_argument) {
                notify($ERRORS{'WARNING'}, 0, "datastore name argument was not 
specified");
                return;
        }
        
+       return $self->{datastore_objects}{$datastore_name_argument} if 
($self->{datastore_objects}{$datastore_name_argument});
+       
        # Get the host view
-       my $host_view = VIExt::get_host_view(1);
+       my $host_view = $self->_get_host_view();
        
        # Get an array containing datastore managed object references
        my @datastore_mo_refs = @{$host_view->datastore};
@@ -2096,11 +2247,13 @@ sub _get_datastore_object {
        my @datastore_names_found;
        for my $datastore_mo_ref (@datastore_mo_refs) {
                my $datastore = Vim::get_view(mo_ref => $datastore_mo_ref);
-               return $datastore if ($datastore_name eq 
$datastore->summary->name);
-               push @datastore_names_found, $datastore->summary->name;
+               my $datastore_name = $datastore->summary->name;
+               $self->{datastore_objects}{$datastore_name} = $datastore;
        }
        
-       notify($ERRORS{'WARNING'}, 0, "failed to find datastore named 
$datastore_name, datastore names found:\n" . join("\n", 
@datastore_names_found));
+       return $self->{datastore_objects}{$datastore_name_argument} if 
($self->{datastore_objects}{$datastore_name_argument});
+       
+       notify($ERRORS{'WARNING'}, 0, "failed to find datastore named 
$datastore_name_argument, datastore names found:\n" . join("\n", 
keys(%{$self->{datastore_objects}})));
        return;
 }
 
@@ -2134,10 +2287,14 @@ sub _get_datastore_info {
                return;
        }
        
+       # If the datastore info was previously retrieved, return the cached 
data unless an argument was specified
+       my $no_cache = shift;
+       return $self->{datastore_info} if (!$no_cache && 
$self->{datastore_info});
+       
        my $vmhost_hostname = $self->data->get_vmhost_hostname();
        
        # Get the host view
-       my $host_view = VIExt::get_host_view(1);
+       my $host_view = $self->_get_host_view();
        
        # Get an array containing datastore managed object references
        my @datastore_mo_refs = @{$host_view->datastore};
@@ -2173,6 +2330,8 @@ sub _get_datastore_info {
                $datastore_info->{$datastore_name} = $datastore_view->summary;
        }
        
+       #notify($ERRORS{'DEBUG'}, 0, "retrieved datastore info:\n" . 
format_data($datastore_info));
+       $self->{datastore_info} = $datastore_info;
        return $datastore_info;
 }
 
@@ -2201,12 +2360,7 @@ sub create_snapshot {
        # Override the die handler
        local $SIG{__DIE__} = sub{};
        
-       my $vm;
-       eval { $vm = Vim::find_entity_view(view_type => 'VirtualMachine', 
filter => {'config.files.vmPathName' => $vmx_path}); };
-       if (!$vm) {
-               notify($ERRORS{'WARNING'}, 0, "unable to create snapshop 
because VM is not registered: $vmx_path");
-               return;
-   }
+       my $vm = $self->_get_vm_view($vmx_path) || return;
        
        eval { $vm->CreateSnapshot(name => $snapshot_name,
                                                                                
memory => 0,
@@ -2243,18 +2397,13 @@ sub snapshot_exists {
        # Get the vmx path argument and convert it to a datastore path
        my $vmx_path = $self->_get_datastore_path(shift) || return;
        
-       # Override the die handler because fileManager may call it
+       # Override the die handler
        local $SIG{__DIE__} = sub{};
        
-       my $vm;
-       eval { $vm = Vim::find_entity_view(view_type => 'VirtualMachine', 
filter => {'config.files.vmPathName' => $vmx_path}); };
-       if (!$vm) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine if snapshot 
exists because VM is not registered: $vmx_path");
-               return;
-   }
+       my $vm = $self->_get_vm_view($vmx_path) || return;
        
        if (defined($vm->snapshot)) {
-               notify($ERRORS{'DEBUG'}, 0, "snapshot exists for VM: 
$vmx_path");
+               notify($ERRORS{'DEBUG'}, 0, "snapshot exists for VM: 
$vmx_path\n" . format_data($vm->snapshot));
                return 1;
        }
        else {


Reply via email to