Modified: vcl/sandbox/patches/vSphere_SDK_2.3.2_updated.pm
URL: 
http://svn.apache.org/viewvc/vcl/sandbox/patches/vSphere_SDK_2.3.2_updated.pm?rev=1631761&r1=1631760&r2=1631761&view=diff
==============================================================================
--- vcl/sandbox/patches/vSphere_SDK_2.3.2_updated.pm (original)
+++ vcl/sandbox/patches/vSphere_SDK_2.3.2_updated.pm Tue Oct 14 13:46:30 2014
@@ -1,3696 +1,3696 @@
-#!/usr/bin/perl -w
-###############################################################################
-# $Id: vSphere_SDK.pm 1448791 2013-02-21 20:02:20Z jfthomps $
-###############################################################################
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###############################################################################
-
-=head1 NAME
-
-VCL::Module::Provisioning::VMware::vSphere_SDK;
-
-=head1 SYNOPSIS
-
- my $vmhost_datastructure = $self->get_vmhost_datastructure();
- my $vsphere_sdk = 
VCL::Module::Provisioning::VMware::vSphere_SDK->new({data_structure => 
$vmhost_datastructure});
- my @registered_vms = $vsphere_sdk->get_registered_vms();
-
-=head1 DESCRIPTION
-
- This module provides support for the vSphere SDK. The vSphere SDK can be used
- to manage VMware Server 2.x, ESX 3.0.x, ESX/ESXi 3.5, ESX/ESXi 4.0, vCenter
- Server 2.5, and vCenter Server 4.0.
- 
- This patch was created as a temporary fix for deployments running VCL 2.3.2
- which encounter problems where the vSphere function calls die abruptly. The
- calls were not wrapped in eval blocks. This modified module adds the following
- subroutines:
- 
- _get_service_content
- _get_view
- _find_entity_view
- _find_entity_views
- 
- All calls to the vSphere SDK functions are routed through these subroutines
- which include the proper eval blocks.
-
-=cut
-
-##############################################################################
-package VCL::Module::Provisioning::VMware::vSphere_SDK;
-
-# Specify the lib path using FindBin
-use FindBin;
-use lib "$FindBin::Bin/../../../..";
-
-# Configure inheritance
-use base qw(VCL::Module::Provisioning::VMware::VMware);
-
-# Specify the version of this module
-our $VERSION = '2.3.2';
-
-# Specify the version of Perl to use
-use 5.008000;
-
-use strict;
-use warnings;
-use diagnostics;
-use English qw( -no_match_vars );
-use File::Temp qw( tempdir );
-use List::Util qw( max );
-
-use VCL::utils;
-
-##############################################################################
-
-=head1 API OBJECT METHODS
-
-=cut
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 initialize
-
- Parameters  : none
- Returns     : boolean
- Description : Initializes the vSphere SDK object by establishing a connection
-               to the VM host.
-
-=cut
-
-sub initialize {
-       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;
-       }
-       
-       # Newer versions of LWP::Protocol::https have strict SSL checking 
enabled by default
-       # The vSphere SDK won't be able to connect if ESXi or vCenter uses a 
self-signed certificate
-       # The following setting disables strict checking:
-       $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
-       
-       # Override the die handler because process will die if VMware Perl 
libraries aren't installed
-       local $SIG{__DIE__} = sub{};
-       
-       eval "use VMware::VIRuntime; use VMware::VILib; use VMware::VIExt";
-       if ($EVAL_ERROR) {
-               notify($ERRORS{'OK'}, 0, "vSphere SDK for Perl does not appear 
to be installed on this managment node, unable to load VMware vSphere SDK Perl 
modules, error:\n$EVAL_ERROR");
-               return 0;
-       }
-       notify($ERRORS{'DEBUG'}, 0, "loaded VMware vSphere SDK modules");
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       my $vmhost_username = $self->data->get_vmhost_profile_username();
-       my $vmhost_password = $self->data->get_vmhost_profile_password();
-       my $vmhost_profile_id = $self->data->get_vmhost_profile_id();
-       
-       if (!$vmhost_hostname) {
-               notify($ERRORS{'WARNING'}, 0, "VM host name could not be 
retrieved");
-               return;
-       }
-       elsif (!$vmhost_username) {
-               notify($ERRORS{'DEBUG'}, 0, "unable to use vSphere SDK, VM host 
username is not configured in the database for VM profile: $vmhost_profile_id");
-               return;
-       }
-       elsif (!$vmhost_password) {
-               notify($ERRORS{'DEBUG'}, 0, "unable to use vSphere SDK, VM host 
password is not configured in the database for VM profile: $vmhost_profile_id");
-               return;
-       }
-       
-       Opts::set_option('username', $vmhost_username);
-       Opts::set_option('password', $vmhost_password);
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       # Assemble the URLs to try, URL will vary based on the VMware product
-       my @possible_vmhost_urls = (
-               "https://$vmhost_hostname/sdk";,
-               "https://$vmhost_hostname:8333/sdk";,
-       );
-       
-       # Also add URLs containing the short host name if the VM hostname is a 
full DNS name
-       if ($vmhost_hostname =~ /\./) {
-               my ($vmhost_short_name) = $vmhost_hostname =~ /^([^\.]+)/;
-               push @possible_vmhost_urls, "https://$vmhost_short_name/sdk";;
-               push @possible_vmhost_urls, 
"https://$vmhost_short_name:8333/sdk";;
-       }
-       
-       # Call HostConnect, check how long it takes to connect
-       my $vim;
-       for my $host_url (@possible_vmhost_urls) {
-               Opts::set_option('url', $host_url);
-               
-               notify($ERRORS{'DEBUG'}, 0, "attempting to connect to VM host: 
$host_url ($vmhost_username)");
-               eval { $vim = Util::connect(); };
-               $vim = 'undefined' if !defined($vim);
-               my $error_message = $@;
-               undef $@;
-               
-               # It's normal if some connection attempts fail - SSH will be 
used if the vSphere SDK isn't available
-               # Don't display a warning unless the error indicates a 
configuration problem (wrong username or password)
-               # Possible error messages:
-               #    Cannot complete login due to an incorrect user name or 
password.
-               #    Error connecting to server at 'https://<VM host>/sdk': 
Connection refused
-               if ($error_message && $error_message =~ /incorrect/) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to connect to VM 
host because username or password is incorrectly configured in the VM profile 
($vmhost_username/$vmhost_password), error: $error_message");
-               }
-               elsif (!$vim || $error_message) {
-                       notify($ERRORS{'DEBUG'}, 0, "unable to connect to VM 
host using URL: $host_url, error:\n$error_message");
-               }
-               else {
-                       notify($ERRORS{'OK'}, 0, "connected to VM host: 
$host_url, username: '$vmhost_username'");
-                       last;
-               }
-       }
-       
-       if (!$vim) {
-               notify($ERRORS{'DEBUG'}, 0, "failed to connect to VM host 
$vmhost_hostname");
-               return;
-       }
-       elsif (!ref($vim)) {
-               notify($ERRORS{'DEBUG'}, 0, "failed to connect to VM host 
$vmhost_hostname, Util::connect returned '$vim'");
-               return;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "connected to $vmhost_hostname, VIM 
object type: " . ref($vim));
-               return 1;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_registered_vms
-
- Parameters  : none
- Returns     : array
- Description : Returns an array containing the vmx file paths of the VMs 
running
-               on the VM host.
-
-=cut
-
-sub get_registered_vms {
-       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;
-       }
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       my @vms = $self->_find_entity_views('VirtualMachine',
-               {
-                       begin_entity => $self->_get_datacenter_view()
-               }
-       );
-       
-       my @vmx_paths;
-       for my $vm (@vms) {
-               push @vmx_paths, 
$self->_get_normal_path($vm->summary->config->vmPathName) || return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "found " . scalar(@vmx_paths) . " 
registered VMs:\n" . join("\n", @vmx_paths));
-       return @vmx_paths;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_register
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Registers the VM specified by vmx file path argument. Returns
-               true if the VM is already registered or if the VM was
-               successfully registered.
-
-=cut
-
-sub vm_register {
-       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 = $self->_get_datastore_path(shift) || return;
-       
-       my $datacenter = $self->_get_datacenter_view() || return;
-       my $vm_folder = $self->_get_view($datacenter->{vmFolder}) || return;
-       
-       my $resource_pool = $self->_get_resource_pool_view() || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       my $vm_mo_ref;
-       eval { $vm_mo_ref = $vm_folder->RegisterVM(path => $vmx_path,
-                                                                               
          asTemplate => 'false',
-                                                                               
          pool => $resource_pool
-                                                                               
        );
-       };
-       
-       if ($@) {
-               if ($@->isa('SoapFault') && ref($@->detail) eq 'AlreadyExists') 
{
-                       notify($ERRORS{'DEBUG'}, 0, "VM is already registered: 
$vmx_path");
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to register VM: 
$vmx_path, error:\n$@");
-                       return;
-               }
-       }
-       
-       if (ref($vm_mo_ref) ne 'ManagedObjectReference' || $vm_mo_ref->type ne 
'VirtualMachine') {
-               notify($ERRORS{'WARNING'}, 0, "RegisterVM did not return a 
VirtualMachine ManagedObjectReference:\n" . format_data($vm_mo_ref));
-               return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "registered VM: $vmx_path");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_unregister
-
- Parameters  : $vmx_file_path or $vm_view or $vm_mo_ref
- Returns     : boolean
- Description : Unregisters the VM specified by vmx file path argument. Returns
-               true if the VM is not registered or if the VM was successfully
-               unregistered.
-
-=cut
-
-sub vm_unregister {
-       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 $argument = shift;
-       my $vm_view;
-       my $vm_name;
-       if (my $type = ref($argument)) {
-               if ($type eq 'ManagedObjectReference') {
-                       notify($ERRORS{'DEBUG'}, 0, "argument is a 
ManagedObjectReference, retrieving VM view");
-                       $vm_view = $self->_get_view($argument)
-               }
-               elsif ($type eq 'VirtualMachine') {
-                       $vm_view = $argument;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "invalid argument 
reference type: '$type', must be either VirtualMachine or 
ManagedObjectReference");
-                       return;
-               }
-               
-               $vm_name = $vm_view->{name};
-               if (!$vm_name) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to unregister VM, 
name could not be determined from VM view:\n" . format_data($vm_view));
-                       return;
-               }
-       }
-       else {
-               $vm_name = $argument;
-               $vm_view = $self->_get_vm_view($argument);
-       }
-       
-       my $vmx_path = $vm_view->{summary}{config}{vmPathName};
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       notify($ERRORS{'DEBUG'}, 0, "attempting to unregister VM: '$vm_name' 
($vmx_path)");
-       
-       eval { $vm_view->UnregisterVM(); };
-       if ($@) {
-               notify($ERRORS{'WARNING'}, 0, "failed to unregister VM: 
$vm_name, error:\n$@");
-               return;
-       }
-       
-       # Delete the cached VM object
-       delete $self->{vm_view_objects}{$vmx_path};
-       
-       notify($ERRORS{'DEBUG'}, 0, "unregistered VM: $vm_name");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_power_on
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Powers on the VM specified by vmx file path argument. Returns
-               true if the VM was successfully powered on or if it was already
-               powered on.
-
-=cut
-
-sub vm_power_on {
-       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 = $self->_get_datastore_path(shift) || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       my $vm = $self->_get_vm_view($vmx_path) || return;
-       
-       eval { $vm->PowerOnVM(); };
-       if ($@) {
-               if ($@->isa('SoapFault') && ref($@->detail) eq 
'InvalidPowerState') {
-                       my $existing_power_state = 
$@->detail->existingState->val;
-                       if ($existing_power_state =~ /on/i) {
-                               notify($ERRORS{'DEBUG'}, 0, "VM is already 
powered on: $vmx_path");
-                               return 1;
-                       }
-               }
-               
-               notify($ERRORS{'WARNING'}, 0, "failed to power on VM: 
$vmx_path, error:\n$@");
-               return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "powered on VM: $vmx_path");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_power_off
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Powers off the VM specified by vmx file path argument. Returns
-               true if the VM was successfully powered off or if it was already
-               powered off.
-
-=cut
-
-sub vm_power_off {
-       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 = $self->_get_datastore_path(shift) || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       my $vm = $self->_get_vm_view($vmx_path) || return;
-       
-       eval { $vm->PowerOffVM(); };
-       if ($@) {
-               if ($@->isa('SoapFault') && ref($@->detail) eq 
'InvalidPowerState') {
-                       my $existing_power_state = 
$@->detail->existingState->val;
-                       if ($existing_power_state =~ /off/i) {
-                               notify($ERRORS{'DEBUG'}, 0, "VM is already 
powered off: $vmx_path");
-                               return 1;
-                       }
-               }
-               
-               notify($ERRORS{'WARNING'}, 0, "failed to power off VM: 
$vmx_path, error:\n$@");
-               return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "powered off VM: $vmx_path");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_vm_power_state
-
- Parameters  : $vmx_file_path
- Returns     : string
- Description : Determines the power state of the VM specified by the vmx file
-               path argument. A string is returned containing one of the
-               following values:
-               -on
-               -off
-               -suspended
-
-=cut
-
-sub get_vm_power_state {
-       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 = $self->_get_datastore_path(shift) || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       my $vm = $self->_get_vm_view($vmx_path) || return;
-       
-       my $power_state = $vm->runtime->powerState->val;
-       
-       my $return_power_state;
-       if ($power_state =~ /on/i) {
-               $return_power_state = 'on';
-       }
-       elsif ($power_state =~ /off/i) {
-               $return_power_state = 'off';
-       }
-       elsif ($power_state =~ /suspended/i) {
-               $return_power_state = 'suspended';
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "detected unsupported power 
state: $power_state");
-               $return_power_state = '$power_state';
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "power state of VM $vmx_path: 
$return_power_state");
-       return $return_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
- 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.
-               
-               The disk type argument is optional and may be one of the
-               following values:
-               -eagerZeroedThick
-                  -all space allocated and wiped clean of any previous 
contents on the physical media at creation time
-                  -may take longer time during creation compared to other disk 
formats
-               -flatMonolithic
-                  -preallocated monolithic disk
-                  -disks in this format can be used with other VMware products
-                  -format is only applicable as a destination format in a 
clone operation
-                  -not usable for disk creation
-                  -since vSphere API 4.0
-               -preallocated
-                  -all space allocated at creation time
-                  -space is zeroed on demand as the space is used
-               -raw
-                  -raw device
-               -rdm
-                  -virtual compatibility mode raw disk mapping
-                  -grants access to the entire raw disk and the virtual disk 
can participate in snapshots
-               -rdmp
-                  -physical compatibility mode (pass-through) raw disk mapping
-                  -passes SCSI commands directly to the hardware
-                  -cannot participate in snapshots
-               -sparse2Gb, 2Gbsparse
-                  -sparse disk with 2GB maximum extent size
-                  -can be used with other VMware products
-                  -2GB extent size makes these disks easier to burn to dvd or 
use on filesystems that don't support large files
-                  -only applicable as a destination format in a clone operation
-                  -not usable for disk creation
-               -sparseMonolithic
-                  -sparse monolithic disk
-                  -can be used with other VMware products
-                  -only applicable as a destination format in a clone operation
-                  -not usable for disk creation
-                  -since vSphere API 4.0
-               -thick
-                  -all space allocated at creation time
-                  -space may contain stale data on the physical media
-                  -primarily used for virtual machine clustering
-                  -generally insecure and should not be used
-                  -due to better performance and security properties, the use 
of the 'preallocated' format is preferred over this format
-               -thick2Gb
-                  -thick disk with 2GB maximum extent size
-                  -can be used with other VMware products
-                  -2GB extent size makes these disks easier to burn to dvd or 
use on filesystems that don't support large files
-                  -only applicable as a destination format in a clone operation
-                  -not usable for disk creation
-               -thin (default)
-                  -space required for thin-provisioned virtual disk is 
allocated and zeroed on demand as the space is used
-                  
-               The adapter type argument is optional and may be one of the
-               following values:
-               -busLogic
-               -ide
-               -lsiLogic
-               
-               If the adapter type argument is not specified an attempt will be
-               made to retrieve it from the source vmdk file. If this fails,
-               lsiLogic will be used.
-
-=cut
-
-sub copy_virtual_disk {
-       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 source and destination path arguments in the datastore path 
format
-       my $source_path = $self->_get_datastore_path(shift) || return;
-       my $destination_path = $self->_get_datastore_path(shift) || return;
-       
-       # Make sure the source path ends with .vmdk
-       if ($source_path !~ /\.vmdk$/i || $destination_path !~ /\.vmdk$/i) {
-               notify($ERRORS{'WARNING'}, 0, "source and destination path 
arguments must end with .vmdk:\nsource path argument: $source_path\ndestination 
path argument: $destination_path");
-               return;
-       }
-       
-       
-       # Get the adapter type and disk type arguments if they were specified
-       # If not specified, set the default values
-       my $destination_disk_type = shift || 'thin';
-       
-       # Fix the disk type in case 2gbsparse was passed
-       if ($destination_disk_type =~ /2gbsparse/i) {
-               $destination_disk_type = 'sparse2Gb';
-       }
-       
-       # Check the disk type argument, the string must match exactly or the 
copy will fail
-       my @valid_disk_types = qw( eagerZeroedThick flatMonolithic preallocated 
raw rdm rdmp sparse2Gb sparseMonolithic thick thick2Gb thin );
-       if (!grep(/^$destination_disk_type$/, @valid_disk_types)) {
-               notify($ERRORS{'WARNING'}, 0, "disk type argument is not valid: 
'$destination_disk_type', it must exactly match (case sensitive) one of the 
following strings:\n" . join("\n", @valid_disk_types));
-               return;
-       }
-       
-       my $vmhost_name = $self->data->get_vmhost_hostname();
-       
-       my $source_datastore_name = $self->_get_datastore_name($source_path) || 
return;
-       my $destination_datastore_name = 
$self->_get_datastore_name($destination_path) || return;
-       
-       my $source_datastore = 
$self->_get_datastore_object($source_datastore_name) || return;
-       my $destination_datastore = 
$self->_get_datastore_object($destination_datastore_name) || return;
-       
-       my $destination_base_name = 
$self->_get_file_base_name($destination_path);
-       
-       my $datacenter_view = $self->_get_datacenter_view() || return;
-       my $virtual_disk_manager_view = $self->_get_virtual_disk_manager_view() 
|| return;
-       
-       # Get the source vmdk file info so the source adapter and disk type can 
be displayed
-       my $source_info = $self->_get_file_info($source_path) || return;
-       if (scalar(keys %$source_info) != 1) {
-               notify($ERRORS{'WARNING'}, 0, "unable to copy virtual disk, 
multiple source files were found:\n" . format_data($source_info));
-       }
-       
-       my $source_info_file_path = (keys(%$source_info))[0];
-       
-       my $source_adapter_type = 
$source_info->{$source_info_file_path}{controllerType} || 'lsiLogic';
-       my $source_disk_type = $source_info->{$source_info_file_path}{diskType} 
|| '';
-       my $source_file_size_bytes = 
$source_info->{$source_info_file_path}{fileSize} || '0';
-       my $source_file_capacity_kb = 
$source_info->{$source_info_file_path}{capacityKb} || '0';
-       my $source_file_capacity_bytes = ($source_file_capacity_kb * 1024);
-       
-       # Set the destination adapter type to the source adapter type if it 
wasn't specified as an argument
-       my $destination_adapter_type = shift || $source_adapter_type;
-       
-       if ($destination_adapter_type =~ /bus/i) {
-               $destination_adapter_type = 'busLogic';
-       }
-       elsif ($destination_adapter_type =~ /lsi/) {
-               $destination_adapter_type = 'lsiLogic';
-       }
-       else {
-               $destination_adapter_type = 'ide';
-       }
-       
-       if ($source_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;
-       }
-       
-       # 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;
-       
-       notify($ERRORS{'DEBUG'}, 0, "attempting to copy virtual disk on VM host 
$vmhost_name: '$source_path' --> '$destination_path'\n" .
-               "source adapter type: $source_adapter_type\n" .
-               "destination adapter type: $destination_adapter_type\n" .
-               "disk type: $source_disk_type\n" .
-               "source capacity: " . 
get_file_size_info_string($source_file_capacity_bytes) . "\n" .
-               "source space used: " . 
get_file_size_info_string($source_file_size_bytes)
-       );
-       
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       # Create a virtual disk spec object
-       my $virtual_disk_spec = VirtualDiskSpec->new(
-               adapterType => $destination_adapter_type,
-               diskType => $destination_disk_type,
-       );
-       
-       my $copy_virtual_disk_result;
-       eval {
-               $copy_virtual_disk_result = 
$virtual_disk_manager_view->CopyVirtualDisk(
-                       sourceName => $source_path,
-                       sourceDatacenter => $datacenter_view,
-                       destName => $destination_path,
-                       destDatacenter => $datacenter_view,
-                       destSpec => $virtual_disk_spec,
-                       force => 1
-               );
-       };
-       
-       # Check if an error occurred
-       if (my $copy_virtual_disk_fault = $@) {
-               if ($copy_virtual_disk_fault =~ /No space left/i) {
-                       # Check if the output indicates there is not enough 
space to copy the vmdk
-                       # Output will contain:
-                       #    Fault string: A general system error occurred: No 
space left on device
-                       #    Fault detail: SystemError
-                       notify($ERRORS{'CRITICAL'}, 0, "failed to copy vmdk on 
VM host $vmhost_name using CopyVirtualDisk function, no space is left on the 
destination device: '$destination_path'\nerror:\n$copy_virtual_disk_fault");
-                       return;
-               }
-               elsif ($copy_virtual_disk_fault =~ /not implemented/i) {
-                       notify($ERRORS{'DEBUG'}, 0, "unable to copy vmdk using 
CopyVirtualDisk function, VM host $vmhost_name does not implement the 
CopyVirtualDisk function");
-                       
-                       # Delete the destination directory path previously 
created
-                       $self->delete_file($destination_directory_path);
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to copy vmdk on 
VM host $vmhost_name using CopyVirtualDisk function: '$source_path' --> 
'$destination_path'\nerror:\n$copy_virtual_disk_fault");
-                       return;
-               }
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "copied vmdk on VM host $vmhost_name 
using CopyVirtualDisk function:\n" . format_data($copy_virtual_disk_result));
-               return 1;
-       }
-       
-       
-       my $source_vm_name = 
$self->_clean_vm_name("source_$destination_base_name");
-       my $clone_vm_name = $self->_clean_vm_name($destination_base_name);
-       
-       my $source_vm_directory_path = "[$source_datastore_name] 
$source_vm_name";
-       my $clone_vm_directory_path = "[$destination_datastore_name] 
$clone_vm_name";
-       
-       # Make sure the source and clone directories don't exist
-       # Otherwise the VM creation/cloning process will create another 
directory with '_1' appended and the files won't be deleted
-       if ($self->file_exists($source_vm_directory_path)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to copy virtual disk, 
source VM directory path already exists: $source_vm_directory_path");
-               return;
-       }
-       if ($self->file_exists($clone_vm_directory_path)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to copy virtual disk, 
clone VM directory path already exists: $clone_vm_directory_path");
-               return;
-       }
-       
-       
-       my $file_manager = $self->_get_file_manager_view() || return;
-       my $resource_pool_view = $self->_get_resource_pool_view() || return;
-       
-       my $folder_view = $self->_find_entity_view("Folder",
-               {
-                       begin_entity => $datacenter_view,
-                       filter => { name => "vm" }
-               }
-       );
-       
-       if (!$folder_view){
-               notify($ERRORS{'WARNING'}, 0, "failed to retrieve VM folder 
view");
-               return;
-       }
-       
-       # Create a virtual machine on top of this virtual disk
-       # First, create a controller for the virtual disk
-       my $controller;
-       if ($destination_adapter_type eq 'lsiLogic') {
-               $controller = VirtualLsiLogicController->new(
-                       key => 0,
-                       device => [0],
-                       busNumber => 0,
-                       sharedBus => VirtualSCSISharing->new('noSharing')
-               );
-       }
-       else {
-               $controller = VirtualBusLogicController->new(
-                       key => 0,
-                       device => [0],
-                       busNumber => 0,
-                       sharedBus => VirtualSCSISharing->new('noSharing')
-               );
-       }
-       
-       # Next create a disk type (it will be the same as the source disk)   
-       my $disk_backing_info = ($source_disk_type)->new(
-               datastore => $source_datastore,
-               fileName => $source_path,
-               diskMode => "independent_persistent"
-       );
-       
-       # Create the actual virtual disk
-       my $source_vm_disk = VirtualDisk->new(
-               key => 0,
-               backing => $disk_backing_info,
-               capacityInKB => $source_file_capacity_kb,
-               controllerKey => 0,
-               unitNumber => 0
-       );
-       
-       # Create the specification for creating a source VM
-       my $source_vm_config = VirtualMachineConfigSpec->new(
-               name => $source_vm_name,
-               deviceChange => [
-                       VirtualDeviceConfigSpec->new(
-                               operation => 
VirtualDeviceConfigSpecOperation->new('add'),
-                               device => $controller
-                       ),
-                       VirtualDeviceConfigSpec->new(
-                               operation => 
VirtualDeviceConfigSpecOperation->new('add'),
-                               device => $source_vm_disk
-                       )
-               ],
-               files => VirtualMachineFileInfo->new(
-                       logDirectory => $source_vm_directory_path,
-                       snapshotDirectory => $source_vm_directory_path,
-                       suspendDirectory => $source_vm_directory_path,
-                       vmPathName => $source_vm_directory_path
-               )
-       );
-       
-       # Create the specification for cloning the VM
-       my $clone_spec = VirtualMachineCloneSpec->new(
-               config => VirtualMachineConfigSpec->new(
-                       name => $clone_vm_name,
-                       files => VirtualMachineFileInfo->new(
-                               logDirectory => $clone_vm_directory_path,
-                               snapshotDirectory => $clone_vm_directory_path,
-                               suspendDirectory => $clone_vm_directory_path,
-                               vmPathName => $clone_vm_directory_path
-                       )
-               ),
-               powerOn => 0,
-               template => 0,
-               location => VirtualMachineRelocateSpec->new(
-                       datastore => $destination_datastore,
-                       pool => $resource_pool_view,
-                       diskMoveType => 'moveAllDiskBackingsAndDisallowSharing',
-                       transform => 
VirtualMachineRelocateTransformation->new('sparse'),
-               )
-       );
-       
-       
-       notify($ERRORS{'DEBUG'}, 0, "attempting to copy virtual disk by cloning 
temporary VM: '$source_path' --> '$destination_path'\n" .
-               "adapter type: $source_adapter_type\n" .
-               "source disk type: $source_disk_type\n" .
-               "source capacity: " . 
get_file_size_info_string($source_file_capacity_bytes) . "\n" .
-               "source space used: " . 
get_file_size_info_string($source_file_size_bytes) . "\n" .
-               "source VM name: $source_vm_name\n" .
-               "clone VM name: $clone_vm_name\n" .
-               "source VM directory path: $source_vm_directory_path\n" .
-               "clone VM directory path: $clone_vm_directory_path"
-       );
-       
-       
-       my $source_vm_view;
-       my $clone_vm_view;
-       eval {
-               my $source_vm = $folder_view->CreateVM(
-                       config => $source_vm_config,
-                       pool => $resource_pool_view
-               );
-               if ($source_vm) {
-                       notify($ERRORS{'DEBUG'}, 0, "created temporary source 
VM which will be cloned: $source_vm_name");
-                       $source_vm_view = $self->_get_view($source_vm);
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to create 
temporary source VM which will be cloned: $source_vm_name");
-                       return;
-               }
-               
-               notify($ERRORS{'DEBUG'}, 0, "cloning VM: $source_vm_name --> 
$clone_vm_name");
-               my $clone_vm = $source_vm_view->CloneVM(
-                       folder => $folder_view,
-                       name => $clone_vm_name,
-                       spec => $clone_spec
-               );
-               if ($clone_vm) {
-                       $clone_vm_view = $self->_get_view($clone_vm);
-                       notify($ERRORS{'DEBUG'}, 0, "cloned VM: $source_vm_name 
--> $clone_vm_name" . format_data($clone_vm_view));
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to clone VM: 
$source_vm_name --> $clone_vm_name");
-                       return;
-               }
-       };
-       
-       # Check if an error occurred
-       if (my $fault = $@) {
-               if ($fault =~ /No space left/i) {
-                       # Check if the output indicates there is not enough 
space to copy the vmdk
-                       # Output will contain:
-                       #    Fault string: A general system error occurred: No 
space left on device
-                       #    Fault detail: SystemError
-                       notify($ERRORS{'CRITICAL'}, 0, "failed to copy vmdk on 
VM host $vmhost_name, no space is left on the destination device: 
'$destination_path'\nerror:\n$fault");
-                       return;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to copy vmdk on 
VM host $vmhost_name: '$source_path' --> '$destination_path'\nerror:\n$fault");
-               }
-               return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "deleting source VM: $source_vm_name");
-       $self->vm_unregister($source_vm_view);
-       notify($ERRORS{'DEBUG'}, 0, "deleting source VM directory: 
$source_vm_directory_path");
-       $self->delete_file($source_vm_directory_path);
-       
-       notify($ERRORS{'DEBUG'}, 0, "deleting cloned VM: $clone_vm_name");
-       $self->vm_unregister($clone_vm_view);
-       my @clone_files = $self->find_files($clone_vm_directory_path, '*', 1);
-       for my $clone_file_path (grep(!/\.(vmdk)$/i, @clone_files)) {
-               notify($ERRORS{'DEBUG'}, 0, "deleting cloned VM file: 
$clone_file_path");
-               $self->delete_file($clone_file_path);
-       }
-       
-    # 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;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 move_virtual_disk
-
- Parameters  : $source_path, $destination_path
- Returns     : boolean
- Description : Moves or renames a virtual disk (set of vmdk files).
-
-=cut
-
-sub move_virtual_disk {
-       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 source path argument in datastore path format
-       my $source_path = $self->_get_datastore_path(shift) || return;
-       my $destination_path = $self->_get_datastore_path(shift) || return;
-       
-       my $vmhost_name = $self->data->get_vmhost_hostname();
-       
-       # Make sure the source path ends with .vmdk
-       if ($source_path !~ /\.vmdk$/i || $destination_path !~ /\.vmdk$/i) {
-               notify($ERRORS{'WARNING'}, 0, "source and destination path 
arguments must end with .vmdk:\nsource path argument: $source_path\ndestination 
path argument: $destination_path");
-               return;
-       }
-       
-       # Make sure the source file exists
-       if (!$self->file_exists($source_path)) {
-               notify($ERRORS{'WARNING'}, 0, "source file does not exist on VM 
host $vmhost_name: '$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'");
-               return;
-       }
-       
-       # Get the destination parent directory path, make sure it exists
-       my $destination_parent_directory_path = 
$self->_get_parent_directory_datastore_path($destination_path) || return;
-       $self->create_directory($destination_parent_directory_path) || return;
-       
-       # Check if a virtual disk manager object is available
-       my $virtual_disk_manager = $self->_get_virtual_disk_manager_view() || 
return;
-       
-       # Create a datacenter object
-       my $datacenter = $self->_get_datacenter_view() || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       # Attempt to move the virtual disk using MoveVirtualDisk
-       notify($ERRORS{'DEBUG'}, 0, "attempting to move virtual disk on VM host 
$vmhost_name: '$source_path' --> '$destination_path'");
-       eval { $virtual_disk_manager->MoveVirtualDisk(sourceName => 
$source_path,
-                                                                               
                                                 sourceDatacenter => 
$datacenter,
-                                                                               
                                                 destName => $destination_path,
-                                                                               
                                                 destDatacenter => $datacenter,
-                                                                               
                                                 force => 0);
-       };
-       
-       # Check if an error occurred
-       if (my $fault = $@) {
-               # Get the source file info
-               my $source_file_info = 
$self->_get_file_info($source_path)->{$source_path};
-               
-               # 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 ($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;
-    }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 create_nfs_datastore
-
- Parameters  : $datastore_name, $remote_host, $remote_path
- Returns     : boolean
- Description : Creates an NFS datastore on the VM host. Note: this subroutine 
is
-               not currenly being called by anything.
-
-=cut
-
-sub create_nfs_datastore {
-       my $self = shift;
-       if (ref($self) !~ /module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       # Get the arguments
-       my ($datastore_name, $remote_host, $remote_path) = @_;
-       if (!$datastore_name || !$remote_host || !$remote_path) {
-               notify($ERRORS{'WARNING'}, 0, "datastore name, remote host, and 
remote path arguments were not supplied");
-               return;
-       }
-       
-       # Remove trailing slashes from the remote path
-       $remote_path =~ s/\/+$//g;
-       
-       # Assemble a datastore device string, used to check if existing 
datastore is pointing to the same remote host and path
-       my $datastore_device = "$remote_host:$remote_path";
-       
-       # Get the existing datastore info
-       my $datastore_info = $self->_get_datastore_info();
-       for my $check_datastore_name (keys(%$datastore_info)) {
-               my $check_datastore_type = 
$datastore_info->{$check_datastore_name}{type};
-               
-               # Make sure a non-NFS datastore with the same name doesn't 
alreay exist
-               if ($check_datastore_type !~ /nfs/i) {
-                       if ($check_datastore_name eq $datastore_name) {
-                               notify($ERRORS{'WARNING'}, 0, "datastore named 
$datastore_name already exists on VM host but its type is not NFS:\n" . 
format_data($datastore_info->{$check_datastore_name}));
-                               return;
-                       }
-                       else {
-                               # Type isn't NFS and name doesn't match
-                               next;
-                       }
-               }
-               
-               # Get the existing datastore device string, format is:
-               # 10.25.0.245:/install/vmtest/datastore
-               my $check_datastore_device = 
$datastore_info->{$check_datastore_name}{datastore}{value};
-               if (!$check_datastore_device) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to retrieve 
datastore device string from datastore info:\n" . 
format_data($datastore_info->{$check_datastore_name}));
-                       next;
-               }
-               
-               # Remove trailing slashes from existing device string
-               $check_datastore_device =~ s/\/+$//g;
-               
-               # Check if datastore already exists pointing to the same remote 
path
-               if ($check_datastore_name eq $datastore_name) {
-                       # Datastore names match, check if existing datastore is 
pointing the the requested device path
-                       if ($check_datastore_device eq $datastore_device) {
-                               notify($ERRORS{'DEBUG'}, 0, 
"$check_datastore_type datastore '$datastore_name' already exists on VM host, 
remote path: $check_datastore_device");
-                               return 1;
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, 
"$check_datastore_type datastore '$datastore_name' already exists on VM host 
but it is pointing to a different remote path:
-                                                requested remote path: 
$datastore_device
-                                                existing remote path: 
$check_datastore_device");
-                               return;
-                       }
-               }
-               else {
-                       # Datastore names don't match, make sure an existing 
datastore with a different name isn't pointing to the requested device path
-                       if ($check_datastore_device eq $datastore_device) {
-                               notify($ERRORS{'WARNING'}, 0, 
"$check_datastore_type datastore with a different name already exists on VM 
host pointing to '$check_datastore_device':
-                                                requested datastore name: 
$datastore_name
-                                                existing datastore name: 
$check_datastore_name");
-                               return;
-                       }
-                       else {
-                               # Datastore name doesn't match, datastore 
remote path doesn't match
-                               next;
-                       }
-               }
-       }
-       
-       # Get the datastore system object
-       my $datastore_system = 
$self->_get_view($self->_get_datastore_view->configManager->datastoreSystem);
-       if (!$datastore_system) {
-               notify($ERRORS{'WARNING'}, 0, "failed to retrieve datastore 
system object");
-               return;
-       }
-       
-       # Create a HostNasVolumeSpec object to store the datastore configuration
-       my $host_nas_volume_spec = HostNasVolumeSpec->new(accessMode => 
'readWrite',
-                                                                               
                                                          localPath => 
$datastore_name,
-                                                                               
                                                          remoteHost => 
$remote_host,
-                                                                               
                                                          remotePath => 
$remote_path,
-                                                                               
                                                          );
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       # Attempt to cretae the NAS datastore
-       notify($ERRORS{'DEBUG'}, 0, "attempting to create NAS datastore:\n" . 
format_data($host_nas_volume_spec));
-       eval { $datastore_system->CreateNasDatastore(spec => 
$host_nas_volume_spec); };
-       if (my $fault = $@) {
-               notify($ERRORS{'WARNING'}, 0, "failed to create NAS datastore 
on VM host:\ndatastore name: $datastore_name\nremote host: $remote_host\nremote 
path: $remote_path\nerror:\n$@");
-               return;
-       }
-       
-       notify($ERRORS{'OK'}, 0, "created NAS datastore on VM host: 
$datastore_name");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_virtual_disk_controller_type
-
- Parameters  : $vmdk_file_path
- Returns     : string
- Description : Retrieves the disk controller type configured for the virtual
-               disk specified by the vmdk file path argument. A string is
-               returned containing one of the following values:
-               -lsiLogic
-               -busLogic
-               -ide
-
-=cut
-
-sub get_virtual_disk_controller_type {
-       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 vmdk file path argument
-       my $vmdk_file_path = $self->_get_datastore_path(shift) || return;
-       if ($vmdk_file_path !~ /\.vmdk$/) {
-               notify($ERRORS{'WARNING'}, 0, "file path argument must end with 
.vmdk: $vmdk_file_path");
-               return;
-       }
-       
-       # Get the vmdk file info
-       my $vmdk_file_info = 
$self->_get_file_info($vmdk_file_path)->{$vmdk_file_path};
-       if (!$vmdk_file_info) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve info for 
file: $vmdk_file_path");
-               return;
-       }
-       
-       # Check if the controllerType key exists in the vmdk file info
-       if (!defined($vmdk_file_info->{controllerType}) || 
!$vmdk_file_info->{controllerType}) {
-               notify($ERRORS{'DEBUG'}, 0, "unable to retrieve controllerType 
value from file info: $vmdk_file_path\n" . format_data($vmdk_file_info));
-               return;
-       }
-       
-       my $controller_type = $vmdk_file_info->{controllerType};
-       
-       my $return_controller_type;
-       if ($controller_type =~ /lsi/i) {
-               $return_controller_type = 'lsiLogic';
-       }
-       elsif ($controller_type =~ /bus/i) {
-               $return_controller_type = 'busLogic';
-       }
-       elsif ($controller_type =~ /ide/i) {
-               $return_controller_type = 'ide';
-       }
-       else {
-               $return_controller_type = $controller_type;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "retrieved controllerType value from vmdk 
file info: $return_controller_type ($controller_type)");
-       return $return_controller_type;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_virtual_disk_type
-
- Parameters  : $vmdk_file_path
- Returns     : string
- Description : Retrieves the disk type configured for the virtual
-               disk specified by the vmdk file path argument. A string is
-               returned containing one of the following values:
-               -FlatVer1
-               -FlatVer2
-               -RawDiskMappingVer1
-               -SparseVer1
-               -SparseVer2
-
-=cut
-
-sub get_virtual_disk_type {
-       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 vmdk file path argument
-       my $vmdk_file_path = $self->_get_datastore_path(shift) || return;
-       if ($vmdk_file_path !~ /\.vmdk$/) {
-               notify($ERRORS{'WARNING'}, 0, "file path argument must end with 
.vmdk: $vmdk_file_path");
-               return;
-       }
-       
-       # Get the vmdk file info
-       my $vmdk_file_info = 
$self->_get_file_info($vmdk_file_path)->{$vmdk_file_path};
-       if (!$vmdk_file_info) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve info for 
file: $vmdk_file_path");
-               return;
-       }
-       
-       # Check if the diskType key exists in the vmdk file info
-       if (!defined($vmdk_file_info->{diskType}) || 
!$vmdk_file_info->{diskType}) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve diskType 
value from file info: $vmdk_file_path\n" . format_data($vmdk_file_info));
-               return;
-       }
-       
-       my $disk_type = $vmdk_file_info->{diskType};
-       
-       if ($disk_type =~ /VirtualDisk(.+)BackingInfo/) {
-               $disk_type = $1;
-       }
-       notify($ERRORS{'DEBUG'}, 0, "retrieved diskType value from vmdk file 
info: $disk_type");
-       return $disk_type;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_virtual_disk_hardware_version
-
- Parameters  : $vmdk_file_path
- Returns     : string
- Description : Retrieves the virtual disk hardware version configured for the
-               virtual disk specified by the vmdk file path argument.
-
-=cut
-
-sub get_virtual_disk_hardware_version {
-       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 vmdk file path argument
-       my $vmdk_file_path = $self->_get_datastore_path(shift) || return;
-       if ($vmdk_file_path !~ /\.vmdk$/) {
-               notify($ERRORS{'WARNING'}, 0, "file path argument must end with 
.vmdk: $vmdk_file_path");
-               return;
-       }
-       
-       # Get the vmdk file info
-       my $vmdk_file_info = 
$self->_get_file_info($vmdk_file_path)->{$vmdk_file_path};
-       if (!$vmdk_file_info) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve info for 
file: $vmdk_file_path");
-               return;
-       }
-       
-       # Check if the hardwareVersion key exists in the vmdk file info
-       my $hardware_version = $vmdk_file_info->{hardwareVersion};
-       if (!$hardware_version) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve 
hardwareVersion value from file info: $vmdk_file_path\n" . 
format_data($vmdk_file_info));
-               return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "retrieved hardwareVersion value from vmdk 
file info: $hardware_version");
-       return $hardware_version;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_vmware_product_name
-
- Parameters  : none
- Returns     : string
- Description : Returns the full VMware product name installed on the VM host.
-               Examples:
-                                       VMware Server 2.0.2 build-203138
-                                       VMware ESXi 4.0.0 build-208167
-
-=cut
-
-sub get_vmware_product_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;
-       }
-       
-       return $self->{product_name} if $self->{product_name};
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $service_content = $self->_get_service_content();
-       my $product_name = $service_content->{about}->{fullName};
-       if ($product_name) {
-               notify($ERRORS{'DEBUG'}, 0, "VMware product being used on VM 
host $vmhost_hostname: '$product_name'");
-               $self->{product_name} = $product_name;
-               return $self->{product_name};
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve VMware 
product name being used on VM host $vmhost_hostname");
-               return;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_vmware_product_version
-
- Parameters  : none
- Returns     : string
- Description : Returns the VMware product version installed on the VM host.
-               Example: '4.0.0'
-
-=cut
-
-sub get_vmware_product_version {
-       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->{product_version} if $self->{product_version};
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $datacenter_view = $self->_get_datacenter_view();
-       my $product_version = $datacenter_view->config->product->version;
-       
-       if ($product_version) {
-               notify($ERRORS{'DEBUG'}, 0, "retrieved product version for VM 
host $vmhost_hostname: $product_version");
-               $self->{product_version} = $product_version;
-               return $self->{product_version};
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve product 
version for VM host $vmhost_hostname");
-               return;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_network_names
-
- Parameters  : none
- Returns     : array
- Description : Retrieves the network names configured on the VM host.
-
-=cut
-
-sub get_network_names {
-       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 $datacenter_view = $self->_get_datacenter_view();
-       
-       # Retrieve the network info, check if each network is accessible
-       my @network_names;
-       for my $network (@{Vim::get_views(mo_ref_array => 
$datacenter_view->network)}) {
-               push @network_names, $network->name;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "retrieved network names:\n" . join("\n", 
@network_names));
-       return @network_names;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 is_restricted
-
- Parameters  : none
- Returns     : boolean
- Description : Determines if remote access to the VM host via the vSphere SDK 
is
-               restricted due to the type of VMware license being used on the
-               host. 0 is returned if remote access is not restricted. 1 is
-               returned if remote access is restricted and the access to the VM
-               host is read-only.
-
-=cut
-
-sub is_restricted {
-       my $self = shift;
-       if (ref($self) !~ /module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $service_content = $self->_get_service_content();
-       if (!$service_content) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve vSphere SDK 
service content object, assuming access to the VM host via the vSphere SDK is 
restricted");
-               return 1;
-       }
-       
-       # Attempt to get a virtual disk manager object
-       # This is required to copy virtual disks and perform other operations
-       if (!$service_content->{virtualDiskManager}) {
-               notify($ERRORS{'OK'}, 0, "access to the VM host is restricted, 
virtual disk manager is not available through the vSphere SDK");
-               return 1;
-       }
-       
-       # Get a fileManager object
-       my $file_manager = $self->_get_view($service_content->{fileManager}) || 
return;
-       if (!$file_manager) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine if access to 
the VM host via the vSphere SDK is restricted due to the license, failed to 
retrieve file manager object");
-               return 1;
-       }
-       
-       # Override the die handler because MakeDirectory may call it
-       local $SIG{__DIE__} = sub{};
-
-       # Attempt to create the test directory, check if RestrictedVersion 
fault occurs
-       eval { $file_manager->DeleteDatastoreFile(name => ''); } ;
-       if (my $fault = $@) {
-               if ($fault->isa('SoapFault') && ref($fault->detail) eq 
'RestrictedVersion') {
-                       notify($ERRORS{'OK'}, 0, "access to the VM host via the 
vSphere SDK is restricted due to the license: " . $fault->name);
-                       return 1;
-               }
-               elsif ($fault->isa('SoapFault') && (ref($fault->detail) eq 
'InvalidDatastorePath' || ref($fault->detail) eq 'InvalidArgument')) {
-                       # Do nothing, expected since empty path was passed to 
DeleteDatastoreFile
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to determine if 
access to the VM host via the vSphere SDK is restricted due to the license, 
error:\n$@");
-                       return 1;
-               }
-       }
-       
-       notify($ERRORS{'OK'}, 0, "access to the VM host via the vSphere SDK is 
NOT restricted due to the license");
-       
-       return 0;
-}
-
-##############################################################################
-
-=head1 OS FUNCTIONALITY OBJECT METHODS
-
-=cut
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 create_directory
-
- Parameters  : $directory_path
- Returns     : boolean
- Description : Creates a directory on a datastore on the VM host using the
-               vSphere SDK.
-
-=cut
-
-sub create_directory {
-       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 and check the directory path argument
-       my $directory_path = $self->_get_datastore_path(shift) || return;
-       
-       # Check if the directory already exists
-       return 1 if $self->file_exists($directory_path);
-       
-       # Get the VM host name
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       # Get a fileManager object
-       my $file_manager = $self->_get_file_manager_view() || return;
-       
-       # Override the die handler because MakeDirectory may call it
-       local $SIG{__DIE__} = sub{};
-
-       # Attempt to create the directory
-       eval { $file_manager->MakeDirectory(name => $directory_path,
-                                                                               
                        datacenter => $self->_get_datacenter_view(),
-                                                                               
                        createParentDirectories => 1);
-       };
-       
-       if ($@) {
-               if ($@->isa('SoapFault') && ref($@->detail) eq 
'FileAlreadyExists') {
-                       notify($ERRORS{'DEBUG'}, 0, "directory already exists: 
'$directory_path'");
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to create 
directory: '$directory_path'\nerror:\n$@");
-                       return;
-               }
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "created directory: 
'$directory_path'");
-               return 1;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 delete_file
-
- Parameters  : $file_path
- Returns     : boolean
- Description : Deletes the file from a datastore on the VM host. Wildcards may
-               not be used in the file path argument.
-
-=cut
-
-sub delete_file {
-       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 and check the file path argument
-       my $path_argument = shift;
-       if (!$path_argument) {
-               notify($ERRORS{'WARNING'}, 0, "path argument was not 
specified");
-               return;
-       }
-       
-       my $datastore_path = $self->_get_datastore_path($path_argument);
-       if (!$datastore_path) {
-               notify($ERRORS{'WARNING'}, 0, "failed to convert path argument 
to datastore path: $path_argument");
-               return;
-       }
-       
-       # Sanity check, make sure the file path argument is not the root of a 
datastore
-       # Otherwise everything in the datastore would be deleted
-       if ($datastore_path =~ /^\[.+\]$/) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called with the 
file path argument pointing to the root of a datastore, this would cause all 
datastore contents to be deleted\nfile path argument: 
'$path_argument'\ndatastore path: '$datastore_path'");
-               return;
-       }
-       
-       # Get a fileManager object
-       my $file_manager = $self->_get_file_manager_view() || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-
-       # Attempt to delete the file
-       notify($ERRORS{'OK'}, 0, "attempting to delete file: $datastore_path");
-       eval { $file_manager->DeleteDatastoreFile(name => $datastore_path, 
datacenter => $self->_get_datacenter_view()); };
-       if ($@) {
-               if ($@->isa('SoapFault') && ref($@->detail) eq 'FileNotFound') {
-                       notify($ERRORS{'DEBUG'}, 0, "file does not exist: 
$datastore_path");
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to delete file: 
$datastore_path, error:\n$@");
-                       return;
-               }
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "deleted file: $datastore_path");
-               return 1;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 copy_file
-
- Parameters  : $source_file_path, $destination_file_path
- Returns     : boolean
- Description : Copies a file from one datastore location on the VM host to
-               another datastore location on the VM host. Wildcards may not be
-               used in the file path argument.
-
-=cut
-
-sub copy_file {
-       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 and check the file path arguments
-       my $source_file_path = $self->_get_datastore_path(shift) || return;
-       my $destination_file_path = $self->_get_datastore_path(shift) || return;
-       
-       # Get the VM host name
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       # Get the destination directory path and create the directory if it 
doesn't exit
-       my $destination_directory_path = 
$self->_get_parent_directory_datastore_path($destination_file_path) || return;
-       $self->create_directory($destination_directory_path) || return;
-       
-       # Get a fileManager object
-       my $file_manager = $self->_get_file_manager_view() || return;
-       my $datacenter = $self->_get_datacenter_view() || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       # Attempt to copy the file
-       notify($ERRORS{'DEBUG'}, 0, "attempting to copy file on VM host 
$vmhost_hostname: '$source_file_path' --> '$destination_file_path'");
-       eval { $file_manager->CopyDatastoreFile(sourceName => $source_file_path,
-                                                                               
                                 sourceDatacenter => $datacenter,
-                                                                               
                                 destinationName => $destination_file_path,
-                                                                               
                                 destinationDatacenter => $datacenter,
-                                                                               
                                 force => 0);
-       };
-       
-       # Check if an error occurred
-       if ($@) {
-               if ($@->isa('SoapFault') && ref($@->detail) eq 'FileNotFound') {
-                       notify($ERRORS{'WARNING'}, 0, "source file does not 
exist on VM host $vmhost_hostname: '$source_file_path'");
-                       return 0;
-               }
-               elsif ($@->isa('SoapFault') && ref($@->detail) eq 
'FileAlreadyExists') {
-                       notify($ERRORS{'WARNING'}, 0, "destination file already 
exists on VM host $vmhost_hostname: '$destination_file_path'");
-                       return 0;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to copy file on 
VM host $vmhost_hostname: '$source_file_path' --> 
'$destination_file_path'\nerror:\n$@");
-                       return;
-               }
-       }
-       
-       notify($ERRORS{'OK'}, 0, "copied file on VM host $vmhost_hostname: 
'$source_file_path' --> '$destination_file_path'");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 copy_file_to
-
- Parameters  : $source_file_path, $destination_file_path
- Returns     : boolean
- Description : Copies a file from the management node to a datastore on the VM
-               host. The complete source and destination file paths must be
-               specified. Wildcards may not be used.
-
-=cut
-
-sub copy_file_to {
-       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 source and destination arguments
-       my $source_file_path = normalize_file_path(shift) || return;
-       my $destination_file_path = $self->_get_datastore_path(shift) || return;
-       
-       # Make sure the source file exists on the management node
-       if (!-f $source_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "source file does not exist on 
the management node: '$source_file_path'");
-               return;
-       }
-       
-       # Make sure the destination directory path exists
-       my $destination_directory_path = 
$self->_get_parent_directory_datastore_path($destination_file_path) || return;
-       $self->create_directory($destination_directory_path) || return;
-       sleep 2;
-       
-       # Get the VM host name
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $datacenter_name = $self->_get_datacenter_name();
-       
-       # Get the destination datastore name and relative datastore path
-       my $destination_datastore_name = 
$self->_get_datastore_name($destination_file_path);
-       my $destination_relative_datastore_path = 
$self->_get_relative_datastore_path($destination_file_path);
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-       # Attempt to copy the file -- make a few attempts since this can 
sometimes fail
-    return $self->code_loop_timeout(
-        sub{
-            my $response;
-            eval { $response = VIExt::http_put_file("folder" , 
$source_file_path, $destination_relative_datastore_path, 
$destination_datastore_name, $datacenter_name); };
-            if ($response->is_success) {
-                notify($ERRORS{'DEBUG'}, 0, "copied file from management node 
to VM host: '$source_file_path' --> 
$vmhost_hostname:'[$destination_datastore_name] 
$destination_relative_datastore_path'");
-                return 1;
-            }
-            else {
-                notify($ERRORS{'WARNING'}, 0, "failed to copy file from 
management node to VM host: '$source_file_path' --> 
$vmhost_hostname($datacenter_name):'$destination_file_path'\nerror: " . 
$response->message);
-                return;
-            }
-        }, [], "attempting to copy file from management node to VM host: 
'$source_file_path' --> $vmhost_hostname:'[$destination_datastore_name] 
$destination_relative_datastore_path'", 50, 5);
-
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 copy_file_from
-
- Parameters  : $source_file_path, $destination_file_path
- Returns     : boolean
- Description : Copies file from a datastore on the VM host to the management
-               node. The complete source and destination file paths must be
-               specified. Wildcards may not be used.
-
-=cut
-
-sub copy_file_from {
-       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 source and destination arguments
-       my $source_file_path = $self->_get_datastore_path(shift) || return;
-       my $destination_file_path = normalize_file_path(shift) || return;
-       
-       # Get the destination directory path and make sure the directory exists
-       my $destination_directory_path = 
$self->_get_parent_directory_normal_path($destination_file_path) || return;
-       if (!-d $destination_directory_path) {
-               # Attempt to create the directory
-               my $command = "mkdir -p -v \"$destination_directory_path\" 2>&1 
&& ls -1d \"$destination_directory_path\"";
-               my ($exit_status, $output) = run_command($command, 1);
-               if (!defined($output)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to run command to 
create directory on management node: '$destination_directory_path'\ncommand: 
'$command'");
-                       return;
-               }
-               elsif (grep(/created directory/i, @$output)) {
-                       notify($ERRORS{'OK'}, 0, "created directory on 
management node: '$destination_directory_path'");
-               }
-               elsif (grep(/mkdir: /i, @$output)) {
-                       notify($ERRORS{'WARNING'}, 0, "error occurred 
attempting to create directory on management node: 
'$destination_directory_path':\ncommand: '$command'\nexit status: 
$exit_status\noutput:\n" . join("\n", @$output));
-                       return;
-               }
-               elsif (grep(/^$destination_directory_path/, @$output)) {
-                       notify($ERRORS{'OK'}, 0, "directory already exists on 
management node: '$destination_directory_path'");
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "unexpected output 
returned from command to create directory on management node: 
'$destination_directory_path':\ncommand: '$command'\nexit status: 
$exit_status\noutput:\n" . join("\n", @$output));
-                       return;
-               }
-       }
-       
-       # Get the VM host name
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $datacenter_name = $self->_get_datacenter_name();
-       
-       # Get the source datastore name
-       my $source_datastore_name = 
$self->_get_datastore_name($source_file_path) || return;
-       
-       # Get the source file relative datastore path
-       my $source_file_relative_datastore_path = 
$self->_get_relative_datastore_path($source_file_path) || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-       
-    # Attempt to copy the file -- make a few attempts since this can sometimes 
fail
-    return $self->code_loop_timeout(
-        sub{
-            my $response;
-            eval { $response = VIExt::http_get_file("folder", 
$source_file_relative_datastore_path, $source_datastore_name, $datacenter_name, 
$destination_file_path); };
-            if ($response->is_success) {
-                notify($ERRORS{'DEBUG'}, 0, "copied file from VM host to 
management node: $vmhost_hostname:'[$source_datastore_name] 
$source_file_relative_datastore_path' --> '$destination_file_path'");
-                return 1;
-            }
-            else {
-                notify($ERRORS{'WARNING'}, 0, "failed to copy file from VM 
host to management node: $vmhost_hostname:'[$source_datastore_name] 
$source_file_relative_datastore_path' --> '$destination_file_path'\nerror: " . 
$response->message);
-                return;
-            }
-        }, [], "attempting to copy file from VM host to management node:  
$vmhost_hostname:'[$source_datastore_name] 
$source_file_relative_datastore_path' --> '$destination_file_path'", 50, 5);
-
-}
-
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_file_contents
-
- Parameters  : $file_path
- Returns     : array
- Description : Returns an array containing the contents of the file on the VM
-               host specified by the file path argument. Each array element
-               contains a line in the file.
-
-=cut
-
-sub get_file_contents {
-       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;
-       }
-       
-       # TODO: add file size check before retrieving file in case file is huge
-       
-       # Get the source and destination arguments
-       my ($path) = shift;
-       if (!$path) {
-               notify($ERRORS{'WARNING'}, 0, "file path argument was not 
specified");
-               return;
-       }
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       # Create a temp directory to store the file and construct the temp file 
path
-       # The temp directory is automatically deleted then this variable goes 
out of scope
-       my $temp_directory_path = tempdir( CLEANUP => 1 );
-       my $source_file_name = $self->_get_file_name($path);
-       my $temp_file_path = "$temp_directory_path/$source_file_name";
-       
-       $self->copy_file_from($path, $temp_file_path) || return;
-       
-       # Run cat to retrieve the contents of the file
-       my $command = "cat \"$temp_file_path\"";
-       my ($exit_status, $output) = VCL::utils::run_command($command, 1);
-       if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to run command to read 
file: '$temp_file_path'\ncommand: '$command'");
-               return;
-       }
-       elsif (grep(/^cat: /, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to read contents of file: 
'$temp_file_path', exit status: $exit_status, output:\n" . join("\n", 
@$output));
-               return;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "retrieved " . scalar(@$output) . " 
lines from file: '$temp_file_path'");
-       }
-       
-       # Output lines contain trailing newlines, remove them
-       @$output = map { chomp; $_; } @$output;
-       return @$output;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 move_file
-
- Parameters  : $source_path, $destination_path
- Returns     : boolean
- Description : Moves or renames a file from one datastore location on the VM
-               host to another datastore location on the VM host. Wildcards may
-               not be used in the file path argument.
-
-=cut
-
-sub move_file {
-       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 and check the file path arguments
-       my $source_file_path = $self->_get_datastore_path(shift) || return;
-       my $destination_file_path = $self->_get_datastore_path(shift) || return;
-       
-       # Get the VM host name
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       # Get the destination directory path and create the directory if it 
doesn't exit
-       my $destination_directory_path = 
$self->_get_parent_directory_datastore_path($destination_file_path) || return;
-       $self->create_directory($destination_directory_path) || return;
-       
-       # Get a fileManager and Datacenter object
-       my $file_manager = $self->_get_file_manager_view() || return;
-       my $datacenter = $self->_get_datacenter_view() || return;
-       
-       # Override the die handler
-       local $SIG{__DIE__} = sub{};
-
-       # Attempt to copy the file
-       notify($ERRORS{'DEBUG'}, 0, "attempting to move file on VM host 
$vmhost_hostname: '$source_file_path' --> '$destination_file_path'");
-       eval { $file_manager->MoveDatastoreFile(sourceName => $source_file_path,
-                                                                               
                                 sourceDatacenter => $datacenter,
-                                                                               
                                 destinationName => $destination_file_path,
-                                                                               
                                 destinationDatacenter => $datacenter
-                                                                               
                                 );
-       };
-       
-       if ($@) {
-               if ($@->isa('SoapFault') && ref($@->detail) eq 'FileNotFound') {
-                       notify($ERRORS{'WARNING'}, 0, "source file does not 
exist on VM host $vmhost_hostname: '$source_file_path'");
-                       return 0;
-               }
-               elsif ($@->isa('SoapFault') && ref($@->detail) eq 
'FileAlreadyExists') {
-                       notify($ERRORS{'WARNING'}, 0, "destination file already 
exists on VM host $vmhost_hostname: '$destination_file_path'");
-                       return 0;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to move file on 
VM host $vmhost_hostname: '$source_file_path' --> '$destination_file_path', 
error:\n$@");
-                       return;
-               }
-       }
-       
-       notify($ERRORS{'OK'}, 0, "moved file on VM host $vmhost_hostname: 
'$source_file_path' --> '$destination_file_path'");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 file_exists
-
- Parameters  : $file_path
- Returns     : boolean
- Description : Determines if a file exists on a datastore on the VM host.
-
-=cut
-
-sub file_exists {
-       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 and check the file path argument
-       my $file_path = $self->_get_datastore_path(shift) || return;
-       
-       # Check if the path argument is the root of a datastore
-       if ($file_path =~ /^\[(.+)\]$/) {
-               my $datastore_name = $1;
-               (my @datastore_names = $self->_get_datastore_names()) || return;
-               
-               if (grep(/^$datastore_name$/, @datastore_names)) {
-                       notify($ERRORS{'DEBUG'}, 0, "file (datastore root) 
exists: $file_path");
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "file (datastore root) does 
not exist: $file_path, datastores on VM host:\n" . join("\n", 
@datastore_names));
-                       return 0;
-               }
-       }
-       
-       # Take the path apart, get the filename and parent directory path
-       my $base_directory_path = 
$self->_get_parent_directory_datastore_path($file_path) || return;
-       my $file_name = $self->_get_file_name($file_path) || return;
-       
-       my $result = $self->find_files($base_directory_path, $file_name);
-       if ($result) {
-               notify($ERRORS{'DEBUG'}, 0, "file exists: $file_path");
-               return 1;
-       }
-       elsif (defined($result)) {
-               notify($ERRORS{'DEBUG'}, 0, "file does not exist: $file_path");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to determine if file 
exists: $file_path");
-               return;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_file_size
-
- Parameters  : $file_path
- Returns     : integer
- Description : Determines the size of a file of a datastore in bytes. Wildcards
-               may be used in the file path argument. The total size of all
-               files found will be returned. Subdirectories are not searched.
-
-=cut
-
-sub get_file_size {
-       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 and check the file path argument
-       my $file_path_argument = shift;
-       if (!$file_path_argument) {
-               notify($ERRORS{'WARNING'}, 0, "file path argument was not 
specified");
-               return;
-       }
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       # Get the file info
-       my $file_info = $self->_get_file_info($file_path_argument);
-       if (!defined($file_info)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to get file size, failed 
to get file info for: $file_path_argument");
-               return;
-       }
-       
-       # Make sure the file info is not null or else an error occurred
-       if (!$file_info) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve info for file 
on $vmhost_hostname: $file_path_argument");
-               return;
-       }
-       
-       # Check if there are any keys in the file info hash - no keys indicates 
no files were found
-       if (!keys(%{$file_info})) {
-               notify($ERRORS{'DEBUG'}, 0, "unable to determine size of file 
on $vmhost_hostname because it does not exist: $file_path_argument");
-               return;
-       }
-       
-       # Loop through the files, add their sizes to the total
-       my $total_size_bytes = 0;
-       for my $file_path (keys(%{$file_info})) {
-               my $file_size_bytes = $file_info->{$file_path}{fileSize};
-               notify($ERRORS{'DEBUG'}, 0, "size of '$file_path': " . 
format_number($file_size_bytes) . " bytes");
-               $total_size_bytes += $file_size_bytes;
-       }
-       
-       my $total_size_bytes_string = format_number($total_size_bytes);
-       my $total_size_mb_string = format_number(($total_size_bytes / 1024 / 
1024), 2);
-       my $total_size_gb_string = format_number(($total_size_bytes / 1024 / 
1024 /1024), 2);
-       
-       notify($ERRORS{'DEBUG'}, 0, "total file size of '$file_path_argument': 
$total_size_bytes_string bytes ($total_size_mb_string MB, $total_size_gb_string 
GB)");
-       return $total_size_bytes;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 find_files
-
- Parameters  : $base_directory_path, $search_pattern, $search_subdirectories 
(optional)
- Returns     : array
- Description : Finds files in a datastore on the VM host stored under the base
-               directory path argument. The search pattern may contain
-               wildcards. Subdirectories will be searched if the 3rd argument 
is
-               not supplied.
-
-=cut
-
-sub find_files {
-       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 arguments
-       my ($base_directory_path, $search_pattern, $search_subdirectories) = @_;
-       if (!$base_directory_path || !$search_pattern) {
-               notify($ERRORS{'WARNING'}, 0, "base directory path and search 
pattern arguments were not specified");
-               return;
-       }
-       
-       $search_subdirectories = 1 if !defined($search_subdirectories);
-       
-       $base_directory_path = $self->_get_normal_path($base_directory_path) || 
return;
-       
-       # Get the file info
-       my $file_info = 
$self->_get_file_info("$base_directory_path/$search_pattern", 
$search_subdirectories);
-       if (!defined($file_info)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to find files, failed to 
get file info for: $base_directory_path/$search_pattern");
-               return;
-       }
-       
-       # Loop through the keys of the file info hash
-       my @file_paths;
-       for my $file_path (keys(%{$file_info})) {
-               # Add the file path to the return array
-               push @file_paths, $self->_get_normal_path($file_path);
-               
-               # vmdk files will have a diskExtents key
-               # The extents must be added to the return array
-               if (defined($file_info->{$file_path}->{diskExtents})) {
-                       for my $disk_extent 
(@{$file_info->{$file_path}->{diskExtents}}) {
-                               # Convert the datastore file paths to normal 
file paths
-                               $disk_extent = 
$self->_get_normal_path($disk_extent);
-                               push @file_paths, 
$self->_get_normal_path($disk_extent);
-                       }
-               }
-       }
-       
-       @file_paths = sort @file_paths;
-       notify($ERRORS{'DEBUG'}, 0, "matching file count: " . 
scalar(@file_paths));
-       return @file_paths;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
- 
-=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
-
- Parameters  : $path
- Returns     : integer
- Description : Returns the bytes available in the path specified by the
-               argument.
-
-=cut
-
-sub get_available_space {
-       my $self = shift;
-       if (ref($self) !~ /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(1) || return;
-       
-       my $available_bytes = $datastore_info->{$datastore_name}{freeSpace};
-       if (!defined($available_bytes)) {
-               notify($ERRORS{'WARNING'}, 0, "datastore $datastore_name 
freeSpace key does not exist in datastore info:\n" . 
format_data($datastore_info));
-               return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "space available in $datastore_name 
datastore on $vmhost_hostname: " . get_file_size_info_string($available_bytes));
-       return $available_bytes;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_cpu_core_count
-
- Parameters  : none
- Returns     : integer
- Description : Retrieves the quantitiy of CPU cores the VM host has.
-
-=cut
-
-sub get_cpu_core_count {
-       my $self = shift;
-       if (ref($self) !~ /module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       return $self->{cpu_core_count} if $self->{cpu_core_count};
-       
-       my $cpu_core_count;
-       if (my $host_system_view = $self->_get_host_system_view()) {
-               my $vmhost_hostname = $self->data->get_vmhost_hostname();
-               $cpu_core_count = 
$host_system_view->{hardware}->{cpuInfo}->{numCpuCores};
-               notify($ERRORS{'DEBUG'}, 0, "retrieved CPU core count for VM 
host '$vmhost_hostname': $cpu_core_count");
-       }
-       elsif (my $cluster = $self->_get_cluster_view()) {
-               # Try to get CPU core count of cluster if cluster is being used
-               my $cluster_name = $cluster->{name};
-               $cpu_core_count = $cluster->{summary}->{numCpuCores};
-               notify($ERRORS{'DEBUG'}, 0, "retrieved CPU core count for 
'$cluster_name' cluster: $cpu_core_count");
-       
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine CPU core 
count of VM host");
-               return;
-       }
-       
-       $self->{cpu_core_count} = $cpu_core_count;
-       return $self->{cpu_core_count};
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_cpu_speed
-
- Parameters  : none
- Returns     : integer
- Description : Retrieves the speed of the VM host's CPUs in MHz.
-
-=cut
-
-sub get_cpu_speed {
-       my $self = shift;
-       if (ref($self) !~ /module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       return $self->{cpu_speed} if $self->{cpu_speed};
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       # Try to get CPU speed of resource pool
-       if (my $resource_pool = $self->_get_resource_pool_view()) {
-               my $resource_pool_name = $resource_pool->{name};
-               
-               my $mhz = $resource_pool->{runtime}{cpu}{maxUsage};
-               
-               # maxUsage reports sum of all CPUs - divide by core count
-               # This isn't exact - will be lower than acutal clock rate of 
CPUs in host
-               if (my $cpu_core_count = $self->get_cpu_core_count()) {
-                       $mhz = int($mhz / $cpu_core_count);
-               }
-               
-               $self->{cpu_speed} = $mhz;
-               notify($ERRORS{'DEBUG'}, 0, "retrieved total CPU speed of 
'$resource_pool_name' resource pool: $self->{cpu_speed} MHz");
-               return $self->{cpu_speed};
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine CPU speed of 
VM host, resource pool view object could not be retrieved");
-               return;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_total_memory
-
- Parameters  : none
- Returns     : integer
- Description : Retrieves the VM host's total memory capacity in MB.
-
-=cut
-
-sub get_total_memory {
-       my $self = shift;
-       if (ref($self) !~ /module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       return $self->{total_memory} if $self->{total_memory};
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       
-       # Try to get total memory of resource pool
-       if (my $resource_pool = $self->_get_resource_pool_view()) {
-               my $resource_pool_name = $resource_pool->{name};
-               
-               my $memory_bytes = $resource_pool->{runtime}{memory}{maxUsage};
-               my $memory_mb = int($memory_bytes / 1024 / 1024);
-               
-               $self->{total_memory} = $memory_mb;
-               notify($ERRORS{'DEBUG'}, 0, "retrieved total memory of 
'$resource_pool_name' resource pool: $self->{total_memory} MB");
-               return $self->{total_memory};
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine total memory 
on VM host, resource pool view object could not be retrieved");
-               return;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_license_info
-
- Parameters  : none

[... 5038 lines stripped ...]

Reply via email to