Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm?rev=1798487&r1=1798486&r2=1798487&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm Mon 
Jun 12 16:33:35 2017
@@ -1,4007 +1,4007 @@
-#!/usr/bin/perl -w
-###############################################################################
-# $Id: VIM_SSH.pm 952366 2010-06-07 18:59:25Z arkurth $
-###############################################################################
-# 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::VIM_SSH;
-
-=head1 SYNOPSIS
-
- my $vmhost_datastructure = $self->get_vmhost_datastructure();
- my $VIM_SSH = VCL::Module::Provisioning::VMware::VIM_SSH->new({data_structure 
=> $vmhost_datastructure});
- my @registered_vms = $VIM_SSH->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.
-
-=cut
-
-###############################################################################
-package VCL::Module::Provisioning::VMware::VIM_SSH;
-
-# 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.4.2';
-
-# Specify the version of Perl to use
-use 5.008000;
-
-use strict;
-use warnings;
-use diagnostics;
-
-use English '-no_match_vars';
-use VCL::utils;
-
-###############################################################################
-
-=head1 PRIVATE 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;
-       }
-       
-       my $args  = shift;
-       
-       if (!defined($self->{vmhost_os})) {
-               # 
-               if (!defined $args->{vmhost_os}) {
-                       notify($ERRORS{'WARNING'}, 0, "required 'vmhost_os' 
argument was not passed");
-                       return;
-               }
-               
-               # 
-               if (ref $args->{vmhost_os} !~ /VCL::Module::OS/) {
-                       notify($ERRORS{'CRITICAL'}, 0, "'vmhost_os' argument 
passed is not a reference to a VCL::Module::OS object, type: " . 
ref($args->{vmhost_os}));
-                       return;
-               }
-       
-               # 
-               $self->{vmhost_os} = $args->{vmhost_os};
-       }
-       
-       if (!$self->vmhost_os) {
-               return;
-       }
-       
-       my @required_vmhost_os_subroutines = (
-               'execute',
-       );
-       
-       for my $required_vmhost_os_subroutine (@required_vmhost_os_subroutines) 
{
-               if (!$self->vmhost_os->can($required_vmhost_os_subroutine)) {
-                       notify($ERRORS{'WARNING'}, 0, "required VM host OS 
subroutine is not implemented: $required_vmhost_os_subroutine");
-                       return;
-               }
-       }
-       
-       # Determine which VIM executable is installed on the VM host
-       my $command = 'vim-cmd ; vmware-vim-cmd';
-       my ($exit_status, $output) = $self->vmhost_os->execute($command);
-       if (!defined($output)) {
-               notify($ERRORS{'OK'}, 0, "VIM executable is not available on 
the VM host");
-               return;
-       }
-       elsif (!grep(/vmsvc/, @$output)) {
-               # String 'vmsvc' does not exist in the output, neither of the 
commands worked
-               notify($ERRORS{'DEBUG'}, 0, "VIM executable is not available on 
the VM host, output:\n" . join("\n", @$output));
-               return;
-       }
-       elsif (grep(/: vim-cmd:.*not found/i, @$output)) {
-               # Output contains the line: 'vim-cmd: command not found'
-               $self->{vim_cmd} = 'vmware-vim-cmd';
-       }
-       else {
-               # Output contains the line: 'vmware-vim-cmd: command not found'
-               # Note: VMware ESX 4.1 has BOTH vim-cmd and vmware-vim-cmd
-               $self->{vim_cmd} = 'vim-cmd';
-       }
-       notify($ERRORS{'DEBUG'}, 0, "VIM executable available on VM host: 
$self->{vim_cmd}");
-       
-       notify($ERRORS{'DEBUG'}, 0, ref($self) . " object initialized");
-       return 1;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _run_vim_cmd
-
- Parameters  : $vim_arguments, $timeout_seconds (optional), $attempt_limit 
(optional)
- Returns     : array ($exit_status, $output)
- Description : Runs vim-cmd command on the VMware host. This was designed to
-               allow it to handle most of the error checking.
-               
-               By default, 5 attempts are made.
-               
-               If the exit status of the vim-cmd command is 0 after any 
attempt,
-               $exit_status and $output are returned to the calling subroutine.
-               
-               If the exit $attempt_limit > 1 and the status is not 0 after all
-               attempts are made, undefined is returned. This allows the 
calling
-               subroutine to simply check if result is true if it does not care
-               about the output.
-               
-               There is a special condition if the $attempt_limit is 1 and the
-               exit status is not 0. $exit_status and $output are always
-               returned so calling subroutine can handle the logic.
-
-=cut
-
-sub _run_vim_cmd {
-       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 $vim_arguments = shift;
-       if (!$vim_arguments) {
-               notify($ERRORS{'WARNING'}, 0, "VIM command arguments were not 
specified");
-               return;
-       }
-       
-       my $timeout_seconds = shift || 60;
-       my $attempt_limit = shift || 5;
-       
-       my $request_state_name = $self->data->get_request_state_name();
-       my $vmhost_computer_name = 
$self->vmhost_os->data->get_computer_short_name();
-       
-       my $command = "$self->{vim_cmd} $vim_arguments";
-       
-       my $attempt = 0;
-       my $wait_seconds = 5;
-       
-       my $connection_reset_errors = 0;
-       
-       ATTEMPT: while ($attempt++ < $attempt_limit) {
-               
-               my $semaphore;
-               if ($attempt > 1) {
-                       # Wait before making next attempt
-                       notify($ERRORS{'OK'}, 0, "sleeping $wait_seconds 
seconds before making attempt $attempt/$attempt_limit");
-                       sleep_uninterrupted($wait_seconds);
-                       $semaphore = 
$self->get_semaphore($vmhost_computer_name, 120, 1) || next ATTEMPT;
-               }
-               
-               # The following error is somewhat common if several processes 
are adding/removing VMs at the same time:
-               # (vmodl.fault.ManagedObjectNotFound) {
-               #        dynamicType = <unset>,
-               #        faultCause = (vmodl.MethodFault) null,
-               #        obj = 'vim.VirtualMachine:672',
-               #        msg = "The object has already been deleted or has not 
been completely created",
-               # }
-               
-               # Keep a count of the number of times vim-cmd is executed for 
the entire vcld state process
-               # This will be used to improve performance by reducing the 
number of calls necessary
-               $self->{vim_cmd_calls}++;
-               #notify($ERRORS{'DEBUG'}, 0, "vim-cmd call count: 
$self->{vim_cmd_calls} ($vim_arguments)");
-               
-               #my $register_semaphore;
-               #if ($command =~ /(getallvms|register)/) {
-               #       $register_semaphore = 
$self->get_semaphore($vmhost_computer_name, 120, 1);
-               #       if (!$register_semaphore) {
-               #               next ATTEMPT;
-               #       }
-               #}
-               
-               my ($exit_status, $output) = $self->vmhost_os->execute({
-                       'command' => $command,
-                       'display_output' => 0,
-                       'timeout_seconds' => $timeout_seconds,
-                       #'max_attempts' => 1
-               });
-               
-               if (!defined($output)) {
-                       notify($ERRORS{'WARNING'}, 0, "attempt 
$attempt/$attempt_limit: failed to run VIM command on VM host 
$vmhost_computer_name: $command");
-               }
-               elsif (grep(/already been deleted/i, @$output)) {
-                       notify($ERRORS{'OK'}, 0, "attempt 
$attempt/$attempt_limit: fault occurred attempting to run command on VM host 
$vmhost_computer_name: $command, output:\n" . join("\n", @$output));
-               }
-               elsif (grep(/(Failed to login|connection reset|SSL 
Exception)/i, @$output)) {
-                       # Try to catch these errors:
-                       # Failed to login: Connection reset by peer
-                       # Failed to login: SSL Exception: The SSL handshake 
timed out local: 127.0.0.1:52713 peer: 127.0.0.1:443.
-                       $connection_reset_errors++;
-                       notify($ERRORS{'OK'}, 0, "attempt 
$attempt/$attempt_limit: connection reset while attempting to run command on VM 
host $vmhost_computer_name: $command, output:\n" . join("\n", @$output));
-                       
-                       # If 2 connection reset errors occured, attempt to run 
services.sh restart
-                       if ($connection_reset_errors == 2) {
-                               if ($self->{services_restarted}) {
-                                       notify($ERRORS{'WARNING'}, 0, 
"encountered $connection_reset_errors connection reset errors on VM host 
$vmhost_computer_name, not calling 'services.sh restart', it was already 
attempted");
-                               }
-                               else {
-                                       notify($ERRORS{'OK'}, 0, "calling 
'services.sh restart', encountered $connection_reset_errors connection reset 
errors on VM host $vmhost_computer_name");
-                                       $self->_services_restart();
-                                       $self->{services_restarted} = 1;
-                                       next ATTEMPT;
-                               }
-                       }
-                       elsif ($connection_reset_errors > 2) {
-                               notify($ERRORS{'WARNING'}, 0, "encountered 
$connection_reset_errors connection reset errors on VM host 
$vmhost_computer_name");
-                       }
-                       else {
-                               next ATTEMPT;
-                       }
-                       
-                       # Problem probably won't correct itself
-                       # If request state is 'inuse', set the 
reservation.lastcheck value to 20 minutes before request.end
-                       # This avoids 'inuse' processes from being created over 
and over again which will fail
-                       if ($request_state_name eq 'inuse') {
-                               my $reservation_id = 
$self->data->get_reservation_id();
-                               my $request_end_time_epoch = 
convert_to_epoch_seconds($self->data->get_request_end_time());
-                               my $current_time_epoch = time;
-                               my $reservation_lastcheck_epoch = 
($request_end_time_epoch-(20*60));
-                               
set_reservation_lastcheck($reservation_lastcheck_epoch, $reservation_id);
-                       }
-                       return;
-               }
-               elsif (grep(/^(vim-cmd:|Killed|terminate 
called|Aborted|what\()/i, @$output)) {
-                       # terminate called after throwing an instance of 
'std::bad_alloc'
-                       # what():  std::bad_alloc
-                       # Aborted
-                       notify($ERRORS{'WARNING'}, 0, "attempt 
$attempt/$attempt_limit: failed to execute command on VM host 
$vmhost_computer_name: $command, exit status: $exit_status, output:\n" . 
join("\n", @$output));
-                       next ATTEMPT;
-               }
-               elsif ($exit_status != 0) {
-                       if ($attempt_limit == 1) {
-                               notify($ERRORS{'DEBUG'}, 0, "command failed on 
VM host $vmhost_computer_name, not making another attempt because attempt limit 
argument is set to $attempt_limit, error checking will be done by calling 
subroutine, command: $command, exit status: $exit_status, output:\n" . 
join("\n", @$output));
-                               return ($exit_status, $output);
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "attempt 
$attempt/$attempt_limit: command failed on VM host $vmhost_computer_name: 
$command, exit status: $exit_status, output:\n" . join("\n", @$output));
-                               next ATTEMPT;
-                       }
-               }
-               else {
-                       # VIM command command was executed
-                       if ($attempt > 1) {
-                               notify($ERRORS{'DEBUG'}, 0, "attempt 
$attempt/$attempt_limit: executed command on VM host $vmhost_computer_name: 
$command, exit status: $exit_status");
-                       }
-                       else {
-                               notify($ERRORS{'DEBUG'}, 0, "executed command 
on VM host $vmhost_computer_name: $command, exit status: $exit_status");
-                       }
-                       return ($exit_status, $output);
-               }
-       }
-       
-       notify($ERRORS{'WARNING'}, 0, "failed to run VIM command on VM host 
$vmhost_computer_name: '$command', made $attempt_limit attempts");
-       return;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _services_restart
-
- Parameters  : none
- Returns     : boolean
- Description : Calls 'services.sh restart' on the VM host. This may resolve
-               problems where the host is not responding due to a problem with
-               one or more services. This should rarely be called.
-
-=cut
-
-sub _services_restart {
-       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 $vmhost_computer_name = 
$self->vmhost_os->data->get_computer_short_name();
-       
-       my $semaphore = 
$self->get_semaphore("$vmhost_computer_name-vmware_services_restart", 0);
-       if (!$semaphore) {
-               notify($ERRORS{'OK'}, 0, "unable to obtain semaphore, another 
process is likely restarting services on $vmhost_computer_name, sleeping for 30 
seconds and then proceeding");
-               sleep_uninterrupted(30);
-               return 1;
-       }
-       
-       my $check_services = {
-               'hostd-worker' => '/var/run/vmware/vmware-hostd.PID',
-               'sfcb-vmware_bas' => '/var/run/vmware/vicimprovider.PID',
-               'vmkdevmgr' => '/var/run/vmware/vmkdevmgr.pid',
-               'vmkeventd' => '/var/run/vmware/vmkeventd.pid',
-               'vmsyslogd' => '/var/run/vmware/vmsyslogd.pid',
-               'rhttpproxy-work' => '/var/run/vmware/vmware-rhttpproxy.PID',
-               'vpxa-worker' => '/var/run/vmware/vmware-vpxa.PID',
-       };
-       
-       # Check if the PID files for the following services are correct
-       for my $service_name (keys %$check_services) {
-               my $pid_file_path = $check_services->{$service_name};
-               $self->_check_service_pid($service_name, $pid_file_path);
-       }
-       
-       my $services_command = "services.sh restart";
-       notify($ERRORS{'DEBUG'}, 0, "restarting VMware services on 
$vmhost_computer_name");
-       my ($services_exit_status, $services_output) = 
$self->vmhost_os->execute($services_command, 0, 120);
-       if (!defined($services_output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to run command on VM host 
$vmhost_computer_name: $services_command");
-               return;
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "executed command to restart VMware 
services on $vmhost_computer_name, command: '$services_command', output:\n" . 
join("\n", @$services_output));
-       }
-       return 1;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _check_service_pid
-
- Parameters  : $process_name, $pid_file_path
- Returns     : boolean
- Description : Checks if the PID stored in the PID file matches the parent PID
-               of the running service process. Problems occur if the file does
-               not match the running process PID. Most often, vim-cmd commands
-               fail with an error such as:
-               Connect to localhost failed: Connection failure
-               
-               The PID file is updated with the correct PID if the PID file
-               contents cannot be retrieved and parsed or if the PID stored in
-               the file does not match the running process.
-
-=cut
-
-sub _check_service_pid {
-       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 ($process_name, $pid_file_path) = @_;
-       if (!defined($process_name) || !defined($pid_file_path)) {
-               notify($ERRORS{'WARNING'}, 0, "process name and PID file path 
arguments were not supplied");
-               return;
-       }
-       
-       my $vmhost_computer_name = 
$self->vmhost_os->data->get_computer_short_name();
-       
-       # Retrieve the running PID
-       my $running_pid;
-       my $ps_command = "ps |grep $process_name |awk '{print \$2}'";
-       my ($ps_exit_status, $ps_output) = 
$self->vmhost_os->execute($ps_command);
-       if (!defined($ps_output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to run command to 
determine main $process_name PID on $vmhost_computer_name");
-       }
-       else {
-               ($running_pid) = "@$ps_output" =~ /(\d+)/g;
-               if ($running_pid && $running_pid > 1) {
-                       notify($ERRORS{'DEBUG'}, 0, "retrieved parent 
$process_name PID: $running_pid");
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "parent $process_name 
process is not running");
-               }
-       }
-       
-       # Check if the .pid file exists
-       my $pid_file_exists = $self->vmhost_os->file_exists($pid_file_path);
-       if (!$running_pid) {
-               if ($pid_file_exists) {
-                       notify($ERRORS{'DEBUG'}, 0, "running $process_name 
process was not detected but PID file exists: $pid_file_path, deleting file");
-                       if ($self->vmhost_os->delete_file($pid_file_path)) {
-                               notify($ERRORS{'DEBUG'}, 0, "deleted file on 
$vmhost_computer_name: $pid_file_path");
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "failed to delete 
file on $vmhost_computer_name: $pid_file_path");
-                       }
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "running $process_name 
process was not detected and PID file does not exist: $pid_file_path");
-                       return 1;
-               }
-       }
-       else {
-               if ($pid_file_exists) {
-                       # Retrieve the PID stored in the PID file
-                       my @pid_file_contents = 
$self->vmhost_os->get_file_contents($pid_file_path);
-                       if (@pid_file_contents) {
-                               my ($file_pid) = "@pid_file_contents" =~ 
/(\d+)/g;
-                               if ($file_pid) {
-                                       notify($ERRORS{'DEBUG'}, 0, "retrieved 
PID stored in $pid_file_path: $file_pid");
-                                       if ($file_pid eq $running_pid) {
-                                               notify($ERRORS{'OK'}, 0, "PID 
in $pid_file_path ($file_pid) matches PID of parent $process_name process 
($running_pid), update not necessary");
-                                               return 1;
-                                       }
-                                       else {
-                                               notify($ERRORS{'OK'}, 0, "PID 
in $pid_file_path ($file_pid) does not match PID of parent $process_name 
process ($running_pid), updating $pid_file_path to contain $running_pid");
-                                       }
-                               }
-                               else {
-                                       notify($ERRORS{'WARNING'}, 0, "unable 
to determine PID stored in $pid_file_path, contents:\n" . join("\n", 
@pid_file_contents));
-                               }
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "failed to 
retrieve contents of $pid_file_path");
-                       }
-               }
-               
-               # Update the PID file with the correct PID
-               my $echo_command = "echo -n $running_pid > $pid_file_path";
-               my ($echo_exit_status, $echo_output) = 
$self->vmhost_os->execute($echo_command);
-               if (!defined($echo_output)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to run command to 
update $pid_file_path on $vmhost_computer_name");
-                       return;
-               }
-               elsif (grep(/(ash:|echo:)/, @$echo_output)) {
-                       notify($ERRORS{'WARNING'}, 0, "error occurred updating 
$pid_file_path on $vmhost_computer_name, command: '$echo_command', output:\n" . 
joini("\n", @$echo_output));
-                       return;
-               }
-               else {
-                       notify($ERRORS{'OK'}, 0, "updated $pid_file_path on 
$vmhost_computer_name to contain the correct PID: $running_pid");
-               }
-       }
-       
-       return 1;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _get_vm_list
-
- Parameters  : none
- Returns     : hash
- Description : Returns an hash with keys containing the IDs of the VMs running
-               on the VM host. The values are the vmx file paths.
-
-=cut
-
-sub _get_vm_list {
-       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 $vim_cmd_arguments = "vmsvc/getallvms";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # Check the vim-cmd output
-       # Format of the output from "vim-cmd vmsvc/getallvms":
-       # Vmid Name                                                          
File                                                              Guest OS      
  Version Annotation
-       # 496  vm-ark-mcnc-9 (nonpersistent: vmwarewinxp-base234-v12)        
[nfs-datastore] vm-ark-mcnc-9_234-v12/vm-ark-mcnc-9_234-v12.vmx   winXPProGuest 
  vmx-04      
-       # 512  vm-ark-mcnc-10 (nonpersistent: vmwarelinux-centosbase1617-v1) 
[nfs-datastore] vm-ark-mcnc-10_1617-v1/vm-ark-mcnc-10_1617-v1.vmx 
otherLinuxGuest vmx-04
-       if (!grep(/Vmid\s+Name/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine VM IDs, 
unexpected output returned, VIM command arguments: '$vim_cmd_arguments', 
output:\n" . join("\n", @$output));
-               return;
-       }
-       
-       my %vms;
-       for my $line (@$output) {
-               my ($vm_id, $vmx_file_path) = $line =~ /^(\d+).*(\[.+\.vmx)/;
-               
-               # Skip lines that don't begin with a number
-               next if !defined($vm_id);
-               
-               # Make sure the vmx file path was parsed
-               if (!$vmx_file_path) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to determine vmx 
file path, VIM command arguments: '$vim_cmd_arguments', output line: $line");
-                       return;
-               }
-               
-               # Get the normal path
-               my $vmx_normal_path = $self->_get_normal_path($vmx_file_path);
-               if (!$vmx_normal_path) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to determine 
normal path: $vmx_file_path");
-                       #return;
-               }
-               
-               $vms{$vm_id} = $vmx_normal_path;
-       }
-       
-       #notify($ERRORS{'DEBUG'}, 0, "registered VMs IDs found: " . keys(%vms));
-       return \%vms;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _get_vm_id
-
- Parameters  : $vmx_file_path
- Returns     : integer
- Description : 
-
-=cut
-
-sub _get_vm_id {
-       my $self = shift;
-       if (ref($self) !~ /VCL::Module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
specified");
-               return;
-       }
-       
-       return $self->{vm_id}{$vmx_file_path} if $self->{vm_id}{$vmx_file_path};
-       
-       # Get the VM IDs and vmx paths
-       my $vm_list = $self->_get_vm_list();
-       if (!defined($vm_list)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine VM ID, 
failed to retrieve list of registered VMs and their IDs");
-               return;
-       }
-       
-       for my $vm_id (keys %$vm_list) {
-               if ($vm_list->{$vm_id} && $vmx_file_path eq $vm_list->{$vm_id}) 
{
-                       $self->{vm_id}{$vmx_file_path} = $vm_id;
-                       return $vm_id;
-               }
-       }
-       
-       notify($ERRORS{'WARNING'}, 0, "unable to determine VM ID, vmx file is 
not registered: $vmx_file_path, registered VMs:\n" . format_data($vm_list));
-       return;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _get_vm_summary
-
- Parameters  : $vm_id
- Returns     : string
- Description : Runs "vim-cmd vmsvc/get.summary <VM ID>" to retrive a summary
-               of the configuration of a VM.
-
-=cut
-
-sub _get_vm_summary {
-       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 file path argument
-       my $vmx_file_path = shift || $self->get_vmx_file_path();
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument could not 
be determined");
-               return;
-       }
-       
-       my $vm_id = $self->_get_vm_id($vmx_file_path) || return;
-       
-       my $vim_cmd_arguments = "vmsvc/get.summary $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # The output should look like this:
-       # Listsummary:
-       # (vim.vm.Summary) {
-       #   dynamicType = <unset>,
-       #   vm = 'vim.VirtualMachine:496',
-       #   runtime = (vim.vm.RuntimeInfo) {
-       #      dynamicType = <unset>,
-       #      host = 'vim.HostSystem:ha-host',
-       #      connectionState = "connected",
-       #      powerState = "poweredOn",
-       #      faultToleranceState = "notConfigured",
-       #      toolsInstallerMounted = false,
-       #      suspendTime = <unset>,
-       #      bootTime = "2010-06-08T14:26:48.658743Z",
-       #      suspendInterval = 0,
-       #      question = (vim.vm.QuestionInfo) null,
-       #      memoryOverhead = 119189504,
-       #      maxCpuUsage = 2000,
-       #      maxMemoryUsage = 1024,
-       #      numMksConnections = 0,
-       #      recordReplayState = "inactive",
-       #      cleanPowerOff = <unset>,
-       #      needSecondaryReason = <unset>,
-       #   },
-       #   guest = (vim.vm.Summary.GuestSummary) {
-       #      dynamicType = <unset>,
-       #      guestId = "winXPProGuest",
-       #      guestFullName = "Microsoft Windows XP Professional (32-bit)",
-       #      toolsStatus = "toolsOld",
-       #      toolsVersionStatus = "guestToolsNeedUpgrade",
-       #      toolsRunningStatus = "guestToolsRunning",
-       #      hostName = "APACHE-44896D77.dcs.mcnc.org",
-       #      ipAddress = "152.46.16.235",
-       #   },
-       #   config = (vim.vm.Summary.ConfigSummary) {
-       #      dynamicType = <unset>,
-       #      name = "vm-ark-mcnc-9 (nonpersistent: vmwarewinxp-base234-v12)",
-       #      template = false,
-       #      vmPathName = "[nfs-datastore] 
vm-ark-mcnc-9_234-v12/vm-ark-mcnc-9_234-v12.vmx",
-       #      memorySizeMB = 1024,
-       #      cpuReservation = <unset>,
-       #      memoryReservation = <unset>,
-       #      numCpu = 1,
-       #      numEthernetCards = 2,
-       #      numVirtualDisks = 1,
-       #      uuid = "564d36cf-6988-c91d-0f5f-a62628d46553",
-       #      instanceUuid = "",
-       #      guestId = "winXPProGuest",
-       #      guestFullName = "Microsoft Windows XP Professional (32-bit)",
-       #      annotation = "",
-       #      product = (vim.vApp.ProductInfo) null,
-       #      installBootRequired = <unset>,
-       #      ftInfo = (vim.vm.FaultToleranceConfigInfo) null,
-       #   },
-       #   storage = (vim.vm.Summary.StorageSummary) {
-       #      dynamicType = <unset>,
-       #      committed = 4408509391,
-       #      uncommitted = 11697668096,
-       #      unshared = 4408509391,
-       #      timestamp = "2010-06-08T14:26:30.312473Z",
-       #   },
-       #   quickStats = (vim.vm.Summary.QuickStats) {
-       #      dynamicType = <unset>,
-       #      overallCpuUsage = 20,
-       #      overallCpuDemand = <unset>,
-       #      guestMemoryUsage = 40,
-       #      hostMemoryUsage = 652,
-       #      guestHeartbeatStatus = "yellow",
-       #      distributedCpuEntitlement = <unset>,
-       #      distributedMemoryEntitlement = <unset>,
-       #      staticCpuEntitlement = <unset>,
-       #      staticMemoryEntitlement = <unset>,
-       #      privateMemory = <unset>,
-       #      sharedMemory = <unset>,
-       #      swappedMemory = <unset>,
-       #      balloonedMemory = <unset>,
-       #      consumedOverheadMemory = <unset>,
-       #      ftLogBandwidth = <unset>,
-       #      ftSecondaryLatency = <unset>,
-       #      ftLatencyStatus = <unset>,
-       #   },
-       #   overallStatus = "green",
-       # }
-       if (!grep(/vim\.vm\.Summary/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve VM summary, 
unexpected output returned, VIM command arguments: '$vim_cmd_arguments', 
output:\n" . join("\n", @$output));
-               return;
-       }
-       
-       my $vm_summary_info = $self->_parse_vim_cmd_output($output);
-       if (defined($vm_summary_info->{'vim.vm.Summary'})) {
-               return $vm_summary_info->{'vim.vm.Summary'};
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to retrieve summary of 
VM: $vmx_file_path, parsed output does not contain a 'vim.vm.Summary' key:\n" . 
format_data($vm_summary_info));
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _get_datastore_info
-
- Parameters  : none
- Returns     : hash reference
- Description : 
-
-=cut
-
-sub _get_datastore_info {
-       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 previously retrieved datastore name array if it is defined in 
this object
-       if ($self->{datastore}) {
-               return $self->{datastore};
-       }
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $vim_cmd_arguments = "hostsvc/datastore/listsummary";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # The output should look like this:
-       # (vim.Datastore.Summary) [
-       #       (vim.Datastore.Summary) {
-       #               dynamicType = <unset>,
-       #               datastore = 
'vim.Datastore:4bcf0efe-c426acc4-c7e1-001a644d1cc0',
-       #               name = "local-datastore",
-       #               url = 
"/vmfs/volumes/4bcf0efe-c426acc4-c7e1-001a644d1cc0",
-       #               capacity = 31138512896,
-       #               freeSpace = 26277314560,
-       #               uncommitted = 0,
-       #               accessible = true,
-       #               multipleHostAccess = <unset>,
-       #               type = "VMFS",
-       #       },
-       #       (vim.Datastore.Summary) {
-       #               dynamicType = <unset>,
-       #               datastore = 
'vim.Datastore:10.25.0.245:/vmfs/volumes/nfs-datastore',
-       #               name = "nfs-datastore",
-       #               url = "/vmfs/volumes/95e378c2-863dd2b4",
-       #               capacity = 975027175424,
-       #               freeSpace = 108854874112,
-       #               uncommitted = 0,
-       #               accessible = true,
-       #               multipleHostAccess = <unset>,
-       #               type = "NFS",
-       #       },
-       # ]
-       if (!grep(/vim\.Datastore\.Summary/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine datastore 
names, unexpected output returned, VIM command arguments: '$vim_cmd_arguments', 
output:\n" . join("\n", @$output));
-               return;
-       }
-       
-       my $datastore_info;
-       
-       # Split the output into sections for each datastore
-       my @output_sections = split(/vim\.Datastore\.Summary/i, join("\n", 
@$output));
-       
-       for my $output_section (@output_sections) {
-               my ($datastore_name) = $output_section =~ /name\s*=\s*"(.+)"/;
-               next if (!defined($datastore_name));
-               
-               for my $line (split(/[\r\n]+/, $output_section)) {
-                       # Skip lines which don't contain a '='
-                       next if $line !~ /=/;
-                       
-                       # Parse the line
-                       my ($parameter, $value) = $line =~ 
/^\s*(\w+)\s*=[\s"']*([^"',]+)/g;
-                       if (defined($parameter) && defined($value)) {
-                               $datastore_info->{$datastore_name}{$parameter} 
= $value if ($parameter ne 'name');
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "unable to parse 
parameter and value from line: '$line'");
-                       }
-               }
-               
-               # Check if the accessible value was retrieved and is not false
-               my $datastore_accessible = 
$datastore_info->{$datastore_name}{accessible};
-               if (!$datastore_accessible || $datastore_accessible =~ 
/false/i) {
-                       notify($ERRORS{'DEBUG'}, 0, "datastore 
'$datastore_name' is mounted on $vmhost_hostname but not accessible");
-                       delete $datastore_info->{$datastore_name};
-                       next;
-               }
-               
-               # Add a 'normal_path' key to the hash based on the datastore url
-               my $datastore_url = $datastore_info->{$datastore_name}{url};
-               if (!defined($datastore_url)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to determine 
datastore url from 'vim-cmd $vim_cmd_arguments' output section, datastore name: 
$datastore_name:\n$output_section");
-                       delete $datastore_info->{$datastore_name};
-                       next;
-               }
-               
-               my $datastore_normal_path;
-               if ($datastore_url =~ /^\/vmfs\/volumes/i) {
-                       $datastore_normal_path = 
"/vmfs/volumes/$datastore_name";
-               }
-               else {
-                       $datastore_normal_path = $datastore_url;
-               }
-               $datastore_info->{$datastore_name}{normal_path} = 
$datastore_normal_path;
-       }
-
-       return $datastore_info;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _get_task_ids
-
- Parameters  : $vmx_file_path, $task_type
- Returns     : array
- Description : Returns an array containing the task IDs recently executed on
-               the VM indicated by the $vm_id argument. The task type argument
-               must be specified. Example task type values:
-               powerOn
-               powerOff
-               registerVm
-               unregisterVm
-
-=cut
-
-sub _get_task_ids {
-       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 file path argument
-       my $vmx_file_path = shift || $self->get_vmx_file_path();
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument could not 
be determined");
-               return;
-       }
-       
-       # Get the task type argument
-       my $task_type = shift;
-       
-       my $vm_id = $self->_get_vm_id($vmx_file_path) || return;
-       
-       my $vim_cmd_arguments = "vmsvc/get.tasklist $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # Expected output:
-       # (ManagedObjectReference) [
-       #   'vim.Task:haTask-512-vim.VirtualMachine.powerOn-2826',
-       #   'vim.Task:haTask-512-vim.VirtualMachine.powerOn-2843',
-       #   'vim.Task:haTask-512-vim.VirtualMachine.powerOn-2856'
-       # ]
-       
-       # Expected output if there are no recent tasks:
-       # (ManagedObjectReference) []
-       
-       if (!grep(/ManagedObjectReference/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unexpected output returned while 
attempting to retrieve task list, VIM command arguments: '$vim_cmd_arguments', 
output:\n" . join("\n", @$output));
-               return;
-       }
-       elsif (grep(/\(ManagedObjectReference\)\s*\[\]/i, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "there are no recent tasks for VM 
$vm_id");
-               return ();
-       }
-       
-       #notify($ERRORS{'DEBUG'}, 0, "task list output:\n" . join("\n", 
@$output));
-       
-       # Reverse the output array so the newest tasks are listed first
-       my @reversed_output = reverse(@$output);
-       
-       #notify($ERRORS{'DEBUG'}, 0, "reversed task list output:\n" . 
join("\n", @reversed_output));
-       
-       #my (@task_ids) = grep(/haTask-$vm_id-.+$task_type-/, @reversed_output);
-       my @task_ids;
-       if ($task_type) {
-               @task_ids = map { /(haTask-$vm_id-.+$task_type-\d+)/ } 
@reversed_output;
-       }
-       else {
-               @task_ids = map { /(haTask-$vm_id-.+-\d+)/ } @reversed_output;
-               $task_type = 'all';
-       }
-       
-       # Check if a matching task was found
-       if (!@task_ids) {
-               notify($ERRORS{'WARNING'}, 0, "failed to determine task IDs 
from output for VM $vm_id, task type: $task_type, output:\n" . join("\n", 
@$output));
-               return;
-       }
-       
-       #notify($ERRORS{'DEBUG'}, 0, "retrieved task IDs for VM $vm_id, task 
type: $task_type:\n" . join("\n", @task_ids));
-       return @task_ids;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _get_task_info
-
- Parameters  : $task_id
- Returns     : hash reference
- Description : 
-
-=cut
-
-sub _get_task_info {
-       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 task ID path argument
-       my (@task_ids) = @_;
-       @task_ids = $self->_get_task_ids() if (!@task_ids);
-       
-       my $task_info = {};
-       
-       for my $task_id (@task_ids) {
-               my $vim_cmd_arguments = "vimsvc/task_info $task_id";
-               my ($exit_status, $output) = 
$self->_run_vim_cmd($vim_cmd_arguments);
-               
-               # Expected output:
-               # (vim.TaskInfo) {
-               #   dynamicType = <unset>,
-               #   key = "haTask-496-vim.VirtualMachine.powerOn-3072",
-               #   task = 
'vim.Task:haTask-496-vim.VirtualMachine.powerOn-3072',
-               #   description = (vmodl.LocalizableMessage) null,
-               #   name = "vim.VirtualMachine.powerOn",
-               #   descriptionId = "VirtualMachine.powerOn",
-               #   entity = 'vim.VirtualMachine:496',
-               #   entityName = "vm-ark-mcnc-9 (nonpersistent: 
vmwarewinxp-base234-v12)",
-               #   state = "error",
-               #   cancelled = false,
-               #   cancelable = false,
-               #   error = (vmodl.fault.RequestCanceled) {
-               #      dynamicType = <unset>,
-               #      faultCause = (vmodl.MethodFault) null,
-               #      msg = "The task was canceled by a user.",
-               #   },
-               #   result = <unset>,
-               #   progress = 100,
-               #   reason = (vim.TaskReasonUser) {
-               #      dynamicType = <unset>,
-               #      userName = "root",
-               #   },
-               #   queueTime = "2010-06-30T08:48:44.187347Z",
-               #   startTime = "2010-06-30T08:48:44.187347Z",
-               #   completeTime = "2010-06-30T08:49:26.381383Z",
-               #   eventChainId = 3072,
-               #   changeTag = <unset>,
-               #   parentTaskKey = <unset>,
-               #   rootTaskKey = <unset>,
-               # }
-               
-               # Expected output if the task is not found:
-               # (vmodl.fault.ManagedObjectNotFound) {
-               #   dynamicType = <unset>,
-               #   faultCause = (vmodl.MethodFault) null,
-               #   obj = 
'vim.Task:haTask-496-vim.VirtualMachine.powerOn-3072x',
-               #   msg = "The object has already been deleted or has not been 
completely created",
-               # }
-               
-               if (!defined($output)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to execute 
command to retrieve info for task ID: $task_id");
-                       next;
-               }
-               elsif (grep(/ManagedObjectNotFound/i, @$output)) {
-                       notify($ERRORS{'WARNING'}, 0, "task was not found, task 
ID: $task_id, output:\n" . join("\n", @$output));
-                       next;
-               }
-               elsif (!grep(/vim.TaskInfo/i, @$output)) {
-                       notify($ERRORS{'WARNING'}, 0, "unexpected output 
returned while attempting to retrieve task list, VIM command arguments: 
'$vim_cmd_arguments' output:\n" . join("\n", @$output));
-                       next;
-               }
-               else {
-                       #notify($ERRORS{'DEBUG'}, 0, "retrieved info for task 
$task_id");       
-                       $task_info->{$task_id} = join("\n", @$output);
-               }
-       }
-       
-       return $task_info;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 _wait_for_task
-
- Parameters  : $task_id, $timeout_seconds (optional)
- Returns     : boolean
- Description : Waits for the vim task to complete. Returns true if the task
-               completes successfully.
-
-=cut
-
-sub _wait_for_task {
-       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 task ID path argument
-       my $task_id = shift;
-       if (!$task_id) {
-               notify($ERRORS{'WARNING'}, 0, "task ID argument was not 
supplied");
-               return;
-       }
-       
-       my $timeout_seconds = shift || 30;
-       
-       my $start_time = time();
-       
-       while (time() - $start_time < $timeout_seconds) {
-               notify($ERRORS{'DEBUG'}, 0, "checking status of task: 
$task_id");
-               
-               # Get the task info
-               my $task_info = $self->_get_task_info($task_id);
-               my $task_info_output = $task_info->{$task_id};
-               if (!$task_info || !$task_info_output) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to determine if 
task $task_id has completed, task info could not be retrieved");
-                       return;
-               }
-               
-               # Parse the output to get the task state and progress
-               my ($task_state) = $task_info_output =~ 
/state\s*=\s*"([^"]+)/is;
-               if (!$task_state) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to determine task 
state from task info output:\n$task_info_output");
-                       return;
-               }
-               
-               my ($error_message) = $task_info_output =~ /msg\s*=\s*"([^"]+)/;
-               $error_message = $task_info_output if !$error_message;
-               
-               my ($progress)= $task_info_output =~ /progress\s*=\s*(\d+)/;
-               $progress = 'unknown' if !defined($progress);
-               
-               if ($task_state =~ /success/) {
-                       notify($ERRORS{'DEBUG'}, 0, "task completed 
successfully: $task_id");
-                       return 1;
-               }
-               elsif ($task_state =~ /error|cancelled/) {
-                       
-                       # Check if the task failed with the message: 'Operation 
failed since another task is in progress.'
-                       if ($error_message =~ /another task is in progress/i) {
-                               # Retrieve info for all of the VMs recent tasks
-                               my $task_info_all = $self->_get_task_info();
-                               notify($ERRORS{'WARNING'}, 0, "task $task_id 
did not complete successfully, state: $task_state, error message: 
$error_message, task info:\n" . format_data($task_info_all));
-                       }
-                       elsif ($error_message =~ /state of the virtual machine 
has not changed since the last snapshot/i) {
-                               # Snapshot may fail if VM is suspended and 
snapshot was already taken after suspension, message will be:
-                               # message = "An error occurred while taking a 
snapshot: The state of the virtual machine has not changed since the last 
snapshot operation."
-                               notify($ERRORS{'DEBUG'}, 0, "snapshot task is 
not necessary: $task_id, message: $error_message");
-                               return 1;
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "task $task_id 
did not complete successfully, state: $task_state, error message: 
$error_message");
-                       }
-                       return;
-               }
-               elsif ($task_state =~ /running/) {
-                       notify($ERRORS{'DEBUG'}, 0, "task state: $task_state, 
progress: $progress, sleeping for 3 seconds before checking task state again");
-                       sleep 3;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "task state: $task_state, 
progress: $progress, sleeping for 3 seconds before checking task state again, 
output:\n$task_info_output");
-                       sleep 3;
-               }
-       }
-       
-       notify($ERRORS{'WARNING'}, 0, "timeout was reached: $timeout_seconds 
seconds, task never completed");
-       return;
-}
-
-###############################################################################
-
-=head1 API OBJECT METHODS
-
-=cut
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=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;
-       }
-       
-       # Get the VM IDs
-       my $vm_list = $self->_get_vm_list();
-       if (!defined($vm_list)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve registered 
VMs, failed to retrieve list of registered VMs and their IDs");
-               return;
-       }
-       
-       # Get the vmx path values for each VM
-       my @vmx_paths = sort { lc($a) cmp lc($b) } values(%$vm_list);
-       
-       notify($ERRORS{'DEBUG'}, 0, "found " . scalar(@vmx_paths) . " 
registered VMs");
-       return @vmx_paths;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 get_vm_power_state
-
- Parameters  : $vmx_file_path
- Returns     : string
- Description : Returns a string containing the power state of the VM indicated
-                                       by the vmx file path argument. The 
string returned may be 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 file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       my $vm_id = $self->_get_vm_id($vmx_file_path) || return;
-       
-       my $vim_cmd_arguments = "vmsvc/power.getstate $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # The output should look like this:
-       # Retrieved runtime info
-       # Powered on
-       
-       # Retrieved runtime info
-       # Powered off
-       
-       # Retrieved runtime info
-       # Suspended
-       
-       notify($ERRORS{'DEBUG'}, 0, "$vim_cmd_arguments:\n" . join("\n", 
@$output));
-       
-       if (grep(/powered on/i, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "VM is powered on: $vmx_file_path");
-               return 'on';
-       }
-       elsif (grep(/powered off/i, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "VM is powered off: 
$vmx_file_path");
-               return 'off';
-       }
-       elsif (grep(/suspended/i, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "VM is suspended: $vmx_file_path");
-               return 'suspended';
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unexpected output returned while 
attempting to determine power state of $vmx_file_path, VIM command arguments: 
'$vim_cmd_arguments' output:\n" . join("\n", @$output));
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_power_on
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Powers on the VM indicated by the vmx file path argument.
-
-=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 file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       # Get the VM ID
-       my $vm_id = $self->_get_vm_id($vmx_file_path);
-       if (!defined($vm_id)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to power on VM because VM 
ID could not be determined");
-               return;
-       }
-       
-       my $vim_cmd_arguments = "vmsvc/power.on $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 
360);
-       return if !$output;
-       
-       # Expected output if the VM was not previously powered on:
-       # Powering on VM:
-       
-       # Expected output if the VM was previously powered on:
-       # Powering on VM:
-       # (vim.fault.InvalidPowerState) {
-       #   dynamicType = <unset>,
-       #   faultCause = (vmodl.MethodFault) null,
-       #   requestedState = "poweredOn",
-       #   existingState = "poweredOn",
-       #   msg = "The attempted operation cannot be performed in the current 
state (Powered On).",
-       # }
-       
-       if (grep(/existingState = "poweredOn"/i, @$output)) {
-               notify($ERRORS{'OK'}, 0, "VM is already powered on: 
$vmx_file_path");
-               return 1;
-       }
-       elsif (!grep(/Powering on VM/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unexpected output returned while 
attempting to power on VM $vmx_file_path, VIM command arguments: 
'$vim_cmd_arguments', output:\n" . join("\n", @$output));
-               return;
-       }
-       
-       # Get the task ID
-       my @task_ids = $self->_get_task_ids($vmx_file_path, 'powerOn');
-       if (!@task_ids) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve the ID of the 
task created to power on the VM");
-               return;
-       }
-       
-       # Wait for the task to complete
-       if ($self->_wait_for_task($task_ids[0])) {
-               notify($ERRORS{'OK'}, 0, "powered on VM: $vmx_file_path");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to power on VM: 
$vmx_file_path, the vim power on task did not complete successfully, vim-cmd 
$vim_cmd_arguments output:\n" . join("\n", @$output));
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_power_off
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Powers off the VM indicated by the vmx file path argument.
-
-=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 file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       # Check if the VM is already powered off
-       my $vm_power_state = $self->get_vm_power_state($vmx_file_path);
-       if ($vm_power_state && $vm_power_state =~ /off/i) {
-               notify($ERRORS{'DEBUG'}, 0, "VM is already powered off: 
$vmx_file_path");
-               return 1;
-       }
-       
-       # Get the VM ID
-       my $vm_id = $self->_get_vm_id($vmx_file_path);
-       if (!defined($vm_id)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to power off VM because 
VM ID could not be determined");
-               return;
-       }
-       
-       my $vim_cmd_arguments = "vmsvc/power.off $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # Expected output if the VM was not previously powered off:
-       # Powering off VM:
-       
-       # Expected output if the VM was previously powered off:
-       # Powering off VM:
-       # (vim.fault.InvalidPowerState) {
-       #   dynamicType = <unset>,
-       #   faultCause = (vmodl.MethodFault) null,
-       #   requestedState = "poweredOff",
-       #   existingState = "poweredOff",
-       #   msg = "The attempted operation cannot be performed in the current 
state (Powered Off).",
-       # }
-       
-       if (grep(/existingState = "poweredOff"/i, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "VM is already powered off: 
$vmx_file_path");
-               return 1;
-       }
-       elsif (!grep(/Powering off VM/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unexpected output returned while 
attempting to power off VM $vmx_file_path, VIM command arguments: 
'$vim_cmd_arguments', output:\n" . join("\n", @$output));
-               return;
-       }
-
-       # Get the task ID
-       my @task_ids = $self->_get_task_ids($vmx_file_path, 'powerOff');
-       if (!@task_ids) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve the ID of the 
task created to power off the VM");
-               return;
-       }
-       
-       # Wait for the task to complete
-       if ($self->_wait_for_task($task_ids[0])) {
-               notify($ERRORS{'OK'}, 0, "powered off VM: $vmx_file_path");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to power off VM: 
$vmx_file_path, the vim power off task did not complete successfully, vim-cmd 
$vim_cmd_arguments output:\n" . join("\n", @$output));
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_suspend
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Suspends the VM indicated by the vmx file path argument.
-
-=cut
-
-sub vm_suspend {
-       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 file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       # Check if the VM is already powered off
-       my $vm_power_state = $self->get_vm_power_state($vmx_file_path);
-       if ($vm_power_state) {
-               if ($vm_power_state =~ /off/i) {
-                       notify($ERRORS{'DEBUG'}, 0, "VM is already powered off: 
$vmx_file_path");
-                       return 1;
-               }
-               elsif ($vm_power_state =~ /suspend/i) {
-                       notify($ERRORS{'DEBUG'}, 0, "VM is already suspended: 
$vmx_file_path");
-                       return 1;
-               }
-       }
-       
-       # Get the VM ID
-       my $vm_id = $self->_get_vm_id($vmx_file_path);
-       if (!defined($vm_id)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to power off VM because 
VM ID could not be determined");
-               return;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "suspending VM: $vmx_file_path ($vm_id)");
-       my $start_time = time;
-       my $vim_cmd_arguments = "vmsvc/power.suspend $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 
400);
-       return if !$output;
-       
-       # Expected output if the VM was not previously suspended:
-       # Suspending VM:
-       
-       # Expected output if the VM was previously suspended or powered off:
-       # Suspending VM:
-       # Suspend failed
-       
-       if (!grep(/Suspending VM/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unexpected output returned while 
attempting to suspend VM $vmx_file_path, VIM command arguments: 
'$vim_cmd_arguments', output:\n" . join("\n", @$output));
-               return;
-       }
-
-       # Get the task ID
-       my @task_ids = $self->_get_task_ids($vmx_file_path, 'suspend');
-       if (!@task_ids) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve the ID of the 
task created to suspend the VM");
-               return;
-       }
-       
-       # Wait for the task to complete
-       if ($self->_wait_for_task($task_ids[0])) {
-               my $duration = (time - $start_time);
-               notify($ERRORS{'OK'}, 0, "suspended VM: $vmx_file_path, took 
$duration seconds");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to suspend VM: 
$vmx_file_path, the vim power off task did not complete successfully, vim-cmd 
$vim_cmd_arguments output:\n" . join("\n", @$output));
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_register
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Registers the VM indicated by the vmx file path argument.
-
-=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 file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       # Check if the VM is already registered
-       if ($self->is_vm_registered($vmx_file_path)) {
-               notify($ERRORS{'OK'}, 0, "VM is already registered: 
$vmx_file_path");
-               return 1;
-       }
-       
-       $vmx_file_path =~ s/\\* /\\ /g;
-       my $vim_cmd_arguments = "solo/registervm \"$vmx_file_path\"";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 
60, 1);
-       return if !$output;
-       
-       # Note: registervm does not produce any output if it was successful
-       
-       # Expected output if the vmx file path does not exist:
-       # (vim.fault.NotFound) {
-       #   dynamicType = <unset>,
-       #   faultCause = (vmodl.MethodFault) null,
-       #   msg = "The object or item referred to could not be found.",
-       # }
-       
-       if (grep(/vim.fault.NotFound/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to register VM, vmx file 
was not found: $vmx_file_path, output:\n" . join("\n", @$output));
-               return;
-       }
-       elsif (grep(/vim.fault.AlreadyExists/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to register VM on the 1st 
attempt, an existing invalid VM using the same vmx file path may already 
already be registered, output:\n" . join("\n", @$output));
-               
-               # If an "invalid" VM exists using the same .vmx path, this 
fault will be generated:
-               #    (vim.fault.AlreadyExists) {
-               #    faultCause = (vmodl.MethodFault) null,
-               #    name = "51",
-               #    msg = "The specified key, name, or identifier '51' already 
exists."
-               my ($vm_id) = join("\n", @$output) =~ /name\s*=\s*"(\d+)"/;
-               if ($vm_id) {
-                       if ($self->vm_unregister($vm_id)) {
-                               notify($ERRORS{'DEBUG'}, 0, "unregistered 
existing invalid VM $vm_id, making another attempt to register VM: 
$vmx_file_path");
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "failed to 
register VM: $vmx_file_path, unable to unregister existing invalid VM $vm_id");
-                               return;
-                       }
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to register VM: 
$vmx_file_path, ID of existing invalid VM could not be determined, was 
expecting a line beginning with 'name = \"<ID>\"' in output:\n" . join("\n", 
@$output));
-                       return;
-               }
-       }
-       
-       if (grep(/fault/i, @$output)) {
-               # Only made 1 attempt so far, try again if fault occurred, 
allow 4 more attempts
-               ($exit_status, $output) = 
$self->_run_vim_cmd($vim_cmd_arguments, 60, 4);
-               return if !$output;
-       }
-       
-       if (grep(/fault/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to register VM: 
$vmx_file_path, vim-cmd $vim_cmd_arguments output:\n" . join("\n", @$output));
-               return;
-       }
-       
-       # Check to make sure the VM is registered
-       if ($self->is_vm_registered($vmx_file_path)) {
-               notify($ERRORS{'OK'}, 0, "registered VM: '$vmx_file_path'");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to register VM: 
'$vmx_file_path'");
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 vm_unregister
-
- Parameters  : $vm_identifier 
- Returns     : boolean
- Description : Unregisters the VM indicated by the argument which may either be
-               the .vmx file path or VM ID.
-
-=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;
-       }
-       
-       # Note: allow the VM ID to be passed in case the .vmx file path cannot 
be determined
-       # This allows an invalid VM with a missing .vmx file to be unregistered
-       
-       my $vm_identifier = shift;
-       if (!$vm_identifier) {
-               notify($ERRORS{'WARNING'}, 0, "VM identifier argument was not 
supplied");
-               return;
-       }
-       
-       my $vm_id;
-       my $vmx_file_path;
-       if ($vm_identifier =~ /^\d+$/) {
-               $vm_id = $vm_identifier;
-       }
-       else {
-               # Argument should be the vmx file path
-               $vmx_file_path = $vm_identifier;
-               
-               # Check if the VM is not registered
-               if (!$self->is_vm_registered($vmx_file_path)) {
-                       notify($ERRORS{'OK'}, 0, "VM not unregistered because 
it is not registered: $vmx_file_path");
-                       return 1;
-               }
-               
-               # Power of the VM if it is powered on or the unregister command 
will fail
-               my $vm_power_state = $self->get_vm_power_state($vmx_file_path);
-               if ($vm_power_state && $vm_power_state =~ /on/i) {
-                       if (!$self->vm_power_off($vmx_file_path)) {
-                               notify($ERRORS{'WARNING'}, 0, "failed to 
unregister VM because it could not be powered off: $vmx_file_path");
-                               return;
-                       }
-               }
-               
-               $vm_id = $self->_get_vm_id($vmx_file_path);
-               if (!defined($vm_id)) {
-                       notify($ERRORS{'OK'}, 0, "unable to unregister VM 
because VM ID could not be determined for vmx path argument: $vmx_file_path");
-                       return;
-               }
-       }
-       
-       my $vim_cmd_arguments = "vmsvc/unregister $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       
-       # Delete cached .vmx - VM ID mapping if previously retrieved
-       delete $self->{vm_id}{$vm_identifier};
-       
-       return if !$output;
-       
-       # Expected output if the VM is not registered:
-       # (vim.fault.NotFound) {
-       #   dynamicType = <unset>,
-       #   faultCause = (vmodl.MethodFault) null,
-       #   msg = "Unable to find a VM corresponding to 
"/vmfs/volumes/nfs-datastore/vm-ark-mcnc-9_234-v12/vm-ark-mcnc-9_234-v12.vmx"",
-       # }
-       
-       if (grep(/fault/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to unregister VM, VIM 
command arguments: '$vim_cmd_arguments'\noutput:\n" . join("\n", @$output));
-               return;
-       }
-       
-       # Check to make sure the VM is not registered
-       if ($vmx_file_path && $self->is_vm_registered($vmx_file_path)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to unregister VM: 
$vmx_file_path (ID: $vm_id), it still appears to be registered");
-               return;
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "unregistered VM: $vm_identifier");
-               return 1;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 get_virtual_disk_type
-
- Parameters  : $vmdk_file_path
- Returns     : 
- 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 = shift;
-       if (!$vmdk_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmdk file path argument was not 
supplied");
-               return;
-       }
-       
-       my ($vmdk_directory_path, $vmdk_file_name) = $vmdk_file_path =~ 
/^(.+)\/([^\/]+\.vmdk)/;
-       if (!$vmdk_directory_path || !$vmdk_file_name) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine directory 
path and file name from vmdk file path: $vmdk_directory_path");
-               return;
-       }
-       
-       my $vmdk_directory_datastore_path = 
$self->_get_datastore_path($vmdk_directory_path);
-       if (!$vmdk_directory_datastore_path) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine vmdk 
directory datastore path from vmdk directory path: $vmdk_directory_path");
-               return;
-       }
-       
-       # The output of 'vim-cmd hostsvc/datastorebrowser/disksearch' differs 
for VMware Server 2.x and ESXi
-       # The value of 'thin' is not returned if disksearch is run under ESXi
-       my $vmware_product_name = $self->get_vmhost_product_name();
-       my $vim_cmd_arguments;
-       if ($vmware_product_name =~ /esx/i) {
-               $vim_cmd_arguments = "hostsvc/datastorebrowser/search 0 
\"$vmdk_directory_datastore_path\"";
-       }
-       else {
-               $vim_cmd_arguments = "hostsvc/datastorebrowser/disksearch 
\"$vmdk_directory_datastore_path\"";
-       }
-       
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # Expected output:
-       #(vim.host.DatastoreBrowser.SearchResults) {
-       #   dynamicType = <unset>,
-       #   datastore = 'vim.Datastore:10.10.14.20:/nfs-datastore1',
-       #   folderPath = "[nfs-datastore1] vclv17-149_234-v14",
-       #   file = (vim.host.DatastoreBrowser.FileInfo) [
-       #      (vim.host.DatastoreBrowser.VmDiskInfo) {
-       #         dynamicType = <unset>,
-       #         path = "vmwarewinxp-base234-v14.vmdk",
-       #         fileSize = 5926510592,
-       #         modification = "2010-11-24T17:06:44Z",
-       #         owner = <unset>,
-       #         diskType = "vim.vm.device.VirtualDisk.FlatVer2BackingInfo",
-       #         capacityKb = 14680064,
-       #         hardwareVersion = 4,
-       #         controllerType = "vim.vm.device.VirtualIDEController",
-       #         diskExtents = (string) [
-       #            "[nfs-datastore1] 
vclv17-149_234-v14/vmwarewinxp-base234-v14-flat.vmdk"
-       #         ],
-       #         thin = true,
-       #      }
-       #   ],
-       #}
-
-
-       my $output_string = join("\n", @$output);
-       my (@disk_info_sections) = 
split(/vim.host.DatastoreBrowser.VmDiskInfo/, $output_string);
-       
-       for my $disk_info (@disk_info_sections) {
-               my ($disk_path) = $disk_info =~ /\spath = "(.+)"/i;
-               
-               if (!$disk_path || $disk_path ne $vmdk_file_name) {
-                       next;
-               }
-               
-               my ($disk_type) = $disk_info =~ /\sdiskType = "(.+)"/i;
-               if (!$disk_type) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to determine disk 
type, disk path: $disk_path, disk info section from vim-cmd $vim_cmd_arguments 
output:\n$disk_info");
-                       next;
-               }
-               
-               # Disk type format: 
vim.vm.device.VirtualDisk.FlatVer2BackingInfo
-               # Remove everything but "FlatVer2"
-               $disk_type =~ s/(^.*\.|BackingInfo$)//g;
-               
-               # Return 'thin' if thin is set to true
-               my ($thin) = $disk_info =~ /\sthin\s*=\s*(.+)/i;
-               if (defined($thin) && $thin =~ /true/) {
-                       $disk_type = 'thin';
-               }
-               
-               notify($ERRORS{'DEBUG'}, 0, "$disk_path disk type: $disk_type");
-               return $disk_type;
-       }
-       
-       notify($ERRORS{'WARNING'}, 0, "unable to determine disk type for disk: 
$vmdk_file_path, vim-cmd $vim_cmd_arguments output:\n" . join("\n", @$output));
-       return;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=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. False is returned
-                                       if the controller type cannot be 
retrieved. A string is returned
-                                       containing one of the following values:
-                                       -IDE
-                                       -lsiLogic
-                                       -busLogic
-
-=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 = shift;
-       if (!$vmdk_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmdk file path argument was not 
supplied");
-               return;
-       }
-       
-       my ($vmdk_directory_path, $vmdk_file_name) = $vmdk_file_path =~ 
/^(.+)\/([^\/]+\.vmdk)/;
-       if (!$vmdk_directory_path || !$vmdk_file_name) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine directory 
path and file name from vmdk file path: $vmdk_directory_path");
-               return;
-       }
-       
-       my $vmdk_directory_datastore_path = 
$self->_get_datastore_path($vmdk_directory_path);
-       if (!$vmdk_directory_datastore_path) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine vmdk 
directory datastore path from vmdk directory path: $vmdk_directory_path");
-               return;
-       }
-       
-       my $vim_cmd_arguments = "hostsvc/datastorebrowser/searchsubfolders 0 
\"$vmdk_directory_datastore_path\"";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # Expected output:
-       # (vim.host.DatastoreBrowser.SearchResults) {
-       #   dynamicType = <unset>,
-       #   datastore = 'vim.Datastore:10.25.0.245:/vmfs/volumes/nfs-datastore',
-       #   folderPath = "[nfs-datastore] vmwarewinxp-base234-v12",
-       #   file = (vim.host.DatastoreBrowser.FileInfo) [
-       #      (vim.host.DatastoreBrowser.VmDiskInfo) {
-       #         dynamicType = <unset>,
-       #         path = "vmwarewinxp-base234-v12.vmdk",
-       #         fileSize = 4774187008,
-       #         modification = "2010-06-30T21:03:45Z",
-       #         owner = <unset>,
-       #         diskType = "vim.vm.device.VirtualDisk.SparseVer2BackingInfo",
-       #         capacityKb = 14680064,
-       #         hardwareVersion = 4,
-       #         controllerType = "vim.vm.device.VirtualBusLogicController",
-       #         diskExtents = (string) [
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s001.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s002.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s003.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s004.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s005.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s006.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s007.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s008.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s009.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s010.vmdk"
-       #         ],
-       #         thin = false,
-       #      },
-       #      (vim.host.DatastoreBrowser.VmDiskInfo) {
-       #         dynamicType = <unset>,
-       #         path = "esx_2gb_sparse.vmdk",
-       #         fileSize = 4410286080,
-       #         modification = "2010-07-01T18:38:04Z",
-       #         owner = <unset>,
-       #         diskType = "vim.vm.device.VirtualDisk.SparseVer2BackingInfo",
-       #         capacityKb = 14680064,
-       #         hardwareVersion = 7,
-       #         controllerType = "vim.vm.device.VirtualIDEController",
-       #         diskExtents = (string) [
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s001.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s002.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s003.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s004.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s005.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s006.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s007.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s008.vmdk"
-       #         ],
-       #         thin = true,
-       #      },
-       #      (vim.host.DatastoreBrowser.VmDiskInfo) {
-       #         dynamicType = <unset>,
-       #         path = "thin_vmwarewinxp-base234-v12.vmdk",
-       #         fileSize = 4408459264,
-       #         modification = "2010-06-30T20:53:51Z",
-       #         owner = <unset>,
-       #         diskType = "vim.vm.device.VirtualDisk.FlatVer2BackingInfo",
-       #         capacityKb = 14680064,
-       #         hardwareVersion = 4,
-       #         controllerType = <unset>,
-       #         diskExtents = (string) [
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/thin_vmwarewinxp-base234-v12-flat.vmdk"
-       #         ],
-       #         thin = true,
-       #      }
-       #   ],
-       # }
-
-       my $output_string = join("\n", @$output);
-       my (@disk_info_sections) = 
split(/vim.host.DatastoreBrowser.VmDiskInfo/, $output_string);
-       
-       for my $disk_info (@disk_info_sections) {
-               my ($disk_path) = $disk_info =~ /\spath = "(.+)"/i;
-               
-               if (!$disk_path) {
-                       next;
-               }
-               elsif ($disk_path ne $vmdk_file_name) {
-                       #notify($ERRORS{'DEBUG'}, 0, "ignoring disk because the 
file name does not match $vmdk_file_name: $disk_path");
-                       next;
-               }
-               
-               my ($controller_type) = $disk_info =~ 
/\scontrollerType\s*=\s*(.+)/i;
-               if (!$controller_type) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to determine disk 
controller type, disk path: $disk_path, disk info section from vim-cmd 
$vim_cmd_arguments output:\n$disk_info");
-                       next;
-               }
-               
-               if ($controller_type =~ /unset/i) {
-                       notify($ERRORS{'DEBUG'}, 0, "disk controller type is 
not set in the vmdk file: $disk_path");
-                       return 0;
-               }
-               else {
-                       # Extract just the controller type name from the value: 
vim.vm.device.VirtualIDEController --> IDE
-                       $controller_type =~ 
s/(.*vim.vm.device.Virtual|Controller.*)//ig;
-                       notify($ERRORS{'DEBUG'}, 0, "retrieved controller type 
for $disk_path: '$controller_type'");
-                       return $controller_type;
-               }
-       }
-       
-       notify($ERRORS{'WARNING'}, 0, "unable to determine disk controller type 
for disk: $vmdk_file_path, vim-cmd $vim_cmd_arguments output:\n" . join("\n", 
@$output));
-       return;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 get_virtual_disk_hardware_version
-
- Parameters  : $vmdk_file_path
- Returns     : integer
- Description : Retrieves the hardware version configured for the virtual
-                                       disk specified by the vmdk file path 
argument. False is returned
-                                       if the hardware version cannot be 
retrieved.
-
-=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 = shift;
-       if (!$vmdk_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmdk file path argument was not 
supplied");
-               return;
-       }
-       
-       my ($vmdk_directory_path, $vmdk_file_name) = $vmdk_file_path =~ 
/^(.+)\/([^\/]+\.vmdk)/;
-       if (!$vmdk_directory_path || !$vmdk_file_name) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine directory 
path and file name from vmdk file path: $vmdk_directory_path");
-               return;
-       }
-       
-       my $vmdk_directory_datastore_path = 
$self->_get_datastore_path($vmdk_directory_path);
-       if (!$vmdk_directory_datastore_path) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine vmdk 
directory datastore path from vmdk directory path: $vmdk_directory_path");
-               return;
-       }
-       
-       my $vim_cmd_arguments = "hostsvc/datastorebrowser/searchsubfolders 0 
\"$vmdk_directory_datastore_path\"";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # Expected output:
-       # (vim.host.DatastoreBrowser.SearchResults) {
-       #   dynamicType = <unset>,
-       #   datastore = 'vim.Datastore:10.25.0.245:/vmfs/volumes/nfs-datastore',
-       #   folderPath = "[nfs-datastore] vmwarewinxp-base234-v12",
-       #   file = (vim.host.DatastoreBrowser.FileInfo) [
-       #      (vim.host.DatastoreBrowser.VmDiskInfo) {
-       #         dynamicType = <unset>,
-       #         path = "vmwarewinxp-base234-v12.vmdk",
-       #         fileSize = 4774187008,
-       #         modification = "2010-06-30T21:03:45Z",
-       #         owner = <unset>,
-       #         diskType = "vim.vm.device.VirtualDisk.SparseVer2BackingInfo",
-       #         capacityKb = 14680064,
-       #         hardwareVersion = 4,
-       #         controllerType = "vim.vm.device.VirtualBusLogicController",
-       #         diskExtents = (string) [
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s001.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s002.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s003.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s004.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s005.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s006.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s007.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s008.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s009.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/vmwarewinxp-base234-v12-s010.vmdk"
-       #         ],
-       #         thin = false,
-       #      },
-       #      (vim.host.DatastoreBrowser.VmDiskInfo) {
-       #         dynamicType = <unset>,
-       #         path = "esx_2gb_sparse.vmdk",
-       #         fileSize = 4410286080,
-       #         modification = "2010-07-01T18:38:04Z",
-       #         owner = <unset>,
-       #         diskType = "vim.vm.device.VirtualDisk.SparseVer2BackingInfo",
-       #         capacityKb = 14680064,
-       #         hardwareVersion = 7,
-       #         controllerType = "vim.vm.device.VirtualIDEController",
-       #         diskExtents = (string) [
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s001.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s002.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s003.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s004.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s005.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s006.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s007.vmdk",
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/esx_2gb_sparse-s008.vmdk"
-       #         ],
-       #         thin = true,
-       #      },
-       #      (vim.host.DatastoreBrowser.VmDiskInfo) {
-       #         dynamicType = <unset>,
-       #         path = "thin_vmwarewinxp-base234-v12.vmdk",
-       #         fileSize = 4408459264,
-       #         modification = "2010-06-30T20:53:51Z",
-       #         owner = <unset>,
-       #         diskType = "vim.vm.device.VirtualDisk.FlatVer2BackingInfo",
-       #         capacityKb = 14680064,
-       #         hardwareVersion = 4,
-       #         controllerType = <unset>,
-       #         diskExtents = (string) [
-       #            "[nfs-datastore] 
vmwarewinxp-base234-v12/thin_vmwarewinxp-base234-v12-flat.vmdk"
-       #         ],
-       #         thin = true,
-       #      }
-       #   ],
-       # }
-
-       my $output_string = join("\n", @$output);
-       my (@disk_info_sections) = 
split(/vim.host.DatastoreBrowser.VmDiskInfo/, $output_string);
-       
-       for my $disk_info (@disk_info_sections) {
-               my ($disk_path) = $disk_info =~ /\spath = "(.+)"/i;
-               
-               if (!$disk_path) {
-                       next;
-               }
-               elsif ($disk_path ne $vmdk_file_name) {
-                       notify($ERRORS{'DEBUG'}, 0, "ignoring disk because the 
file name does not match $vmdk_file_name: $disk_path");
-                       next;
-               }
-               
-               my ($hardware_version) = $disk_info =~ 
/\shardwareVersion\s*=\s*(\d+)/ig;
-               if (!$hardware_version) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to determine disk 
hardware version, disk path: $disk_path, disk info section from vim-cmd 
$vim_cmd_arguments output:\n$disk_info");
-                       next;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "retrieved hardware version 
for $disk_path: '$hardware_version'");
-                       return $hardware_version;
-               }
-       }
-       
-       notify($ERRORS{'WARNING'}, 0, "unable to determine hardware version for 
disk: $vmdk_file_path, vim-cmd $vim_cmd_arguments output:\n" . join("\n", 
@$output));
-       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 $vim_cmd_arguments = "solo/environment";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # The output should contain a network section:
-   #network = (vim.vm.NetworkInfo) [
-   #   (vim.vm.NetworkInfo) {
-   #      dynamicType = <unset>,
-   #      name = "Private",
-   #      network = (vim.Network.Summary) {
-   #         dynamicType = <unset>,
-   #         network = 'vim.Network:HaNetwork-Private',
-   #         name = "Private",
-   #         accessible = true,
-   #         ipPoolName = "",
-   #      },
-   #   },
-   #   (vim.vm.NetworkInfo) {
-   #      dynamicType = <unset>,
-   #      name = "Public",
-   #      network = (vim.Network.Summary) {
-   #         dynamicType = <unset>,
-   #         network = 'vim.Network:HaNetwork-Public',
-   #         name = "Public",
-   #         accessible = true,
-   #         ipPoolName = "",
-   #      },
-   #   },
-   #],
-       
-       # Convert the output line array to a string then split it by network 
sections
-       my ($network_info) = join("\n", @$output) =~ 
/(vim\.vm\.NetworkInfo[^\]]+)/;
-       if ($network_info) {
-               notify($ERRORS{'DEBUG'}, 0, "network info:\n$network_info");
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to retrieve network info, 
vim-cmd arguments: '$vim_cmd_arguments', $exit_status: $exit_status, output:\n" 
. join("\n", @$output));
-               return;
-       }
-       
-       my (@network_sections) = split(/vim.vm.NetworkInfo/, $network_info);
-       
-       # Extract the network names from the network sections
-       my @network_names;
-       for my $network_info (@network_sections) {
-               my ($network_name) = $network_info =~ /\sname = "(.+)"/i;
-               next if !$network_name;
-               push @network_names, $network_name;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "retrieved network names:\n" . join("\n", 
@network_names));
-       return @network_names;
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 create_snapshot
-
- Parameters  : $vmx_file_path, $name (optional)
- Returns     : boolean
- Description : Creates a snapshot of the VM.
-
-=cut
-
-sub create_snapshot {
-       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 file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       my $snapshot_name = shift || ("VCL: " . convert_to_datetime());
-       
-       # Get the VM ID
-       my $vm_id = $self->_get_vm_id($vmx_file_path);
-       if (!defined($vm_id)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to create snapshot 
because VM ID could not be determined");
-               return;
-       }
-       
-       my $vim_cmd_arguments = "vmsvc/snapshot.create $vm_id '$snapshot_name'";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 
60, 1);
-       return if !$output;
-       
-       notify($ERRORS{'DEBUG'}, 0, "create snapshot output:\n" . join("\n", 
@$output));
-       
-       # IMPORTANT: Don't check for 'failed' in the output, it may contain 
failed but the snapshot is not necessary:
-       # Snapshot not taken since the state of the virtual machine has not 
changed since the last snapshot operation.
-       #if (grep(/failed|invalid/i, @$output)) {
-       #       notify($ERRORS{'WARNING'}, 0, "failed to create snapshot of VM 
$vmx_file_path, VIM command arguments: '$vim_cmd_arguments', output:\n" . 
join("\n", @$output));
-       #       return;
-       #}
-       
-       # Get the task ID
-       my @task_ids = $self->_get_task_ids($vmx_file_path, 'createSnapshot');
-       if (!@task_ids) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve the ID of the 
task created to create snapshot");
-               return;
-       }
-       
-       # Wait for the task to complete
-       if ($self->_wait_for_task($task_ids[0])) {
-               notify($ERRORS{'OK'}, 0, "created snapshot of VM: 
$vmx_file_path, snapshot name: $snapshot_name");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to create snapshot VM: 
$vmx_file_path, the vim task did not complete successfully, vim-cmd 
$vim_cmd_arguments output:\n" . join("\n", @$output));
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 remove_snapshots
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Removes all snapshots for a VM.
-
-=cut
-
-sub remove_snapshots {
-       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 file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       # Get the VM ID
-       my $vm_id = $self->_get_vm_id($vmx_file_path);
-       if (!defined($vm_id)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to create snapshot 
because VM ID could not be determined");
-               return;
-       }
-       
-       my $vim_cmd_arguments = "vmsvc/snapshot.removeall $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 
7200);
-       return if !$output;
-       
-       notify($ERRORS{'DEBUG'}, 0, "remove snapshots output:\n" . join("\n", 
@$output));
-       
-       if (grep(/failed|invalid/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to remove snapshots for 
VM $vmx_file_path, VIM command arguments: '$vim_cmd_arguments', output:\n" . 
join("\n", @$output));
-               return;
-       }
-       
-       # Get the task ID
-       my @task_ids = $self->_get_task_ids($vmx_file_path, 
'removeAllSnapshots');
-       if (!@task_ids) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve the ID of the 
task created to remove snapshots");
-               return;
-       }
-       
-       # Wait for the task to complete
-       if ($self->_wait_for_task($task_ids[0], 7200)) {
-               notify($ERRORS{'OK'}, 0, "removed snapshots for VM: 
$vmx_file_path");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to remove snapshots for 
VM: $vmx_file_path, the vim task did not complete successfully, vim-cmd 
$vim_cmd_arguments output:\n" . join("\n", @$output));
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=head2 snapshot_exists
-
- Parameters  : $vmx_file_path
- Returns     : boolean
- Description : Determines if a snapshot exists for the VM.
-
-=cut
-
-sub snapshot_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 the vmx file path argument
-       my $vmx_file_path = shift;
-       if (!$vmx_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not 
supplied");
-               return;
-       }
-       
-       # Get the VM ID
-       my $vm_id = $self->_get_vm_id($vmx_file_path);
-       if (!defined($vm_id)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine if snapshot 
exists because VM ID could not be determined");
-               return;
-       }
-       
-       my $vim_cmd_arguments = "vmsvc/snapshot.get $vm_id";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       notify($ERRORS{'DEBUG'}, 0, "snapshot.get output:\n" . join("\n", 
@$output));
-       
-       if (grep(/failed|invalid/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to determine if snapshot 
exists for VM $vmx_file_path, VIM command arguments: '$vim_cmd_arguments', 
output:\n" . join("\n", @$output));
-               return;
-       }
-       
-       # Expected output if shapshot exists:
-       # Get Snapshot:
-       # |-ROOT
-       # --Snapshot Name        : 1311966951
-       # --Snapshot Desciption  :
-       # --Snapshot Created On  : 7/29/2011 19:15:59
-       # --Snapshot State       : powered off
-       
-       # Expected output if snapshot does not exist:
-       # Get Snapshot:
-
-       if (grep(/-ROOT/, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "snapshot exists for VM 
$vmx_file_path");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "snapshot does NOT exist for VM 
$vmx_file_path");
-               return 0;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=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) !~ /VCL::Module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $vim_cmd_arguments = "hostsvc/hosthardware";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # The CPU info should be contained in the output:
-       #       cpuInfo = (vim.host.CpuInfo) {
-       #      dynamicType = <unset>,
-       #      numCpuPackages = 2,
-       #      numCpuCores = 8,
-       #      numCpuThreads = 8,
-       #      hz = 2000070804,
-       #   },
-       
-       my ($cpu_cores_line) = grep(/^\s*numCpuCores\s*=/i, @$output);
-       if (!$cpu_cores_line) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine VM host 
$vmhost_hostname CPU core count, output does not contain a 'numCpuCores =' 
line:\n" . join("\n", @$output));
-               return;
-       }
-       elsif ($cpu_cores_line =~ /(\d+)/) {
-               my $cpu_core_count = $1;
-               notify($ERRORS{'DEBUG'}, 0, "retrieved VM host $vmhost_hostname 
CPU core count: $cpu_core_count");
-               return $cpu_core_count;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to determine VM host 
$vmhost_hostname CPU core count from line: $cpu_cores_line");
-               return;
-       }
-}
-
-#//////////////////////////////////////////////////////////////////////////////
-
-=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) !~ /VCL::Module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $vim_cmd_arguments = "hostsvc/hosthardware";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # The CPU info should be contained in the output:
-       #       cpuInfo = (vim.host.CpuInfo) {
-       #      dynamicType = <unset>,
-       #      numCpuPackages = 2,
-       #      numCpuCores = 8,
-       #      numCpuThreads = 8,
-       #      hz = 2000070804,
-       #   },
-       
-       my ($hz_line) = grep(/^\s*hz\s*=/i, @$output);
-       if (!$hz_line) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine VM host 
$vmhost_hostname CPU speed, output does not contain a 'hz =' line:\n" . 
join("\n", @$output));
-               return;
-       }
-       elsif ($hz_line =~ /(\d+)/) {
-               my $mhz = int($1 / 1000000);
-               notify($ERRORS{'DEBUG'}, 0, "retrieved VM host $vmhost_hostname 
CPU speed: $mhz MHz");
-               return $mhz;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to determine VM host 
$vmhost_hostname CPU speed from line: $hz_line");
-               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) !~ /VCL::Module/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $vmhost_hostname = $self->data->get_vmhost_hostname();
-       
-       my $vim_cmd_arguments = "hostsvc/hosthardware";
-       my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
-       return if !$output;
-       
-       # The following line should be contained in the output:
-       #        memorySize = 17178869760,
-       
-       my ($memory_size_line) = grep(/^\s*memorySize\s*=/i, @$output);
-       if (!$memory_size_line) {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine VM host 
$vmhost_hostname total memory capacity, output does not contain a 'memorySize 
=' line:\n" . join("\n", @$output));
-               return;
-       }
-       elsif ($memory_size_line =~ /(\d+)/) {
-               my $memory_mb = int($1 / 1024 / 1024);
-               notify($ERRORS{'DEBUG'}, 0, "retrieved VM host $vmhost_hostname 
total memory capacity: $memory_mb MB");
-               return $memory_mb;
-       }
-       else {

[... 5603 lines stripped ...]

Reply via email to