VMware {code} Community
vishalsaraswat2
Contributor
Contributor

gSoap/vSphere sdk

Hi all,

I am new to VMWare sdk and gSoap. I was trying to figure out what could be the best possible way to get a hang of it.

As I was going through a lot of Java based code and vSphere implementation which seems pretty simple.

And pointers?

0 Kudos
16 Replies
stumpr
Virtuoso
Virtuoso

gSoap is a bit less intuitive than the Java SDK, primarily b/c gSoap generates very generic code around the SDK WSDL. However, there are some posts on these forums about using gSoap and the SDK. Just do a search for gSoap. I would recommend using C++ and not C for your gSoap project, however. You'll have problems with multiple inheritance on some of the SDK objects with C.

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

Actually, I have a very basic query. For example, if I want to get a list of MangedHosts from vSphere then, as far as I have understood -

a) Set appropriate TraversalSpec

b) Set appropriate PropertySpec

For example in case of Vm we set Virtual Machine, but in case of MangedHosts, I think we have to set ComputerResource, but what all do we keep on setting to fetch a fetch a particular info, is the kind of understanding I require.

Any suggestions?

0 Kudos
njain
Expert
Expert

To get managed hosts information, you will need to set "HostSystem" as part of your propertySpec.

To get more clarity on how to traverse the objects and get properties, you can refer to section "Creating a Specification That Filters Objects and Properties" on page 63 and "Traversing Objects" on page 68 of SDK programming guide.

http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/visdk25programmingguide.pdf

Hope this helps.

0 Kudos
offer2
Contributor
Contributor

(Perfect timing)

I've been trying to follow the code in the "classic gSOAP" post - http://communities.vmware.com/thread/200348, and am getting errors compiling the sample code from you.

In that post you havce

ObjectSpec.obj = ServiceContent->rootFolder;
ObjectSpec.skip = &xsd_true;

ObjectSpec.selectSet.push_back(&FolderTraversalSpec);
ObjectSpec.selectSet.push_back(&DataCenterVMTraversalSpec);

However, ObjectSpec.selectSet is an array of SelectionSpec, not TraversalSpec, so of course any C++ compiler will error at thei point.

0 Kudos
stumpr
Virtuoso
Virtuoso

Definitely review the documents njain posted. It'll help understand the inventory tree.

You're correct though, for HostSystems you'll have to have TraversalSpecs for Datacenter, ComputeResource, ClusterComputeResource and Folder objects. HostSystems are the more complex TraversalSpecs to deal with.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
stumpr
Virtuoso
Virtuoso

TraversalSpec inherits from the SelectionSpec class. You shouldn't be getting those errors if you're WSDL code generation was done properly.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
offer2
Contributor
Contributor

Thanks for the pointer - I'd called wsdl2h with (incorrect) flags that flattened the C++ hierachy.

For reference the following commands generate a working set of files for me (with gSOAP 2.7.16)

% $GSOAPHOME}/bin/ wsdl2h -o gSOAPVimService.h -N vim40 -y -I $/import/ /path/to/vimService.wsdl % mkdir stubs % touch env.h % $/bin/soapcpp2 -d stubs -2 -C -L -pdummy env.h

% $/bin/soapcpp2 -d stubs -2 -C -i -q vim40 -x -I $/import/ gSOAPVimService.h

This generates classes in the vim40 C++ namespace.

Compile vim40VimBindingProxy.cpp and vim40C.cpp with -DWITH_NOGLOBAL -DWITH_OPENSSL -DWITH_COOKIES

Compile dummyC.cpp without WITH_NOGLOBAL defined

% ls stubs/

-rw-rr 1 richard staff 535 Apr 27 16:08 VimBinding.nsmap

-rw-rr 1 richard staff 45246 Apr 27 16:08 dummyC.cpp

-rw-rr 1 richard staff 587 Apr 27 16:08 dummyClient.cpp

-rw-rr 1 richard staff 16277 Apr 27 16:08 dummyH.h

-rw-rr 1 richard staff 4799 Apr 27 16:08 dummyStub.h

-rw-rr 1 richard staff 44860449 Apr 27 16:08 vim40C.cpp

-rw-rr 1 richard staff 8808123 Apr 27 16:08 vim40H.h

-rw-rr 1 richard staff 3574153 Apr 27 16:08 vim40Stub.h

-rw-rr 1 richard staff 933132 Apr 27 16:08 vim40VimBindingProxy.cpp

-rw-rr 1 richard staff 118791 Apr 27 16:08 vim40VimBindingProxy.h

The 44MB C++ file takes a while to compile - ~90minutes on my 4core/4GB iMac.

0 Kudos
stumpr
Virtuoso
Virtuoso

The gSOAP libraries are big, but 90 minutes is pretty long. I do use a Makefile and create static & dynamic libraries out of the gSOAP + SDK compiles. For the most part you won't need to modify those object files if you did all your compile flags properly. I may have my Makefiles around from the last time I worked with C++ gSOAP. I'll see about posting them here after I finish updating my system.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
offer2
Contributor
Contributor

Something is obviously not right on my system - the 900k vim40VimBindingProxy.cpp file takes just seconds to compile.

Guessing something is not scalling in the OS X toolchain.

However its working - so that's the main thing.

Thanks.

richard.

0 Kudos
vishalsaraswat
Contributor
Contributor

I went through your example code and the VI SDK guide and this is what I have written to extract the runtine state of all hosts. But i am getting errors while running:

Errors:

RetrieveServiceContent - OK

fullName: VMware vCenter Server 4.0.0 build-208111

Login Successful: Administrator

SOAP 1.1 fault: "":ServerFaultCode

"A specified parameter was not correct.

"

Detail:

Code :

ns1__TraversalSpec crTraversalSpec;

crTraversalSpec.name = new string("CRTraversalSpec");

crTraversalSpec.type = "ComputeResource";

crTraversalSpec.path = "host";

crTraversalSpec.skip = &xsd_true;

ns1__SelectionSpec CRSelectionSpec;

CRSelectionSpec.name = new string("folderSpec");

crTraversalSpec.selectSet.push_back(&CRSelectionSpec);

ns1__TraversalSpec clusterTraversalSpec;

clusterTraversalSpec.name = new string("ClusterTraversalSpec");

crTraversalSpec.type = "ClusterComputeResource";

crTraversalSpec.path = "host";

crTraversalSpec.skip = &xsd_true;

ns1__SelectionSpec ClusterSelectionSpec;

ClusterSelectionSpec.name = new string("folderSpec");

clusterTraversalSpec.selectSet.push_back(&ClusterSelectionSpec);

ns1__TraversalSpec dataCenterTraversalSpec;

dataCenterTraversalSpec.name = new string("DataCenterTraversalSpec");

dataCenterTraversalSpec.type = "Datacenter";

dataCenterTraversalSpec.path = "hostFolder";

dataCenterTraversalSpec.skip = &xsd_true;

ns1__SelectionSpec dataCenterTraversalSelectionSpec;

dataCenterTraversalSelectionSpec.name = new string("folderSpec");

dataCenterTraversalSpec.selectSet.push_back(&dataCenterTraversalSelectionSpec);

ns1__TraversalSpec folderTraversalSpec;

folderTraversalSpec.name = new string("folderTraversalSpec");

folderTraversalSpec.type = "Folder";

folderTraversalSpec.path = "childEntity";

folderTraversalSpec.skip = &xsd_true;

ns1__SelectionSpec folderSelectionSpec1;

folderSelectionSpec1.name = new string("dataCenterTraversalSpec");

ns1__SelectionSpec folderSelectionSpec2;

folderSelectionSpec2.name = new string("crTraversalSpec");

ns1__SelectionSpec folderSelectionSpec3;

folderSelectionSpec3.name = new string("clusterTraversalSpec");

folderTraversalSpec.selectSet.push_back(&folderSelectionSpec1);

folderTraversalSpec.selectSet.push_back(&folderSelectionSpec2);

folderTraversalSpec.selectSet.push_back(&folderSelectionSpec3);

ns1__PropertySpec propertySpec;

propertySpec.type = "HostSystem";

propertySpec.pathSet.push_back("runtime.connectionState");

ns1__ObjectSpec objectSpec;

objectSpec.obj = ServiceContent->rootFolder;

objectSpec.skip = &xsd_true;

ns1__SelectionSpec objectSelectionSpec;

objectSelectionSpec.name = new string("folderSpec");

objectSpec.selectSet.push_back(&objectSelectionSpec);

objectSpec.selectSet.push_back(&dataCenterTraversalSpec);

ns1__PropertyFilterSpec propertyFilterSpec;

propertyFilterSpec.propSet.push_back(&propertySpec);

propertyFilterSpec.objectSet.push_back(&objectSpec);

ns1__DynamicProperty* dynamicProperty;

ns1__RetrievePropertiesRequestType retrievePropertiesReq;

ns1_RetrievePropertiesResponse retrievePropertiesRes;

retrievePropertiesReq._USCOREthis = ServiceContent->propertyCollector;

retrievePropertiesReq.specSet.push_back(&propertyFilterSpec);

if (vim.__ns1__RetrieveProperties(&retrievePropertiesReq, &retrievePropertiesRes) == SOAP_OK){

0 Kudos
stumpr
Virtuoso
Virtuoso

You'll need to clean up your folderTraversalSpec. You need to be able to go into Folders, DataCenters, and ComputeResources. I don't think you'll need ClusterComputeResource now I think about it. You should be able to drop that TraversalSpec and still get your HostSystems.

ns1__TraversalSpec folderTraversalSpec;
folderTraversalSpec.name = new string("folderTraversalSpec");
folderTraversalSpec.type = "Folder";
folderTraversalSpec.path = "childEntity";
folderTraversalSpec.skip = &xsd_true;

folderTraversalSpec.selectSet.push_back(&folderSelectionSpec);
folderTraversalSpec.selectSet.push_back(&dataCenterTraversalSpec);
folderTraversalSpec.selectSet.push_back(&crSelectionSpec);

You'll need to add folderTraversalSpec, dataCenterTraversalSpec, and crTraversalSpec to your ObjectSpec.

ns1__ObjectSpec objectSpec;
objectSpec.obj = ServiceContent->rootFolder;
objectSpec.skip = &xsd_true;
objectSpec.selectSet.push_back(&folderTraversalSpec);
objectSpec.selectSet.push_back(&dataCenterTraversalSpec);
objectSpec.selectSet.push_back(&crSelectionSpec);

And in your PropertySpec:

ns1__PropertySpec propertySpec;
propertySpec.type = "HostSystem";
propertySpec.all = &xsd_false;
propertySpec.pathSet.push_back("runtime.connectionState");

TraversalSpecs are the hardest to deal with, follow up on the links Njain posted earlier to get some samples of the trees.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
vishalsaraswat
Contributor
Contributor

Hi,

Correct me if I am wrong about it...

a) So, I somehow have not been able to get Njain's posts about trees.

b) The selectionSpec has to be provided to the current MOR about the next MOR to be traversed. For example -

- rootFolder should have Datacenter's and DataCenter should have hostFolders and so on.

c) ObjectSpec should have the reference of all the TravesalSpecs.

This is the current updated code. I am still not getting the values but no SOAP_FAULT at least.

Code:

bool xsd_true = 1;

bool xsd_false = 1;

Host* host = new Host();

ns1__TraversalSpec folderTraversalSpec;

folderTraversalSpec.name = new string("folderTraversalSpec");

folderTraversalSpec.type = "Folder";

folderTraversalSpec.path = "childEntity";

folderTraversalSpec.skip = &xsd_true;

ns1__SelectionSpec folderSelectionSpec;

folderSelectionSpec.name = new string("folderTraversalSpec");

//dataCenterTraversalSpec.selectSet.push_back(&CRSelectionSpec);

ns1__TraversalSpec dataCenterTraversalSpec;

dataCenterTraversalSpec.name = new string("datacenterTraversalSpec");

dataCenterTraversalSpec.type = "Datacenter";

dataCenterTraversalSpec.path = "hostFolder";

dataCenterTraversalSpec.skip = &xsd_true;

ns1__SelectionSpec dataCenterTraversalSelectionSpec;

dataCenterTraversalSelectionSpec.name = new string("datacenterTraversalSpec");

ns1__TraversalSpec crTraversalSpec;

crTraversalSpec.name = new string("CRTraversalSpec");

crTraversalSpec.type = "ComputeResource";

crTraversalSpec.path = "host";

crTraversalSpec.skip = &xsd_true;

ns1__SelectionSpec CRSelectionSpec;

CRSelectionSpec.name = new string("CRTraversalSpec");

crTraversalSpec.selectSet.push_back(&dataCenterTraversalSelectionSpec);

folderTraversalSpec.selectSet.push_back(&folderSelectionSpec);

folderTraversalSpec.selectSet.push_back(&dataCenterTraversalSelectionSpec);

dataCenterTraversalSpec.selectSet.push_back(&dataCenterTraversalSelectionSpec);

dataCenterTraversalSpec.selectSet.push_back(&folderSelectionSpec);

ns1__PropertySpec propertySpec;

propertySpec.type = "HostSystem";

propertySpec.pathSet.push_back("runtime.connectionState");

propertySpec.all = &xsd_false;

ns1__ObjectSpec objectSpec;

objectSpec.obj = ServiceContent->rootFolder;

objectSpec.skip = &xsd_true;

//objectSpec.selectSet.push_back(&objectSelectionSpec);

objectSpec.selectSet.push_back(&folderTraversalSpec);

objectSpec.selectSet.push_back(&dataCenterTraversalSpec);

objectSpec.selectSet.push_back(&crTraversalSpec);

ns1__PropertyFilterSpec propertyFilterSpec;

propertyFilterSpec.propSet.push_back(&propertySpec);

propertyFilterSpec.objectSet.push_back(&objectSpec);

ns1__DynamicProperty* dynamicProperty;

ns1__RetrievePropertiesRequestType retrievePropertiesReq;

ns1_RetrievePropertiesResponse retrievePropertiesRes;

retrievePropertiesReq._USCOREthis = ServiceContent->propertyCollector;

retrievePropertiesReq.specSet.push_back(&propertyFilterSpec);

if (vim.__ns1__RetrieveProperties(&retrievePropertiesReq, &retrievePropertiesRes) == SOAP_OK){

cout << "Number of Objects " << retrievePropertiesRes.returnval.size() << endl;

The number of objects I am getting is 0.

Any suggestions?

0 Kudos
stumpr
Virtuoso
Virtuoso

Njain's post is the link to the SDK Programming Guide.

That's about right, but its more about the path down the inventory than MO_Refs.

To go from rootFolder to Datacenters, you go to childEntity. From the Datacenter, you need hostFolder. From hostFolder, you need to go to childEntity again. This is then your ComputeResource objects. From there you need to go to 'host' to get your host systems.

In your example I think you missed adding your ComputeResourceToHost SelectionSpec to your FolderTraversalSpec.

                FolderTraversalSelectionSpec.name = new string("FolderTraversalSpec");
		DataCenterHostFolderTraversalSelectionSpec.name = new string("DataCenterHostFolderTraversalSpec");
		ComputeResourceHostTraversalSelectionSpec.name = new string("ComputeResourceHostTraversalSpec");
		
		DataCenterHostFolderTraversalSpec.name = new string("DataCenterHostFolderTraversalSpec");
		DataCenterHostFolderTraversalSpec.type = "Datacenter";
		DataCenterHostFolderTraversalSpec.path = "hostFolder";
		DataCenterHostFolderTraversalSpec.skip = &xsd_false;
		
		ComputeResourceHostTraversalSpec.name = new string("ComputeResourceHostTraversalSpec");
		ComputeResourceHostTraversalSpec.type = "ComputeResource";
		ComputeResourceHostTraversalSpec.path = "host";
		ComputeResourceHostTraversalSpec.skip = &xsd_false;
		
		FolderTraversalSpec.name = new string("FolderTraversalSpec");
		FolderTraversalSpec.type = "Folder";
		FolderTraversalSpec.path = "childEntity";
		FolderTraversalSpec.skip = &xsd_false;
		
		FolderTraversalSpec.selectSet.push_back(&FolderTraversalSelectionSpec);
		FolderTraversalSpec.selectSet.push_back(&ComputeResourceHostTraversalSelectionSpec);
		FolderTraversalSpec.selectSet.push_back(&DataCenterHostFolderTraversalSelectionSpec);
		
		DataCenterHostFolderTraversalSpec.selectSet.push_back(&FolderTraversalSelectionSpec);

		PropertySpec.type = "HostSystem";
		PropertySpec.all = &xsd_false;
		PropertySpec.pathSet.push_back("name");
		
		ObjectSpec.obj = ServiceContent->rootFolder;
		ObjectSpec.skip = &xsd_false;
		ObjectSpec.selectSet.push_back(&FolderTraversalSpec);
		ObjectSpec.selectSet.push_back(&ComputeResourceHostTraversalSpec);
		ObjectSpec.selectSet.push_back(&DataCenterHostFolderTraversalSpec);
		
		PropertyFilterSpec.propSet.push_back(&PropertySpec);
		PropertyFilterSpec.objectSet.push_back(&ObjectSpec);
		
		RetrievePropertiesReq._USCOREthis = ServiceContent->propertyCollector;
		RetrievePropertiesReq.specSet.push_back(&PropertyFilterSpec);

I attached a working cpp file you can reference.

Example run:

$ ./test6 https://172.16.179.25/sdk administrator **********
RetrieveServiceContent - OK
fullName: VMware vCenter Server 4.0.0 build-208111
  name: VMware vCenter Server
  build: 208111
  version: 4.0.0
  apiType: VirtualCenter
  productLineId: vpx
Login Successful: Administrator
Login Time: Thu Apr 29 14:35:09 2010

Number of Objects 2
Number of Properties for object 0 = 1
  name = vlab-esx-02.vlab.local
Number of Properties for object 1 = 1
  name = vlab-esx-01.vlab.local

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos
vishalsaraswat
Contributor
Contributor

Hey,

Thanks a lot. It worked and helped alot for me to understand the traversal.

-Vishal

0 Kudos
vishalsaraswat
Contributor
Contributor

I have a couple of doubts. If I want to extract the PhysicalNic info of a HostSystem, then -

a) I would have to extract the HostNetworkSystem MOR from ComputeResource

b) Go to pnic under networkInfo.

c) But for some reason it says that it will be NULL if you are on ESX system.

I am trying to extract the this MOR and I get object when I am running it on ESX. Is this the same reason why I am not getting anything?

and top of all, why don't we get the pnic info for and ESX server?

-Vishal

0 Kudos
stumpr
Virtuoso
Virtuoso

You shouldn't need to call RetrieveProperties on another MoRef to get the PhysicalNic properties. However, there will be times you have to make another RetrieveProperties call for some other object off the main inventory.

Where are you getting the impression the PhysicalNic would be unset on ESX?

./test6 https://172.16.50.25/sdk administrator VMware1
RetrieveServiceContent - OK
fullName: VMware vCenter Server 4.0.0 build-208111
  name: VMware vCenter Server
  build: 208111
  version: 4.0.0
  apiType: VirtualCenter
  productLineId: vpx
Login Successful: Administrator
Login Time: Wed May  5 22:57:28 2010

Number of Objects 2
Number of Properties for object 0 = 2
   vmnic0: 00:0c:29:bb:80:6f
   vmnic1: 00:0c:29:bb:80:79
  name = vlab-esx-01.vlab.local
Number of Properties for object 1 = 2
   vmnic0: 00:0c:29:94:68:13
   vmnic1: 00:0c:29:94:68:1d
  name = vlab-esx-02.vlab.local

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