This post is going to be about using simple object collectors to get a list of virtual machines on a given host. Now, there are a couple of ways to do this, namely using traversal objects, but for this post, we are going to keep it simple. We will get to the TraversalSpec object in some later posts, so we will revamp this code at that time. For now, I am going to focus on creating simple collector objects so we can us them as building blocks.

Disclaimer: I know there are some flaws in the code below, mainly traversing multiple folders, etc. Please remember this is base code to help get an understanding of the VMWare SDK and its methods not a comprehensive programming example :)

So the first thing to understand about the ESX infrastructure is the hierarchy. Lets check out the picture below.

image

As you can see, the ESX Server structure is as follows

rootFolder (Everything is a child of this object)

------ Datacenter

------------ Folder

--------------------- VirtualMachine

Given the following structure and the previous comment about making “simple” collectors, we will create three methods each returning a ManagedReferenceObject (this is a VMWare object that you can learn about more in the SDK).

The first method will return the Datacenter object, by passing into the method the main rootFolder.

The second method will return a vmFolder by passing into the method a Datacenter object.

The third method will return a array of virtual machines by passing into the method a vmFolder object.

We also have a helper method that will return some specific properties given a virtual machine object.

So, with that lets get started.

Here is the first method. This method returned the root datacenter object.

public ManagedObjectReference GetVMRootDataCenter( ManagedObjectReference RootFolder )
{
	ManagedObjectReference _returnObject = null;

	PropertySpec[] _ps = new PropertySpec[] { new PropertySpec() };
	_ps[0].type = "Folder";
	_ps[0].pathSet = new string[] { "childEntity" };

	ObjectSpec[] _os = new ObjectSpec[] { new ObjectSpec() };
	_os[0].obj = RootFolder;
	_os[0].skip = false;

	PropertyFilterSpec[] _pfs = new PropertyFilterSpec[] { new PropertyFilterSpec() };
	_pfs[0].propSet = _ps;
	_pfs[0].objectSet = _os;

	ObjectContent[] _rootFoldersObjectContent = this._vmService.RetrieveProperties(this._vmServiceContent.propertyCollector, _pfs);

	foreach (ObjectContent _rootFolder in _rootFoldersObjectContent)
	{
		Array _objectsReturned = (Array)_rootFolder.propSet[0].val;

		_returnObject = (ManagedObjectReference)_objectsReturned.GetValue(0);
	}
	return _returnObject;
}

Here is the second method. This method returns a vmFolder given a Datacenter object.

public ManagedObjectReference GetVMFolder( ManagedObjectReference ParentObject )
{
	ManagedObjectReference _returnedObject = null;

	PropertySpec[] _dataCenterPropertySpec = new PropertySpec[] { new PropertySpec() };
	_dataCenterPropertySpec[0].type = "Datacenter";
	_dataCenterPropertySpec[0].pathSet = new string[] { "vmFolder" }; //Return the vmFolder objects

	ObjectSpec[] _dataCenterObjectSpec = new ObjectSpec[] { new ObjectSpec() };

	_dataCenterObjectSpec[0].obj = ParentObject;
	_dataCenterObjectSpec[0].skip = false;

	PropertyFilterSpec[] _dataCenterToFolderPFS = new PropertyFilterSpec[] { new PropertyFilterSpec() };
	_dataCenterToFolderPFS[0].propSet = _dataCenterPropertySpec;
	_dataCenterToFolderPFS[0].objectSet = _dataCenterObjectSpec;

	ObjectContent[] _vmFoldersObjectContent = this._vmService.RetrieveProperties(this._vmServiceContent.propertyCollector, _dataCenterToFolderPFS);

	foreach (ObjectContent _vmFolder in _vmFoldersObjectContent)
	{
		_returnedObject = (ManagedObjectReference)_vmFolder.propSet[0].val;
	}

	return _returnedObject;
}

Here is the third method. This method returns a array of virtual machines given a vmFolder object.

public ManagedObjectReference[] GetVMChildEntities(ManagedObjectReference ParentFolder)
{
	ManagedObjectReference[] _a = null ;

	PropertySpec[] _dataCenterPropertySpec = new PropertySpec[] { new PropertySpec() };
	_dataCenterPropertySpec[0].type = "Folder";
	_dataCenterPropertySpec[0].pathSet = new string[] { "childEntity","name" }; //Return the vmFolder objects

	ObjectSpec[] _dataCenterObjectSpec = new ObjectSpec[] { new ObjectSpec() };

	_dataCenterObjectSpec[0].obj = ParentFolder;
	_dataCenterObjectSpec[0].skip = false;

	PropertyFilterSpec[] _dataCenterToFolderPFS = new PropertyFilterSpec[] { new PropertyFilterSpec() };
	_dataCenterToFolderPFS[0].propSet = _dataCenterPropertySpec;
	_dataCenterToFolderPFS[0].objectSet = _dataCenterObjectSpec;

	ObjectContent[] _vmFoldersObjectContent = this._vmService.RetrieveProperties(this._vmServiceContent.propertyCollector, _dataCenterToFolderPFS);

	foreach (ObjectContent _vmFolder in _vmFoldersObjectContent)
	{
		Array _childEntities = (Array)_vmFolder.propSet[0].val;
		_a = new ManagedObjectReference[_childEntities.Length];

		for (int i = 0; i < _childEntities.Length; i++)
		{
			_a[i] = (ManagedObjectReference)_childEntities.GetValue(i);
		}
	}

	return _a;
}

So, from those method we will be able to traverse the folder structure and return a list of virtual machines configured on a given ESX Server.

The last method we need is a help method, that will return some properties on a given virtual machine. That is list below.

public System.Collections.Hashtable GetVMWareVirtualMachineProperties( ManagedObjectReference ObjectToRetrieve )
{
	PropertySpec[] _childEntitySpecs = new PropertySpec[] { new PropertySpec() };
	_childEntitySpecs[0].type = "VirtualMachine";
	_childEntitySpecs[0].pathSet = new string[] { "name","runtime.powerState" };


	ObjectSpec[] _childEntityObjects = new ObjectSpec[] { new ObjectSpec() };
	_childEntityObjects[0].obj = ObjectToRetrieve;
	_childEntityObjects[0].skip = false;

	PropertyFilterSpec[] _pfs = new PropertyFilterSpec[] { new PropertyFilterSpec() };
	_pfs[0].objectSet = _childEntityObjects;
	_pfs[0].propSet = _childEntitySpecs;

	ObjectContent[] _childEntityProps = this._vmService.RetrieveProperties(this._vmServiceContent.propertyCollector, _pfs);

	System.Collections.Hashtable _allProps = new System.Collections.Hashtable();
	foreach (DynamicProperty _prop in _childEntityProps[0].propSet)
	{
		_allProps.Add(_prop.name, _prop.val);
	}

	return _allProps;
}

So now we have all the required methods for traversing the folder structure. Lets put it together by logging into the ESX server and calling the methods we have defined about

Before going on, lets add the following as global vars in our project.

        private VimService _vmService = null;
        private ServiceContent _vmServiceContent = null;
        UserSession _vmLoginSession = null;

And here is the login code. You can also view the article on logging into the web service by clicking here.

this._vmService = new VimService();
_vmService.Url = @"https:///sdk";
_vmService.CookieContainer = new System.Net.CookieContainer();

System.Net.ServicePointManager.CertificatePolicy = new TrustAllCerts();

ManagedObjectReference _object = new ManagedObjectReference();
_object.type = "ServiceInstance";
_object.Value = "ServiceInstance";

this._vmServiceContent = this._vmService.RetrieveServiceContent(_object);

this._vmLoginSession = _vmService.Login(_vmServiceContent.sessionManager, "", "", null);</pre>

Once this is done, we can add the code to actually call our method and return the requested information

ManagedObjectReference _rootDataCenter = this.GetVMRootDataCenter(this._vmServiceContent.rootFolder);

ManagedObjectReference _vmFolder = this.GetVMFolder(_rootDataCenter);

foreach (ManagedObjectReference _vm in this.GetVMChildEntities(_vmFolder))
{
	System.Collections.Hashtable _props = this.GetVMWareVirtualMachineProperties(_vm);
	Console.WriteLine("{0}:{1},_props["name"].ToString(), _props["runtime.powerState"].ToString());
}

Ok, thats it, if you run the code you should see a list of your virtual machines along with the power status of each one of them.

Look for more howto’s soon. Hopes this help.