Author: arkurth
Date: Mon Jun 7 18:59:25 2010
New Revision: 952366
URL: http://svn.apache.org/viewvc?rev=952366&view=rev
Log:
VCL-298
Added new VMware modules to support Server 2.x and ESXi 4.x:
VMware.pm - provisioning module
VIX_API.pm - utility module which implements subroutines to use the VMware VIX
API
vSphere_SDK.pm - utility module which implements subroutines to use the VMware
vSphere SDK
Created Provisioning/VMware directory. The new modules reside here so they
don't conflict with the existing VMware modules.
Added:
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIX_API.pm
(with props)
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
(with props)
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm
(with props)
Added:
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIX_API.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIX_API.pm?rev=952366&view=auto
==============================================================================
---
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIX_API.pm
(added)
+++
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIX_API.pm
Mon Jun 7 18:59:25 2010
@@ -0,0 +1,939 @@
+#!/usr/bin/perl -w
+###############################################################################
+# $Id$
+###############################################################################
+# 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::Provisioning::VIX_API
+
+=head1 SYNOPSIS
+
+ Needs to be written
+
+=head1 DESCRIPTION
+
+ This module provides VCL support for VMWare VIX API
+ http://www.vmware.com
+
+=cut
+
+##############################################################################
+package VCL::Module::Provisioning::VMware::VIX_API;
+
+# 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.00';
+
+# Specify the version of Perl to use
+use 5.008000;
+
+use strict;
+use warnings;
+use diagnostics;
+use English qw( -no_match_vars );
+
+use VCL::utils;
+
+use VMware::Vix::Simple;
+use VMware::Vix::API::Constants;
+
+##############################################################################
+
+=head1 CLASS VARIABLES
+
+=cut
+
+=head2 %VIX_PROPERTY_VM
+
+ Data type : hash
+ Description : Contains a mapping between numerical and textual
+ VIX_PROPERTY_VM_* properties
+
+=cut
+
+our %VIX_PROPERTY_VM;
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_NUM_VCPUS)} = 'VM_NUM_VCPUS';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_VMX_PATHNAME)} = 'VM_VMX_PATHNAME';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_VMTEAM_PATHNAME)} =
'VM_VMTEAM_PATHNAME';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_MEMORY_SIZE)} = 'VM_MEMORY_SIZE';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_READ_ONLY)} = 'VM_READ_ONLY';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_IN_VMTEAM)} = 'VM_IN_VMTEAM';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_POWER_STATE)} = 'VM_POWER_STATE';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_TOOLS_STATE)} = 'VM_TOOLS_STATE';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_IS_RUNNING)} = 'VM_IS_RUNNING';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_SUPPORTED_FEATURES)} =
'VM_SUPPORTED_FEATURES';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_IS_RECORDING)} = 'VM_IS_RECORDING';
+$VIX_PROPERTY_VM{eval(VIX_PROPERTY_VM_IS_REPLAYING)} = 'VM_IS_REPLAYING';
+
+=head2 %VIX_POWERSTATE
+
+ Data type : hash
+ Description : Contains a mapping between numerical and textual
+ VIX_POWERSTATE_* properties
+
+=cut
+
+our %VIX_POWERSTATE;
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_POWERING_OFF)} = 'POWERING_OFF'; #
power off has been called but not completed
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_POWERED_OFF)} = 'POWERED_OFF'; # VM
is not running
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_POWERING_ON)} = 'POWERING_ON'; #
power on has been called but not completed
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_POWERED_ON)} = 'POWERED_ON'; # VM
is running
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_SUSPENDING)} = 'SUSPENDING'; #
suspend has been called but not completed
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_SUSPENDED)} = 'SUSPENDED'; # VM
is suspended
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_TOOLS_RUNNING)} = 'TOOLS_RUNNING'; # VM
is running and the VMware Tools is active
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_RESETTING)} = 'RESETTING'; #
reset has been called but not completed
+$VIX_POWERSTATE{eval(VIX_POWERSTATE_BLOCKED_ON_MSG)} = 'BLOCKED_ON_MSG'; # VM
state change is blocked, waiting for user interaction
+
+##############################################################################
+
+=head1 API OBJECT METHODS
+
+=cut
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_vm_power_state
+
+ Parameters : $vmx_path
+ Returns : string
+ Description : Determines the power state of the VM specified by the vmx file
+ path argument and returns a string containing one of the
+ following values:
+ -on
+ -off
+ -suspended
+ -blocked
+
+=cut
+
+sub get_vm_power_state {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ my $attempt = 0;
+ my $attempt_limit = 3;
+ my $attempt_delay = 5;
+ my @power_states;
+ while ($attempt < $attempt_limit) {
+ $attempt++;
+ (@power_states = $self->_get_vm_power_states($vix_vmx_path)) ||
return;
+ my $return_state;
+ if (grep(/POWERED_OFF/, @power_states)) {
+ $return_state = "off";
+ }
+ elsif (grep(/POWERED_ON/, @power_states)) {
+ $return_state = "on";
+ }
+ elsif (grep(/SUSPENDED/, @power_states)) {
+ $return_state = "suspended";
+ }
+ elsif (grep(/BLOCKED_ON_MSG/, @power_states)) {
+ $return_state = "blocked";
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "attempt
$attempt/$attempt_limit: VM $vix_vmx_path in a transition power state
(@power_states), sleeping for $attempt_delay");
+ sleep $attempt_delay;
+ next;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "VM $vix_vmx_path power state:
$return_state");
+ return $return_state;
+ }
+
+ notify($ERRORS{'WARNING'}, 0, "VM $vix_vmx_path is still in a
transition power state (@power_states)");
+ return;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_registered_vms
+
+ Parameters : none
+ Returns : array
+ Description : Retrieves a list of the running VMs on the VM host. Returns an
+ array containing the vmx file paths of the running VMs.
+
+=cut
+
+sub get_registered_vms {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ my $vmx_base_directory_path = $self->get_vmx_base_directory_path() ||
return;
+ (my @registered_vms = $self->_find_items(VIX_FIND_REGISTERED_VMS)) ||
return;
+
+ # Convert the vmx paths back to the normal non-VIX format
+ for (my $i=0; $i<scalar(@registered_vms); $i++) {
+ $registered_vms[$i] =~
s/\s*\[standard\]\s*/$vmx_base_directory_path\//ig;
+ }
+ return @registered_vms;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 vm_power_off
+
+ Parameters : $vmx_file_path
+ Returns : boolean
+ Description : Powers off the VM specified by the vmx file path argument.
+
+=cut
+
+sub vm_power_off {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # Get the VM handle
+ my $vm_handle = $self->_get_vm_handle($vix_vmx_path) || return;
+
+ # Call VMPowerOff
+ notify($ERRORS{'DEBUG'}, 0, "attempting to power off VM:
$vix_vmx_path");
+ my ($error) = VMPowerOff($vm_handle, VIX_VMPOWEROP_NORMAL);
+ if ($error == VIX_OK) {
+ notify($ERRORS{'DEBUG'}, 0, "powered off VM: $vix_vmx_path");
+ return 1;
+ }
+ elsif ($error == VIX_E_VM_NOT_RUNNING) {
+ notify($ERRORS{'DEBUG'}, 0, "VM is not running: $vix_vmx_path");
+ return 1;
+ }
+ else {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'WARNING'}, 0, "failed to power off VM:
$vix_vmx_path, error: $error, $error_text");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 vm_power_on
+
+ Parameters : $vmx_file_path
+ Returns : boolean
+ Description : Powers on the VM specified by the vmx file path argument.
+
+=cut
+
+sub vm_power_on {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # Get the VM handle
+ my $vm_handle = $self->_get_vm_handle($vix_vmx_path) || return;
+
+ # Call VMPowerOn
+ notify($ERRORS{'DEBUG'}, 0, "attempting to power on VM: $vix_vmx_path");
+ my ($error) = VMPowerOn($vm_handle, VIX_VMPOWEROP_NORMAL,
VIX_INVALID_HANDLE);
+ if ($error == VIX_OK) {
+ notify($ERRORS{'DEBUG'}, 0, "powered on VM: $vix_vmx_path");
+ return 1;
+ }
+ else {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'WARNING'}, 0, "failed to power on VM:
$vix_vmx_path, error: $error, $error_text");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 is_vm_registered
+
+ Parameters : $vmx_file_path
+ Returns : boolean
+ Description : Determines if the VM specified by the vmx file path argument is
+ registered.
+
+=cut
+
+sub is_vm_registered {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # Make sure the VM is registered
+ my @registered_vms = $self->get_registered_vms();
+ if (!...@registered_vms) {
+ notify($ERRORS{'DEBUG'}, 0, "there are no registered VMs");
+ return 0;
+ }
+
+ # Loop through the registered VMs and try to find a match
+ # Can't use grep because the vmx paths contain square brackets
+ for my $registered_vmx_path (@registered_vms) {
+ my $registered_vix_vmx_path =
$self->_get_datastore_path($registered_vmx_path);
+ if ($vix_vmx_path eq $registered_vix_vmx_path) {
+ notify($ERRORS{'DEBUG'}, 0, "VM is registered:
$vix_vmx_path");
+ return 1;
+ }
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "VM is not registered: $vix_vmx_path");
+
+ if (defined($self->{vm_handle}{$vix_vmx_path})) {
+ ReleaseHandle($self->{vm_handle}{$vix_vmx_path});
+ }
+
+ return 0;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 vm_register
+
+ Parameters : $vmx_file_path
+ Returns : boolean
+ Description : Registers the VM specified by the vmx file path argument.
Returns
+ true if the VM is successfully registered or if it is already
+ registered.
+
+=cut
+
+sub vm_register {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # Get the VM host handle
+ my $host_handle = $self->_get_host_handle() || return;
+
+ # Make sure the VM is not already registered
+ if ($self->is_vm_registered($vix_vmx_path)) {
+ notify($ERRORS{'OK'}, 0, "VM is already registered:
$vix_vmx_path");
+ return 1;
+ }
+
+ # Call RegisterVM
+ notify($ERRORS{'DEBUG'}, 0, "attempting to register VM: $vix_vmx_path");
+ my ($error) = RegisterVM($host_handle, $vix_vmx_path);
+ if ($error != VIX_OK) {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'WARNING'}, 0, "failed to register VM:
$vix_vmx_path, error: $error, $error_text");
+ return;
+ }
+
+ # Make sure the VM was successfully registered
+ if ($self->is_vm_registered($vix_vmx_path)) {
+ notify($ERRORS{'OK'}, 0, "registered VM: $vix_vmx_path");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "VM is NOT registered, VIX did not
return an error");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 vm_unregister
+
+ Parameters : $vmx_file_path
+ Returns : boolean
+ Description : Unregisters the VM specified by the vmx file path argument.
+ Returns true if the VM is successfully unregistered or if it was
+ not registered to begin with.
+
+=cut
+
+sub vm_unregister {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # Get the VM host handle
+ my $host_handle = $self->_get_host_handle() || return;
+
+ # Make sure the VM is registered
+ if (!$self->is_vm_registered($vix_vmx_path)) {
+ notify($ERRORS{'OK'}, 0, "VM is not registered: $vix_vmx_path");
+ return 1;
+ }
+
+ # Make sure the VM is powered off
+ # If the VM is on and unregistered, the unregister command will succeed
but the VM remains registered
+ my $power_state = $self->get_vm_power_state($vix_vmx_path) || return;
+ if ($power_state ne 'off') {
+ $self->vm_power_off($vix_vmx_path) || return;
+ }
+
+ # Call RegisterVM
+ notify($ERRORS{'DEBUG'}, 0, "attempting to unregister VM:
$vix_vmx_path");
+ my ($error) = UnregisterVM($host_handle, $vix_vmx_path);
+ if ($error != VIX_OK) {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'WARNING'}, 0, "failed to unregister VM:
$vix_vmx_path, error: $error, $error_text");
+ return;
+ }
+
+ # Make sure the VM was unregistered
+ if (!$self->is_vm_registered($vix_vmx_path)) {
+ notify($ERRORS{'OK'}, 0, "unregistered VM: $vix_vmx_path");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "VM is still registered, VIX did
not return an error");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 is_restricted
+
+ Parameters : none
+ Returns : boolean
+ Description : Determines if remote access to the VM host via the VIX API is
+ restricted due to the type of VMware license being used on the
+ host. 0 is returned if remote access is not restricted. 1 is
+ returned if remote access is restricted and the access to the VM
+ host is read-only.
+
+=cut
+
+sub is_restricted {
+ my $self = shift;
+ if (ref($self) !~ /module/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the VM host handle
+ my $host_handle = $self->_get_host_handle() || return;
+
+ # Call RegisterVM
+ notify($ERRORS{'DEBUG'}, 0, "checking if access to the VM host via the
VIX API is restricted due to the license");
+ my ($error) = RegisterVM($host_handle, '');
+
+ if ($error == VIX_E_LICENSE) {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'DEBUG'}, 0, "access to the VM host via the VIX
API is restricted due to the license, result of attempting to register a VM:
$error_text");
+ return 1;
+ }
+ else {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'DEBUG'}, 0, "access to the VM host via the VIX
API is NOT restricted due to the license");
+ return 0;
+ }
+}
+
+##############################################################################
+
+=head1 PRIVATE API OBJECT METHODS
+
+=cut
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 initialize
+
+ Parameters : none
+ Returns : boolean
+ Description : Initialized the VMware VIX API object by obtaining a VM host
+ handle. False is returned if a host handle cannot be obtained.
+
+=cut
+
+sub initialize {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ $self->_get_host_handle() || return;
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _find_items
+
+ Parameters : $search_type, $timeout_seconds (optional)
+ Returns : array
+ Description : Exposes the VMware VIX API FindItems function. It searches for
+ VMs matching the search type argument. The search type values:
+ -VIX_FIND_RUNNING_VMS (1)
+ -VIX_FIND_REGISTERED_VMS (4)
+
+=cut
+
+sub _find_items {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the VM host handle argument
+ my $host_handle = $self->_get_host_handle() || return;
+
+ # Get the search type argument
+ my $search_type = shift;
+ if (!defined($search_type)) {
+ notify($ERRORS{'WARNING'}, 0, "search type argument was not
supplied");
+ return;
+ }
+
+ # Get the optional timeout seconds argument
+ my $timeout_seconds = shift || 15;
+
+ # Check if the search type is valid and set a string
+ my $search_type_string;
+ if ($search_type == VIX_FIND_RUNNING_VMS) {
+ $search_type_string = 'running VMs';
+ }
+ elsif ($search_type == VIX_FIND_REGISTERED_VMS) {
+ $search_type_string = 'registered VMs';
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "unsupported search type
specified: search_type");
+ }
+ notify($ERRORS{'DEBUG'}, 0, "attempting to find $search_type_string");
+
+ # Call FindItems
+ my ($error, @vm_list) = FindItems($host_handle, $search_type,
$timeout_seconds);
+ if ($error) {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'WARNING'}, 0, "failed to find VMs, error:
$error, $error_text");
+ return;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "found " . scalar(@vm_list) . "
$search_type_string:\n" . join("\n", @vm_list));
+ return @vm_list;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_host_handle
+
+ Parameters : none
+ Returns : boolean
+ Description : Obtains a VM host handle and stores it in the VIX API object.
+
+=cut
+
+sub _get_host_handle {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Check if the host handle has already been obtained
+ if (defined($self->{host_handle}) || $self->{host_handle}) {
+ return $self->{host_handle};
+ }
+
+ my $host_hostname = $self->data->get_vmhost_hostname();
+ my $host_username = $self->data->get_vmhost_profile_username();
+ my $host_password = $self->data->get_vmhost_profile_password();
+ my $host_port = '8333';
+ my $host_service_provider = $self->_get_vix_service_provider();
+
+ # Assemble the URLs to try
+ my @host_url_possibilities = (
+ "https://$host_hostname/sdk",
+ "https://$host_hostname:$host_port/sdk",
+ "http://$host_hostname/sdk",
+ "http://$host_hostname:$host_port/sdk",
+ );
+
+ # Call HostConnect, check how long it takes to connect
+ for my $host_url (@host_url_possibilities) {
+ notify($ERRORS{'DEBUG'}, 0, "attempting to connect to VM host:
$host_url");
+ my ($error, $host_handle) = HostConnect(VIX_API_VERSION,
+
$host_service_provider,
+
$host_url,
+
$host_port,
+
$host_username,
+
$host_password,
+
0,
+
VIX_INVALID_HANDLE);
+
+ # Check if an error occurred
+ if ($error == VIX_OK) {
+ notify($ERRORS{'DEBUG'}, 0, "connected to VM host
$host_url");
+ $self->{host_handle} = $host_handle;
+ return $self->{host_handle};
+ }
+ else {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'DEBUG'}, 0, "unable to connect to VM
host using URL: $host_url, error: $error, $error_text");
+ }
+ }
+
+ notify($ERRORS{'WARNING'}, 0, "failed to connect to VM host using any
of the possible URLs");
+ return;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_vm_handle
+
+ Parameters : $vmx_file_path
+ Returns : VIX VM handle object
+ Description : Obtains a VM handle for the VM specified by the vmx path
+ argument.
+
+=cut
+
+sub _get_vm_handle {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path formatted for VIX
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # If a VM handle was previously obtained, release it
+ if ($self->{vm_handle}{$vix_vmx_path}) {
+ ReleaseHandle($self->{vm_handle}{$vix_vmx_path});
+ }
+
+ # Get the host handle
+ my $host_handle = $self->_get_host_handle() || return;
+
+ # Call HostOpenVM
+ notify($ERRORS{'DEBUG'}, 0, "attempting to obtain VM handle:
$vix_vmx_path");
+ my ($error, $vm_handle) = HostOpenVM($host_handle,
+ $vix_vmx_path,
+ VIX_VMOPEN_NORMAL,
+ VIX_INVALID_HANDLE);
+
+ # Check if error occurred
+ if ($error != VIX_OK) {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'WARNING'}, 0, "failed to obtain VM handle:
$vix_vmx_path, error: $error, $error_text");
+ return;
+ }
+ else {
+ $self->{vm_handle}{$vix_vmx_path} = $vm_handle;
+ return $self->{vm_handle}{$vix_vmx_path};
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_vm_power_states
+
+ Parameters : $vmx_path
+ Returns : array
+ Description : Retrieves the power state names for the VM specified by the vmx
+ path argument. An array containing the names is returned. Valid
+ power state names are:
+ -POWERING_OFF
+ -POWERED_OFF
+ -POWERING_ON
+ -POWERED_ON
+ -SUSPENDING
+ -SUSPENDED
+ -TOOLS_RUNNING
+ -RESETTING
+ -BLOCKED_ON_MSG
+
+
+=cut
+
+sub _get_vm_power_states {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # Get the power state property
+ my ($power_state_id) = $self->_get_properties($vix_vmx_path,
VIX_PROPERTY_VM_POWER_STATE);
+ if (!$power_state_id) {
+ notify($ERRORS{'WARNING'}, 0, "failed to retrieve power state
property for VM: $vix_vmx_path");
+ return;
+ }
+
+ # There may be multiple power states in effect, the value returned must
be evaluated bitwise against the valid power state IDs
+ my @powerstate_names;
+ my $powerstate_string;
+ for my $vix_powerstate_id (keys %VIX_POWERSTATE) {
+ if ($power_state_id & $vix_powerstate_id) {
+ unshift @powerstate_names,
$VIX_POWERSTATE{$vix_powerstate_id};
+ $powerstate_string .=
"$VIX_POWERSTATE{$vix_powerstate_id} ($vix_powerstate_id), ";
+ }
+ }
+ $powerstate_string =~ s/, $//;
+
+ notify($ERRORS{'DEBUG'}, 0, "power states for VM: $vix_vmx_path:\n" .
join("\n", @powerstate_names));
+ return @powerstate_names;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_properties
+
+ Parameters : $vm_handle, $property_id_1, $property_id_2...
+ Returns : array
+ Description : Exposes the VIX GetProperties function to retrieve the
properties
+ of a handle.
+
+=cut
+
+sub _get_properties {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx path and format it for the VIX API
+ my $vix_vmx_path = $self->_get_datastore_path(shift) || return;
+
+ # Get the VM handle argument
+ my $vm_handle = $self->_get_vm_handle($vix_vmx_path) || return;
+
+ # Get the property ID argument
+ my @property_ids = @_;
+ if (!...@property_ids) {
+ notify($ERRORS{'WARNING'}, 0, "property ID arguments were not
supplied");
+ return;
+ }
+
+ # Make sure the property IDs are valid
+ my $property_name_string;
+ for my $property_id (@property_ids) {
+ if (!defined($VIX_PROPERTY_VM{$property_id})) {
+ notify($ERRORS{'WARNING'}, 0, "unsupported property ID
was passed as an argument: $property_id");
+ return;
+ }
+ $property_name_string .= "$VIX_PROPERTY_VM{$property_id}
($property_id), ";
+ }
+ $property_name_string =~ s/, $//;
+
+ # Call GetProperties
+ notify($ERRORS{'DEBUG'}, 0, "attempting to retrieve values of
properties: $property_name_string");
+ my ($error, @property_values) = GetProperties($vm_handle,
@property_ids);
+ if ($error) {
+ my $error_text = GetErrorText($error);
+ notify($ERRORS{'WARNING'}, 0, "failed to retrieve values of
properties: $property_name_string, error: $error, $error_text");
+ return;
+ }
+
+ # Make sure the property ID array is the same size as the value array
+ if (scalar(@property_ids) != scalar(@property_values)) {
+ notify($ERRORS{'WARNING'}, 0, "property ID count " .
scalar(@property_ids) . " does not match the number of properties returned by
GetProperties " . scalar(@property_values));
+ return;
+ }
+
+ # Assemble a string showing the names and values of the properties
retrieved
+ my $property_value_string;
+ for (my $i=0; $i<scalar(@property_ids); $i++) {
+ my $property_id = $property_ids[$i];
+ my $property_name = $VIX_PROPERTY_VM{$property_id};
+ my $property_value = $property_values[$i];
+ $property_value_string .= "$property_name ($property_id) =
$property_value\n"
+ }
+ notify($ERRORS{'DEBUG'}, 0, "retrieved
properties:\n$property_value_string");
+
+ return @property_values;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_datastore_path
+
+ Parameters : $vmx_file_path
+ Returns : string
+ Description : Converts the vmx file path argument to a datastore path.
+
+=cut
+
+sub _get_datastore_path {
+ my ($self) = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the path argument if supplied
+ my $path = shift;
+ if (!$path) {
+ notify($ERRORS{'WARNING'}, 0, "path argument was not supplied");
+ return;
+ }
+
+ # Per the VIX documentation:
+ # For VMware Server 1.x, supply the full path name instead of the
datastore path
+ # Also, if the path already contains a '[' assume it's a datastore path
and return it unaltered
+ my $host_service_provider = $self->_get_vix_service_provider() ||
return;
+ if ($host_service_provider == VIX_SERVICEPROVIDER_VMWARE_SERVER ||
$path =~ /\[/) {
+ return $path;
+ }
+
+ my $datastore_name;
+ my $relative_datastore_path;
+
+ if ($path =~ /^\/vmfs\/volumes\//) {
+ ($datastore_name) = $path =~ /\/vmfs\/volumes\/([^\/]+)/;
+ ($relative_datastore_path) = $path =~ /$datastore_name\/(.*)/;
+ }
+ else {
+ $datastore_name = 'standard';
+
+ my $vmx_base_directory_path =
$self->get_vmx_base_directory_path() || return;
+ ($relative_datastore_path) = $path =~
/$vmx_base_directory_path\/(.*)/;
+ }
+
+ $relative_datastore_path =~ s/(^[\s\/]+|[\s\/]+$)//g if
$relative_datastore_path;
+
+ if (!$datastore_name || !$relative_datastore_path) {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine datastore
name and relative datastore path from path: $path");
+ return;
+ }
+
+ return "[$datastore_name] $relative_datastore_path";
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_vix_service_provider
+
+ Parameters : none
+ Returns : integer
+ Description : Determines the appropriate VIX_SERVICEPROVIDER value to use
+ depending on the VMware product being used. Per the VMware VIX
+ documentation:
+ vCenter Server, ESX/ESXi hosts, VMware Server 2.0:
VIX_SERVICEPROVIDER_VMWARE_VI_SERVER
+ VMware Workstation:
VIX_SERVICEPROVIDER_VMWARE_WORKSTATION
+ VMware Player:
VIX_SERVICEPROVIDER_VMWARE_PLAYER
+ VMware Server 1.0.x:
VIX_SERVICEPROVIDER_VMWARE_SERVER
+
+=cut
+
+sub _get_vix_service_provider {
+ my ($self) = @_;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Return the value stored in this object if it has already been
determined
+ return $self->{service_provider} if $self->{service_provider};
+
+ # Check the VM host type name, figure out which VMware product is being
used and set the object's service_provider key
+ # Use VIX_SERVICEPROVIDER_VMWARE_VI_SERVER as the default value since
it's most common
+ my $vmhost_type_name = $self->data->get_vmhost_type_name();
+ if ($vmhost_type_name =~ /(workstation)/i) {
+ $self->{service_provider} =
VIX_SERVICEPROVIDER_VMWARE_WORKSTATION;
+ notify($ERRORS{'DEBUG'}, 0, "VM type is $vmhost_type_name,
using service provider: VIX_SERVICEPROVIDER_VMWARE_WORKSTATION");
+ }
+ elsif ($vmhost_type_name =~ /(player)/i) {
+ $self->{service_provider} = VIX_SERVICEPROVIDER_VMWARE_PLAYER;
+ notify($ERRORS{'DEBUG'}, 0, "VM host type is $vmhost_type_name,
using service provider: VIX_SERVICEPROVIDER_VMWARE_PLAYER");
+ }
+ elsif ($vmhost_type_name =~ /^(vmwareGSX|vmwarefreeserver|.*1\..*)$/i) {
+ $self->{service_provider} = VIX_SERVICEPROVIDER_VMWARE_SERVER;
+ notify($ERRORS{'DEBUG'}, 0, "VM host type is $vmhost_type_name,
using service provider: VIX_SERVICEPROVIDER_VMWARE_SERVER");
+ }
+ else {
+ $self->{service_provider} =
VIX_SERVICEPROVIDER_VMWARE_VI_SERVER;
+ notify($ERRORS{'DEBUG'}, 0, "VM host type is $vmhost_type_name,
using service provider: VIX_SERVICEPROVIDER_VMWARE_VI_SERVER");
+ }
+
+ return $self->{service_provider};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 DESTROY
+
+ Parameters : none
+ Returns : true
+ Description : Called when the VIX API object is destroyed. Disconnects the
host
+ handle.
+
+=cut
+
+sub DESTROY {
+ my $self = shift;
+ notify($ERRORS{'DEBUG'}, 0, "destructor called, ref(\$self)=" .
ref($self));
+
+ # Check for an overridden destructor
+ $self->SUPER::DESTROY if $self->can("SUPER::DESTROY");
+
+ # Disconnect from the VM host if connected
+ HostDisconnect($self->{host_handle}) if $self->{host_handle};
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+1;
+__END__
+
+=head1 SEE ALSO
+
+L<http://cwiki.apache.org/VCL/>
+
+=cut
Propchange:
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIX_API.pm
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIX_API.pm
------------------------------------------------------------------------------
svn:keywords = Date Revision Author HeadURL Id