VMware {code} Community
stumpr
Virtuoso
Virtuoso

find_entity_view & DistributedVirtualSwitches

I just had a co-worker ask for some help on automation with the Perl SDK around DistributedVirtualPortgroups.

What I quickly found out is that find_entity_view calls will not work. And for a very simple reason. TraversalSpecs for networkFolder and datastoreFolder were not added to the subroutine get_search_filter_spec in VICommon.pm. Smiley Wink

It seems like an oversight to have skipped TraversalSpecs for these folders. Without modifying VICommon.pm or calling RetrieveProperties directly, you'll need to do some klunky enumeration of Datacenter(s) and Network properties.

Is this something that others have run into or at least something that is slated to be fixed in a future release of the VI Perl SDK?

I updated the subroutine get_search_filter_spec in VICommon.pm to the following and it works quite simply. Similar specs would have to be added for the datastoreFolder

sub get_search_filter_spec {   
   my ($class, $mo_ref, $property_spec) = @_;
   my $resourcePoolTraversalSpec =
      TraversalSpec->new(name => 'resourcePoolTraversalSpec',
                         type => 'ResourcePool',
                         path => 'resourcePool',
                         skip => 0,
                         selectSet => [SelectionSpec->new(name => 'resourcePoolTraversalSpec'),
                                       SelectionSpec->new(name => 'resourcePoolVmTraversalSpec')]);      

   my $resourcePoolVmTraversalSpec =
      TraversalSpec->new(name => 'resourcePoolVmTraversalSpec',
                         type => 'ResourcePool',
                         path => 'vm',
                         skip => 0);   

   my $computeResourceRpTraversalSpec =
      TraversalSpec->new(name => 'computeResourceRpTraversalSpec',
                         type => 'ComputeResource',
                         path => 'resourcePool',
                         skip => 0,
                         selectSet => [SelectionSpec->new(name => 'resourcePoolTraversalSpec'),
                                       SelectionSpec->new(name => 'resourcePoolVmTraversalSpec')]);      
      
   
   my $computeResourceHostTraversalSpec =
      TraversalSpec->new(name => 'computeResourceHostTraversalSpec',
                         type => 'ComputeResource',
                         path => 'host',
                         skip => 0);
         
   my $datacenterHostTraversalSpec =
      TraversalSpec->new(name => 'datacenterHostTraversalSpec',
                         type => 'Datacenter',
                         path => 'hostFolder',
                         skip => 0,
                         selectSet => );
   
   my $datacenterVmTraversalSpec =
      TraversalSpec->new(name => 'datacenterVmTraversalSpec',
                         type => 'Datacenter',
                         path => 'vmFolder',
                         skip => 0,
                         selectSet => );

   my $hostVmTraversalSpec =
      TraversalSpec->new(name => 'hostVmTraversalSpec',
                         type => 'HostSystem',
                         path => 'vm',
                         skip => 0,
                         selectSet => );

   my $datacenterNetTraversalSpec =
     TraversalSpec->new(name => 'datacenterNetTraversalSpec',
                        type => 'Datacenter',
                        path => 'networkFolder',
                        skip => 0,
                        selectSet => );
      
   my $folderTraversalSpec =
      TraversalSpec->new(name => 'folderTraversalSpec',
                         type => 'Folder',
                         path => 'childEntity',
                         skip => 0,
                         selectSet => [SelectionSpec->new(name => 'folderTraversalSpec'),
                                       SelectionSpec->new(name => 'datacenterHostTraversalSpec'),
                                       SelectionSpec->new(name => 'datacenterVmTraversalSpec',),
                                       SelectionSpec->new(name => 'computeResourceRpTraversalSpec'),
                                       SelectionSpec->new(name => 'computeResourceHostTraversalSpec'),
                                       SelectionSpec->new(name => 'hostVmTraversalSpec'),
                                       SelectionSpec->new(name => 'resourcePoolVmTraversalSpec'),
                                       SelectionSpec->new(name => 'datacenterNetTraversalSpec'),
                                       ]);
   
   my $obj_spec = ObjectSpec->new(obj => $mo_ref,
                                  skip => 0,
                                  selectSet => [$folderTraversalSpec,
                                                $datacenterVmTraversalSpec,
                                                $datacenterHostTraversalSpec,
                                                $computeResourceHostTraversalSpec,
                                                $computeResourceRpTraversalSpec,
                                                $resourcePoolTraversalSpec,
                                                $hostVmTraversalSpec,
                                                $datacenterNetTraversalSpec,
                                                $resourcePoolVmTraversalSpec]);
   
   return PropertyFilterSpec->new(propSet => $property_spec,
                                  objectSet => [$obj_spec]);
}

The following code is much simpler than having to do a few nested soap calls on network objects from each Datacenter in the inventory.

#!/usr/bin/perl

use strict;
use warnings;

use VMware::VIRuntime;

Opts::parse();
Opts::validate();

Util::connect();

my $dvpgs = Vim::find_entity_views(view_type => "DistributedVirtualPortgroup",
									properties => \['name']);
									
foreach (@{$dvpgs}) {
	my $portgroup = $_->{'name'};
	print "Distributed Virtual Portgroup: $portgroup\n";
} 

Just a quick note in case someone else has run into this snag with the VI Perl SDK and needed a fix. Obviously this requires modifying the VICommon.pm module provided by the SDK. The other option would be to build PropertyFilterSpecs and call RetrieveProperties, skipping the utility function find_entity_view.

EDIT: Ugh, the forum code mangled the function, watch directly copying and pasting from this post! Look at datacenterNetTraversalSpec which I added to the subroutine to support the networkFolder with find_entity_view.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
11 Replies
lamw
Community Manager
Community Manager

Great post Ruben!

Sounds more like a bug to me and something that VMware should fix Smiley Wink

I had not dug into the VICommon.pm when I had to extrac vDS information and had to go through the ugly route of traversing datacenter/networks to get to the vDS and vDP

=========================================================================

William Lam

VMware vExpert 2009

VMware ESX/ESXi scripts and resources at:

Twitter: @lamw

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

stumpr
Virtuoso
Virtuoso

William,

Funny thing is, my co-worker sent me a script from the client you obviously updated and touched -- updateVMPortgroupLS.pl. They just wanted to take out the need to have parameters with the uuid and dvPortgroup key value and use something simpler, like the Portgroup friendly name (as seen in vCenter).

So, being a bit persistent, I found a really slick solution as a quick fix to this. You really have to love Perl.

There is a simple source module called Sub::Override that allows you to override subroutines. A quick CPAN install later (you could probably copy the Sub::Override source file to your Perl path) and I have a working solution that doesn't require patching VICommon.pm.


#!/usr/bin/perl

use strict;
use warnings;

use VMware::VIRuntime;
use Sub::Override;

Opts::parse();
Opts::validate();

Util::connect();

my $override = Sub::Override->new( 'EntityViewBase::get_search_filter_spec' => \&get_search_filter_spec2);

my $dvpgs = Vim::find_entity_views(view_type => "DistributedVirtualPortgroup",
									properties => \['name']);
									
foreach (@{$dvpgs}) {
	my $portgroup = $_->{'name'};
	print "Distributed Virtual Portgroup: $portgroup\n";
} 

sub get_search_filter_spec2 {   
   my ($class, $mo_ref, $property_spec) = @_;
   my $resourcePoolTraversalSpec =
      TraversalSpec->new(name => 'resourcePoolTraversalSpec',
                         type => 'ResourcePool',
                         path => 'resourcePool',
                         skip => 0,
                         selectSet => [SelectionSpec->new(name => 'resourcePoolTraversalSpec'),
                                       SelectionSpec->new(name => 'resourcePoolVmTraversalSpec')]);      

   my $resourcePoolVmTraversalSpec =
      TraversalSpec->new(name => 'resourcePoolVmTraversalSpec',
                         type => 'ResourcePool',
                         path => 'vm',
                         skip => 0);   

   my $computeResourceRpTraversalSpec =
      TraversalSpec->new(name => 'computeResourceRpTraversalSpec',
                         type => 'ComputeResource',
                         path => 'resourcePool',
                         skip => 0,
                         selectSet => [SelectionSpec->new(name => 'resourcePoolTraversalSpec'),
                                       SelectionSpec->new(name => 'resourcePoolVmTraversalSpec')]);      
      
   
   my $computeResourceHostTraversalSpec =
      TraversalSpec->new(name => 'computeResourceHostTraversalSpec',
                         type => 'ComputeResource',
                         path => 'host',
                         skip => 0);
         
   my $datacenterHostTraversalSpec =
      TraversalSpec->new(name => 'datacenterHostTraversalSpec',
                         type => 'Datacenter',
                         path => 'hostFolder',
                         skip => 0,
                         selectSet => \[SelectionSpec->new(name => "folderTraversalSpec")]);
   
   my $datacenterVmTraversalSpec =
      TraversalSpec->new(name => 'datacenterVmTraversalSpec',
                         type => 'Datacenter',
                         path => 'vmFolder',
                         skip => 0,
                         selectSet => \[SelectionSpec->new(name => "folderTraversalSpec")]);

   my $datacenterNetTraversalSpec =
      TraversalSpec->new(name => 'datacenterNetTraversalSpec',
                         type => 'Datacenter',
                         path => 'networkFolder',
                         skip => 0,
                         selectSet => \[SelectionSpec->new(name => "folderTraversalSpec")]);

   my $hostVmTraversalSpec =
      TraversalSpec->new(name => 'hostVmTraversalSpec',
                         type => 'HostSystem',
                         path => 'vm',
                         skip => 0,
                         selectSet => \[SelectionSpec->new(name => "folderTraversalSpec")]);
      
   my $folderTraversalSpec =
      TraversalSpec->new(name => 'folderTraversalSpec',
                         type => 'Folder',
                         path => 'childEntity',
                         skip => 0,
                         selectSet => [SelectionSpec->new(name => 'folderTraversalSpec'),
                                       SelectionSpec->new(name => 'datacenterHostTraversalSpec'),
                                       SelectionSpec->new(name => 'datacenterVmTraversalSpec',),
                                       SelectionSpec->new(name => 'datacenterNetTraversalSpec',),
                                       SelectionSpec->new(name => 'computeResourceRpTraversalSpec'),
                                       SelectionSpec->new(name => 'computeResourceHostTraversalSpec'),
                                       SelectionSpec->new(name => 'hostVmTraversalSpec'),
                                       SelectionSpec->new(name => 'resourcePoolVmTraversalSpec'),
                                       ]);
   
   my $obj_spec = ObjectSpec->new(obj => $mo_ref,
                                  skip => 0,
                                  selectSet => [$folderTraversalSpec,
                                                $datacenterVmTraversalSpec,
						$datacenterNetTraversalSpec,
                                                $datacenterHostTraversalSpec,
                                                $computeResourceHostTraversalSpec,
                                                $computeResourceRpTraversalSpec,
                                                $resourcePoolTraversalSpec,
                                                $hostVmTraversalSpec,
                                                $resourcePoolVmTraversalSpec]);
   
   return PropertyFilterSpec->new(propSet => $property_spec,
                                  objectSet => \[$obj_spec]);
}

Note you'll have to search and replace <backslash>[ with [, the forum mangles open-closed brackets on the same line. You can of course add in a TraversalSpec object for the datastoreFolder if you wanted those objects in your scripts. I just did networkFolder with datacenterNetTraversalSpec for this simple fix.

I'm sure VMware will update/fix it, but it'll have to go through testing to get officially released. This fix might fill the gap for some people until then without breaking their VI Perl SDK support by modifying the VMware core modules.

- Reuben

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
lamw
Community Manager
Community Manager

Very slick solution indeed, glad you shared with the community!

You really have to love Perl.

Agreed!

=========================================================================

William Lam

VMware vExpert 2009

VMware ESX/ESXi scripts and resources at:

Twitter: @lamw

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

0 Kudos
stumpr
Virtuoso
Virtuoso

William,

I updated your script a bit using the Override. The changes allow you to drop the dvSwitchUuid parameter all together and the portgroup parameter becomes the friendly name as seen in the vCenter UI (not the key property of dvPortgroup).

It also prevents you from specifying a dvPortgroup that isn't in the same datacenter as the VM specified by vmname. dvPortgroup friendly names can be reused across Datacenters and you aren't guaranteed a unique name in a single vCenter inventory tree with multiple Datacenters instances.

perl updateVMPortgroupLS2.pl --username=administrator --password=VMware1 --server=172.16.171.130 --vmname="TestVM" --vnic=1 --portgroup=dvPortGroup
Reconfiguration of portgroup "dvPortGroup" successful for "TestVM".

For the attached script to work, Sub::Override will have to be installed using CPAN, PPM, or a manual install (copy Override.pm down from CPAN).

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
ymnick
Enthusiast
Enthusiast

Hi Ruben and William,

Is this still the best way for updating distributed vswitch portgroup with vSphere API 5.0?

Thanks,

ymnick

0 Kudos
stumpr
Virtuoso
Virtuoso

You shouldn't need the sub override anymore, newer API versions have the correct traversal specs to get to the DistributedVirtual* objects.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
ymnick
Enthusiast
Enthusiast

Thanks. And beside that the same technique as in the updateVMPortgroupLS2.pl script above?

0 Kudos
stumpr
Virtuoso
Virtuoso

Yeah, should work.  Haven't tried it, but nothing off the top of my head has changed.  Just one version of the SDK didn't include traversal specs to the new network folder when it was first released (bug).  It was fixed soon after.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
ymnick
Enthusiast
Enthusiast

Okay, thanks again. Then another question - it goes through Datacenter object to retrieve dvPortgroup, does this mean that the connection must be against vCenter and not ESXi for this to work?

0 Kudos
stumpr
Virtuoso
Virtuoso

That's correct.  I don't think the Host API even understands DistributedVirtualSwitches.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
ymnick
Enthusiast
Enthusiast

Thank you.

0 Kudos