VMware {code} Community
litty123
Contributor
Contributor
Jump to solution

How to WaitForUpdates of VMs in a particular cluster?

I am using VMWare VSphere WS SDK in Python using the suds client. I want to wait for any changes to VMs. I am specifically interested in VMs of a particular cluster. Is there a way in the propertyfilterspec to say that? I tried setting the managed object reference of the cluster in the ObjectSpec with no avail. Is there anything I am missing?


Concerned piece of code is :


    object_spec = client_factory.create('ns0:ObjectSpec')

    object_spec.obj = clu_mor

    object_spec.skip = False

    object_spec.selectSet = build_recursive_traversal_spec(client_factory)

def build_selection_spec(client_factory, name):

    """Builds the selection spec."""

    sel_spec = client_factory.create('ns0:SelectionSpec')

    sel_spec.name = name

    return sel_spec

def build_traversal_spec(client_factory, name, spec_type, path, skip,

                         select_set):

    """Builds the traversal spec object."""

    traversal_spec = client_factory.create('ns0:TraversalSpec')

    traversal_spec.name = name

    traversal_spec.type = spec_type

    traversal_spec.path = path

    traversal_spec.skip = skip

    traversal_spec.selectSet = select_set

    return traversal_spec

def build_recursive_traversal_spec(client_factory):

    """

    Builds the Recursive Traversal Spec to traverse the object managed

    object hierarchy.

    """

    visit_folders_select_spec = build_selection_spec(client_factory,

                                    "visitFolders")

    # For getting to hostFolder from datacenter

    dc_to_hf = build_traversal_spec(client_factory, "dc_to_hf", "Datacenter",

                                    "hostFolder", False,

                                    [visit_folders_select_spec])

    # For getting to vmFolder from datacenter

    dc_to_vmf = build_traversal_spec(client_factory, "dc_to_vmf", "Datacenter",

                                     "vmFolder", False,

                                     [visit_folders_select_spec])

    # For getting Host System to virtual machine

    h_to_vm = build_traversal_spec(client_factory, "h_to_vm", "HostSystem",

                                   "vm", False,

                                   [visit_folders_select_spec])

    # For getting to networkfolder from datacenter

    dc_to_nwf = build_traversal_spec(client_factory, "dc_to_nwf", "Datacenter",

                                     "networkFolder", False,

                                     [visit_folders_select_spec])

   

    # For getting to Host System from Compute Resource

    cr_to_h = build_traversal_spec(client_factory, "cr_to_h",

                                   "ComputeResource", "host", False, [])

    # For getting to datastore from Compute Resource

    cr_to_ds = build_traversal_spec(client_factory, "cr_to_ds",

                                    "ComputeResource", "datastore", False, [])

    rp_to_rp_select_spec = build_selection_spec(client_factory, "rp_to_rp")

    rp_to_vm_select_spec = build_selection_spec(client_factory, "rp_to_vm")

    # For getting to resource pool from Compute Resource

    cr_to_rp = build_traversal_spec(client_factory, "cr_to_rp",

                                "ComputeResource", "resourcePool", False,

                                [rp_to_rp_select_spec, rp_to_vm_select_spec])

    # For getting to child res pool from the parent res pool

    rp_to_rp = build_traversal_spec(client_factory, "rp_to_rp", "ResourcePool",

                                "resourcePool", False,

                                [rp_to_rp_select_spec, rp_to_vm_select_spec])

    # For getting to Virtual Machine from the Resource Pool

    rp_to_vm = build_traversal_spec(client_factory, "rp_to_vm", "ResourcePool",

                                "vm", False,

                                [rp_to_rp_select_spec, rp_to_vm_select_spec])

    # Get the assorted traversal spec which takes care of the objects to

    # be searched for from the root folder

    traversal_spec = build_traversal_spec(client_factory, "visitFolders",

                                  "Folder", "childEntity", False,

                                  [visit_folders_select_spec, dc_to_hf,

                                   dc_to_vmf, dc_to_nwf, cr_to_ds, cr_to_h, cr_to_rp,

                                   rp_to_rp, h_to_vm, rp_to_vm])

    return traversal_spec

0 Kudos
1 Solution

Accepted Solutions
litty123
Contributor
Contributor
Jump to solution

@stumpr Only a propertycollector gives you a update of changes rite? Can I use ContainerView to wait for updates from any VM under a cluster?

@BenN Thanks for your reply. I figured it out some days back. In case some one else stumbles on this, below is the python code which I wrote for creating the traversal spec:

def build_recursive_traversal_spec(client_factory):

    #Recurse through all ResourcePools

    rp_to_rp = client_factory.create('ns0:TraversalSpec')

    rp_to_rp.name = 'rpToRp'

    rp_to_rp.type = 'ResourcePool'

    rp_to_rp.path = 'resourcePool'

    rp_to_rp.skip = False

    rp_to_vm = client_factory.create('ns0:TraversalSpec')

    rp_to_vm.name = 'rpToVm'

    rp_to_vm.type = 'ResourcePool'

    rp_to_vm.path = 'vm'

    rp_to_vm.skip = False

    spec_array_resource_pool = [client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec')]

    spec_array_resource_pool[0].name = 'rpToRp'

    spec_array_resource_pool[1].name = 'rpToVm'

    rp_to_rp.selectSet = spec_array_resource_pool

    #Traversal through resource pool branch

    cr_to_rp = client_factory.create('ns0:TraversalSpec')

    cr_to_rp.name = 'crToRp'

    cr_to_rp.type = 'ComputeResource'

    cr_to_rp.path = 'resourcePool'

    cr_to_rp.skip = False

    spec_array_computer_resource = [client_factory.create('ns0:SelectionSpec'),

                                    client_factory.create('ns0:SelectionSpec')]

    spec_array_computer_resource[0].name = 'rpToRp'

    spec_array_computer_resource[1].name = 'rpToVm'

    cr_to_rp.selectSet = spec_array_computer_resource

    #Traversal through host branch

    cr_to_h = client_factory.create('ns0:TraversalSpec')

    cr_to_h.name = 'crToH'

    cr_to_h.type = 'ComputeResource'

    cr_to_h.path = 'host'

    cr_to_h.skip = False

    #Traversal through hostFolder branch

    dc_to_hf = client_factory.create('ns0:TraversalSpec')

    dc_to_hf.name = 'dcToHf'

    dc_to_hf.type = 'Datacenter'

    dc_to_hf.path = 'hostFolder'

    dc_to_hf.skip = False

    spec_array_datacenter_host = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datacenter_host[0].name = 'visitFolders'

    dc_to_hf.selectSet = spec_array_datacenter_host

    #Traversal through vmFolder branch

    dc_to_vmf = client_factory.create('ns0:TraversalSpec')

    dc_to_vmf.name = 'dcToVmf'

    dc_to_vmf.type = 'Datacenter'

    dc_to_vmf.path = 'vmFolder'

    dc_to_vmf.skip = False

    spec_array_datacenter_vm = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datacenter_vm[0].name = 'visitFolders'

    dc_to_vmf.selectSet = spec_array_datacenter_vm

    #Traversal through datastore branch

    dc_to_ds = client_factory.create('ns0:TraversalSpec')

    dc_to_ds.name = 'dcToDs'

    dc_to_ds.type = 'Datacenter'

    dc_to_ds.path = 'datastore'

    dc_to_ds.skip = False

    spec_array_datacenter_ds = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datacenter_ds[0].name = 'visitFolders'

    dc_to_ds.selectSet = spec_array_datacenter_ds

    #Recurse through all hosts

    h_to_vm = client_factory.create('ns0:TraversalSpec')

    h_to_vm.name = 'hToVm'

    h_to_vm.type = 'HostSystem'

    h_to_vm.path = 'vm'

    h_to_vm.skip = False

    spec_array_host_vm = [client_factory.create('ns0:SelectionSpec')]

    spec_array_host_vm[0].name = 'visitFolders'

    h_to_vm.selectSet = spec_array_host_vm

    #Recurse through all datastores

    ds_to_vm = client_factory.create('ns0:TraversalSpec')

    ds_to_vm.name = 'dsToVm'

    ds_to_vm.type = 'Datastore'

    ds_to_vm.path = 'vm'

    ds_to_vm.skip = False

    spec_array_datastore_vm = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datastore_vm[0].name = 'visitFolders'

    ds_to_vm.selectSet = spec_array_datastore_vm

    #Recurse through the folders

    visit_folders = client_factory.create('ns0:TraversalSpec')

    visit_folders.name = 'visitFolders'

    visit_folders.type = 'Folder'

    visit_folders.path = 'childEntity'

    visit_folders.skip = False

    spec_array_visit_folders = [client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec')]

    spec_array_visit_folders[0].name = 'visitFolders'

    spec_array_visit_folders[1].name = 'dcToHf'

    spec_array_visit_folders[2].name = 'dcToVmf'

    spec_array_visit_folders[3].name = 'crToH'

    spec_array_visit_folders[4].name = 'crToRp'

    spec_array_visit_folders[5].name = 'dcToDs'

    spec_array_visit_folders[6].name = 'hToVm'

    spec_array_visit_folders[7].name = 'dsToVm'

    spec_array_visit_folders[8].name = 'rpToVm'

    visit_folders.selectSet = spec_array_visit_folders

    #Add all of them here

    spec_array = [visit_folders, dc_to_vmf, dc_to_ds, dc_to_hf, cr_to_h,

                  cr_to_rp, rp_to_rp, h_to_vm, ds_to_vm, rp_to_vm]

    return spec_array

View solution in original post

0 Kudos
4 Replies
stumpr
Virtuoso
Virtuoso
Jump to solution

I'd use a ContainerView object, setting the root to the Cluster entity.  You won't need your traversal specs in that case, just your property list.

I think there is an example of using Views in the SDK.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
BenN
Enthusiast
Enthusiast
Jump to solution

The TraversalSpec you're putting in your ObjectSpec is only going to match Folder objects, but you're putting

a ComputeResource object in the ObjectSpec. Thus, no matches.

Attached is a Java snippet that does what you want, it should be easy enough to translate to Python.

0 Kudos
litty123
Contributor
Contributor
Jump to solution

@stumpr Only a propertycollector gives you a update of changes rite? Can I use ContainerView to wait for updates from any VM under a cluster?

@BenN Thanks for your reply. I figured it out some days back. In case some one else stumbles on this, below is the python code which I wrote for creating the traversal spec:

def build_recursive_traversal_spec(client_factory):

    #Recurse through all ResourcePools

    rp_to_rp = client_factory.create('ns0:TraversalSpec')

    rp_to_rp.name = 'rpToRp'

    rp_to_rp.type = 'ResourcePool'

    rp_to_rp.path = 'resourcePool'

    rp_to_rp.skip = False

    rp_to_vm = client_factory.create('ns0:TraversalSpec')

    rp_to_vm.name = 'rpToVm'

    rp_to_vm.type = 'ResourcePool'

    rp_to_vm.path = 'vm'

    rp_to_vm.skip = False

    spec_array_resource_pool = [client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec')]

    spec_array_resource_pool[0].name = 'rpToRp'

    spec_array_resource_pool[1].name = 'rpToVm'

    rp_to_rp.selectSet = spec_array_resource_pool

    #Traversal through resource pool branch

    cr_to_rp = client_factory.create('ns0:TraversalSpec')

    cr_to_rp.name = 'crToRp'

    cr_to_rp.type = 'ComputeResource'

    cr_to_rp.path = 'resourcePool'

    cr_to_rp.skip = False

    spec_array_computer_resource = [client_factory.create('ns0:SelectionSpec'),

                                    client_factory.create('ns0:SelectionSpec')]

    spec_array_computer_resource[0].name = 'rpToRp'

    spec_array_computer_resource[1].name = 'rpToVm'

    cr_to_rp.selectSet = spec_array_computer_resource

    #Traversal through host branch

    cr_to_h = client_factory.create('ns0:TraversalSpec')

    cr_to_h.name = 'crToH'

    cr_to_h.type = 'ComputeResource'

    cr_to_h.path = 'host'

    cr_to_h.skip = False

    #Traversal through hostFolder branch

    dc_to_hf = client_factory.create('ns0:TraversalSpec')

    dc_to_hf.name = 'dcToHf'

    dc_to_hf.type = 'Datacenter'

    dc_to_hf.path = 'hostFolder'

    dc_to_hf.skip = False

    spec_array_datacenter_host = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datacenter_host[0].name = 'visitFolders'

    dc_to_hf.selectSet = spec_array_datacenter_host

    #Traversal through vmFolder branch

    dc_to_vmf = client_factory.create('ns0:TraversalSpec')

    dc_to_vmf.name = 'dcToVmf'

    dc_to_vmf.type = 'Datacenter'

    dc_to_vmf.path = 'vmFolder'

    dc_to_vmf.skip = False

    spec_array_datacenter_vm = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datacenter_vm[0].name = 'visitFolders'

    dc_to_vmf.selectSet = spec_array_datacenter_vm

    #Traversal through datastore branch

    dc_to_ds = client_factory.create('ns0:TraversalSpec')

    dc_to_ds.name = 'dcToDs'

    dc_to_ds.type = 'Datacenter'

    dc_to_ds.path = 'datastore'

    dc_to_ds.skip = False

    spec_array_datacenter_ds = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datacenter_ds[0].name = 'visitFolders'

    dc_to_ds.selectSet = spec_array_datacenter_ds

    #Recurse through all hosts

    h_to_vm = client_factory.create('ns0:TraversalSpec')

    h_to_vm.name = 'hToVm'

    h_to_vm.type = 'HostSystem'

    h_to_vm.path = 'vm'

    h_to_vm.skip = False

    spec_array_host_vm = [client_factory.create('ns0:SelectionSpec')]

    spec_array_host_vm[0].name = 'visitFolders'

    h_to_vm.selectSet = spec_array_host_vm

    #Recurse through all datastores

    ds_to_vm = client_factory.create('ns0:TraversalSpec')

    ds_to_vm.name = 'dsToVm'

    ds_to_vm.type = 'Datastore'

    ds_to_vm.path = 'vm'

    ds_to_vm.skip = False

    spec_array_datastore_vm = [client_factory.create('ns0:SelectionSpec')]

    spec_array_datastore_vm[0].name = 'visitFolders'

    ds_to_vm.selectSet = spec_array_datastore_vm

    #Recurse through the folders

    visit_folders = client_factory.create('ns0:TraversalSpec')

    visit_folders.name = 'visitFolders'

    visit_folders.type = 'Folder'

    visit_folders.path = 'childEntity'

    visit_folders.skip = False

    spec_array_visit_folders = [client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec'),

                                client_factory.create('ns0:SelectionSpec')]

    spec_array_visit_folders[0].name = 'visitFolders'

    spec_array_visit_folders[1].name = 'dcToHf'

    spec_array_visit_folders[2].name = 'dcToVmf'

    spec_array_visit_folders[3].name = 'crToH'

    spec_array_visit_folders[4].name = 'crToRp'

    spec_array_visit_folders[5].name = 'dcToDs'

    spec_array_visit_folders[6].name = 'hToVm'

    spec_array_visit_folders[7].name = 'dsToVm'

    spec_array_visit_folders[8].name = 'rpToVm'

    visit_folders.selectSet = spec_array_visit_folders

    #Add all of them here

    spec_array = [visit_folders, dc_to_vmf, dc_to_ds, dc_to_hf, cr_to_h,

                  cr_to_rp, rp_to_rp, h_to_vm, ds_to_vm, rp_to_vm]

    return spec_array

0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

Perl example, but shouldn't be too hard to convert.  Not sure which Python kit your using and if they exposed all the SDK objects.

#!/usr/bin/perl

use strict;

use warnings;

use VMware::VIRuntime;

my %opts = (

  clustername => {

  type => "=s",

  variable => "CLUSTERNAME",

  help => "Name of cluster entity",

  required => 1,

  }

);

Opts::add_options(%opts);

Opts::parse();

Opts::validate();

Util::connect();

my ($cluster_name, $cluster_view, $view_manager, $container_view, $moref, $version,

  $property_collector, $property_spec, $filter_spec, $traversal_spec, $update_set,

  $object_spec, $filter );

$cluster_name = Opts::get_option('clustername');

$cluster_view = Vim::find_entity_view(view_type => 'ClusterComputeResource',

  filter => { 'name' => $cluster_name },

  properties => [ 'name' ] );

die "Failed to find cluster '$cluster_name' in inventory" unless $cluster_name;

# View Manager

$view_manager = Vim::get_view( mo_ref => Vim::get_service_content->viewManager );

die "Failed to retrieve View Manager" unless $view_manager;

# Create Container View

$moref = $view_manager->CreateContainerView(

  container => $cluster_view, # Container starting point in inventory tree

  recursive => 1, # Recurse through folders, resource pools, etc.

  type => [ 'VirtualMachine' ], # Add additional entity types if required

);

$container_view = Vim::get_view( mo_ref => $moref );

# Get default session property collector

$property_collector = Vim::get_view( mo_ref => Vim::get_service_content->propertyCollector );

die "Failed to retrieve session Property Collector" unless $property_collector;

# What vm properties do you want to monitor?  Guessing 'all', though that may be too much

# noise depending on your needs.

# PropertySpec - VirtualMachines

$property_spec = new PropertySpec(all => 1, type => 'VirtualMachine');

# TraversalSpec is the ContainerView, which already has captured a set of VMs.  For the

# type, use the moref type of the container_view (here, moref->{type} or use

# $container_view->{mo_ref}->{type}

$traversal_spec = new TraversalSpec(type => $moref->{'type'},

  path => 'view' );

# ObjectSpec

$object_spec = new ObjectSpec(obj => $container_view,

  selectSet => [ $traversal_spec ],

  skip => 1 );

# Create a PropertyFilterSpec.  In this case, will make your selectSet the view container

# traversal spec.

$filter_spec = new PropertyFilterSpec(

  objectSet => [ $object_spec ],

  propSet => [ $property_spec ],

  reportMissingObjectsInResults => 1 );

# Now create a filter.  Depending on your logic, you'll want partialUpdates = 1 or 0.

# For now, will assume 1, which means you will get a full VM update vs partial when any

# vm property is modified.

$filter = $property_collector->CreateFilter(spec => $filter_spec, partialUpdates => 0);

# Loop, waiting for changes

print "Entering update wait loop...\n";

$version = ''; # Initial version should be empty string

while (1) {

  $update_set = $property_collector->WaitForUpdatesEx(version => $version);

  if (defined $update_set) {

  print "Updates found!\n";

  # Here you would iterate the filterSet and objectSet lists, getting the obj (moref)

  # and update changeSet + kind.

  $version = $update_set->{version}; # Get new version string

  }

}

Util::disconnect();

BEGIN {

  $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

}

Sample run:

perl clustervms.pl --clustername=DC0_C0 --username=administrator@vlab --password=VMware1! --server=172.16.254.71

Entering update wait loop...

Updates found!

Updates found!

Updates found!

Updates found!

Updates found!

Updates found!

Updates found!

I'm using a VCSIM setup, which does some random activity to generate changes.  I didn't delve into the loops to parse the UpdateSet data, but I've done so before.  Requires some logic to evaluate the changes in detail.  But if you just want to know a VM changed (but not what), you can just get the obj moref from the updateSet.

Reuben Stump | http://www.virtuin.com | @ReubenStump