VMware ESXi supports the WS-Management protocol in addition to the CIM-XML protocol for passing CIM information between client and server. VMware provides WS-Management client libraries as part of the vSphere SDK for Perl.

In the VMware Web Services for Management Perl Library there are two API layers recommended for Perl clients:

  • WSMan::WSBasic implements serialization and deserialization of objects transported with the SOAP protocol.
  • WSMan::GenericOps implements a wrapper interface for WSMan::WSBasic. WSMan::GenericOps provides CIM objects in the form of Perl hashes.
    Note: The StubOps API layer, which provided a wrapper for WSMan::GenericOps, was deprecated in ESXi 5.0. You can use the GenericOps API layer to get the same results.

Using the WSMan::GenericOps layer of the SDK is similar to using a CIM-XML client library. The client creates a connection object, enumerates instances, and traverses associations in the same general way as described in Make a Connection to the CIMOM, Listing Registered Profiles in the CIM Implementation, and Identifying the Base Server Scoping Instance. For more information about the vSphere SDK for Perl, see the vSphere SDK for Perl Programming Guide.

The following code example shows how you can make a connection to the CIM server, enumerate registered profiles, and follow the ElementConformsToProfile association to the Base Server Scoping Instance of ComputerSystem.

#!/usr/bin/perl
use strict;
use warnings;
use VMware::VIRuntime;
use WSMan::GenericOps;
use VMware::VILib;
$Util::script_version = "1.0";
=pod
  USAGE:: perl central_server.pl --server myserver.example.com --username abc
          --password xxxx [--namespace xxx/xxx] [--timeout numsecs]
=cut
my %opts = (
   namespace  => {
      type     => '=s',
      help     => 'Namespace for queries. Default is root/interop for profile registration.',
      required => 0,
      default => 'root/interop',
   },
   timeout  => {
      type  => '=s',
      help  => 'Default http timeout for all the queries. Default is 120',
      required => 0,
      default => '120'
   },
);
Opts::add_options( %opts );
Opts::parse();
Opts::validate();

Opts::set_option( 'protocol', 'http' );
Opts::set_option( 'servicepath', '/wsman' );
Opts::set_option( 'portnumber', '80');

sub create_connection_object
{
   my %args = (
      path => Opts::get_option( 'servicepath' ),
      username => Opts::get_option( 'username' ),
      password => Opts::get_option( 'password' ),
      port => Opts::get_option ( 'portnumber' ),
      address => Opts::get_option ( 'server' ),
      namespace => Opts::get_option( 'namespace' ),
      timeout  => Opts::get_option( 'timeout' )
   );
   my $client = WSMan::GenericOps->new( %args );
   if ( not defined $client ) {
      print "Failed to create connection object.\n";
      return undef;
   }
   # Add resource URIs for derived classes:
   $client->register_class_ns( OMC => 'http://schema.omc-project.org/wbem/wscim/1/cim-schema/2',
                               VMware => 'http://schemas.vmware.com/wbem/wscim/1/cim-schema/2',
                             );
   return $client;
}

sub get_registered_profiles
{
   my ($client) = @_;
   my @instances = ();
   eval {
      @instances = $client->EnumerateInstances(
                                class_name => 'CIM_RegisteredProfile' );
   };
   if ( $@ ) {
      print "Failed EnumerateInstances() on CIM_RegisteredProfile.\n";
      die $@;
   }
   return @instances;
}

sub isolate_base_server_registration
{
   my ($client, @instances) = @_;
   foreach my $instance (@instances) {
      my $class_name = ( keys %$instance )[ 0 ];
      my $profile = $instance->{ $class_name };
      if ( $profile->{'RegisteredName'}
        && $profile->{'RegisteredName'} eq 'Base Server' ) {
         return $instance;
      }
   }
   return undef;
}

sub associate_to_scoping_instance
{
   my ($client, $instance) = @_;
   my $class_name = ( keys %$instance )[ 0 ];
   my $profile = $instance->{ $class_name };
   my @instances = ();
   eval {
      @instances = $client->EnumerateAssociatedInstances(
                                 class_name => $class_name,
                                 selectors => $profile,
                                 associationclassname => 'CIM_ElementConformsToProfile',
                                 resultrole => 'ManagedElement' );
   };
   if ( $@ ) {
      print "Failed EnumerateAssociatedInstances() for Base Server profile registration.\n";
      die $@;
   }
   if ( scalar( @instances ) > 1 ) {
      print "Error: " . scalar( @instances ) . " Scoping Instances found.\n";
      return undef;
   }
   pop @instances;
}

# Create client connection object for ESX host:
my $client = create_connection_object();
if ( not defined $client ) {
   die "Aborting.\n";
}
my @profile_instances = get_registered_profiles( $client );
if ( scalar( @profile_instances ) == 0 ) {
   die( 'No registered profile instances found on '
        . Opts::get_option( 'server' ) . ':'
        . Opts::get_option( 'namespace' ) . "\n"
      );
}
my $profile_instance = isolate_base_server_registration( $client, @profile_instances );
if ( not defined $profile_instance ) {
   die( "Base Server profile is not registered in namespace.\n" );
}
my $scoping_instance = associate_to_scoping_instance( $client, $profile_instance );
if ( not defined $scoping_instance ) {
   die( "No managed element found for base server.\n" );
}
print "Base Server profile Scoping Instance properties:\n";
my $class_name = ( keys %$scoping_instance )[ 0 ];
my $base_server = $scoping_instance->{ $class_name };
for my $property (keys %$base_server ) {
   my $value = 'undefined';
   if ( defined $base_server->{$property} ) {
      $value = $base_server->{$property}
   }
   print '  ', $property, ': ', $value, "\n";
}