Kjellski
Contributor
Contributor

HowTo: Beginners Advice for using the vSphere APIs in C#

To be done: write about general structure and behavior of the API, e.g.: Folders(not "real" Folders, two points of view - ressource and organization)

Hi there,

in this thread I'll just let you know how I struggeled the API for the last two months and, hopefully, make sure you don't have to too. I've been able to accomplish at least the most of what I wanted but it took me days to find solutions to specific problems. While I had to struggle with incomplete documentation or missing answers to years old questions, I hope you can follow the path of "debugging" I tend to walk along nowadays. I used C# and the vSphere PowerCLI Toolkits VMware.Vim.dll, which enables you to use nice high level features as well as get specific things done.

First off, how to get started?

I chose the, in my opinion, simplest way to program against the API with the vSpherePowerCLI Toolkit. Once again, VMware, please provide more information about how to choose the API. And also mention that everything is nicely possible with this little VMware.Vim.dll with nice Wrapper types for all objects.

Good Part: You don't have to build anything, and you just start right ahead with VisualStudio 2010 and a single reference.

Just download the PowerCLI packagehttp://www.vmware.com/support/developer/PowerCLI/index.html and install it. Then just set the reference in your project to the VMware.Vim.dll in your freshly installed folder ( for me, that was: C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.Vim.dll) on Windows 7. And then you can start coding with "using VMware.Vim;" and there you go!

VimClient vmc = new VimClient();

vmc.Login(<credentials go here>);

Notes: You will always want to keep an instance of the VimClient arround in order to be able to operate on the ManagedObject on the vSphere Server.

CAUTION: Sometimes, it seems to be broken when you instantiate an object with the typical:

// Seems to use the constructor of the class itself and instantiates itself with

// the VimClient to get its data from vCenter...

T t = new T(<vimclient>, <managed object reference>);

If so, try using the:

// instead of null you could also provide properties, which I never needed.

T t = (T) vimclient.GetView(<managed object reference>, null);

You will run into errors. Then it's time to debug!

Lets DEBUG!

I suggest you to do a step by step debug to ensure the source of the error is not misleading your thoughts. First off, go to the website of the ManagedObjectBrowser(MOB), which can be found by browsing to:

https://w.x.y.z/mob where w.x.y.z is the IP of your vSphere Server.

Then, click on ServiceContent and in the appearing window click Invoke! Now you can look at the vSphere Server from the API perspective. Browse to the Folder or whatever you struggle with. Then take a look at the ManagedObjectReference in order to double check that while you Debug, you see

the same ManagedObjectReference in your code. If you are not sure on how to retrieve this, I am always taking the "secure" way over the ViewBase:

// now place the type of object you want to see as T in the line beneath:

T t = (T) vmc.GetView(new ManagedObjectReference(<String from MOB seen reference>, null));

While debugging, set a breakpoint to the line above. Then you'll be able to how this worked out.

Also you'll get a feeling on how to use the API when you browse the vSphere Inventory in the MOB.

A word on ManagedObjects

If you try to find something you want to gather informations from or you want to modfiy an object, I suggest you follow more than one path.

My approach here is to use three different methods to find things. I have a sort of string concatenation class that does some path concatenation for finding objects by inventory paths. This is extremely useful because you don't rely on Managed Object references that you might not even know.

Here is how you can get going:

https:/1.1.1.1/mob/?moid=SearchIndex

And then you have the following options to reach for objects:

ManagedObjectReference:ManagedEntity[]    FindAllByDnsName
ManagedObjectReference:ManagedEntity[]    FindAllByIp
ManagedObjectReference:ManagedEntity[]    FindAllByUuid
ManagedObjectReference:VirtualMachine    FindByDatastorePath
ManagedObjectReference:ManagedEntity    FindByDnsName
ManagedObjectReference:ManagedEntity    FindByInventoryPath
ManagedObjectReference:ManagedEntity    FindByIp
ManagedObjectReference:ManagedEntity    FindByUuid
ManagedObjectReference:ManagedEntity    FindChild

It's super useful to check wether you have all paths in the right place and also to look up some of the entities that you don't want

to click through the whole inventory structure.

One example path you could throw in "FindByInventoryPath" for testing purposes:

/<Name of Datacenter>/host/<Name of ClusterComputeResource>/Resources

This will directly lead you to your Clusters resources MOR from a programs viewpoint.

Now the Programatical part; I've just build up a method for this:


/// <summary>
/// Returns a ManagedObjectReference from an inventory path
/// </summary>
/// <param name="vmc">The client to be used</param>
/// <param name="path">Path of the Entity to be found</param>
/// <returns>the MoRef found by path</returns>
public static ManagedObjectReference findManagedObjectReferenceByPath(VimClient vmc, String path)
{
    // Inventory Searching Instance of SearchIndex
    SearchIndex searcher = (SearchIndex)vmc.GetView(vmc.ServiceContent.SearchIndex, null); // new SearchIndex(vmc, vmc.ServiceContent.SearchIndex);
    ManagedObjectReference result;
    try
    {
        result = searcher.FindByInventoryPath(path);
    }
    catch (Exception e)
    {
        throw new MyNamespace.Exceptions.PathNotFoundException("While trying findManagedObjectReferenceByPath( " + path + "), an InnerException occured.", e);
    }
 
    if (result != null)
    {
        return result;
    }
    else
    {
        throw new MyNamespace.Exceptions.PathNotFoundException("Couldn't find anything by the path: " + path);
    }
}

And btw. with this apprach, you can look at the GUI of vCenter ti guess the right paths...

Useful Documentation

What I made sticky on my browser while developing the application are the following pages:

I know I know, this is not complete, but please provide feedback with your first struggles in order to complete this thing.

Nevertheless, I hope this helps, at least a bit!

Greetings,

Kjellski

P.S.: I hope somebode will make this thread sticky and or suggest feedback for making it richer.

12 Replies
Kjellski
Contributor
Contributor

Just a bummer, I would love to get more information in here but I won't add anything if nobody is interested in it.

0 Kudos
ToolsDev
Contributor
Contributor

Hi,

Just to let you know, I used your guide to get me started on using the VIM dll for writing .Net code.

I've since written a bunch of helper classes in a wrapper DLL which I now use to create internal tools to interface with vCenter.

Thanks for your efforts, I appreciate them.

0 Kudos
Kjellski
Contributor
Contributor

Hell yeah!

Thanks for the reply... actually this thread already had some views but nobody seemed to

take action and reply...

This means a lot to me, do you have any feedback? Grey areas in the parts or information that

I might add in the original post?

Thanks a lot!

Greetings,

Kjellski

0 Kudos
nikhilxp64
Enthusiast
Enthusiast

Hi,

I am trying to follow your guide to using the vim.dll provided with powerCLI, since most of the people on the forums seems to like it more that the web services SDK I am using now.

I think the Login part worked fine but I could not instantiate a VirtualMachine Object. I am unsure of what to fill in the string parameter for:

T t = (T) vmc.GetView(new ManagedObjectReference(<String from MOB seen reference>, null));

Also the link to the reference is that for the Vim.dll API? Because I couldn't find the VimClient.Login or VimClient.GetView methods in there. I think it's for the old version of the web services SDK only.

From what I can make out, the Vim.dll utilizes the web serives SDK to provide it's functionality, but at the same time wraps it in a more friendly interface?

Would definitely like to see more guides like this. More depth would also be appreciated.

Thanks! Smiley Happy

0 Kudos
Kjellski
Contributor
Contributor

Hi there,

nice to see anotherone that was able to get started with this guide.

But for now, lets jump in:

// The problem with your statement could be a two part story.

// I would be very cautious about for what you ask. You can actually

// use the ManagedObjectReference and that is absolutely fine. But

// you'll probably get to the point where you don't have it in the

// first place. I'll update my original post with some infos for finding

// Object over MORs and other useful tools...

// But for now I'll just show you how it works for me. For example:

// Be careful here, it's not enough to put just the Id part in here,

// you have to specify the type up front:

String virutalMachineId = "VirtualMachine-vm-266";

ManagedObjectReference tmp = new ManagedObjectReference(virtualMachineId);
// Another way is this, which I personally prefer...
ManagedObjectReference tmp2 = new ManagedObjectReference { Type = "VirtualMachine", Value = "vm-266" };
VirtualMachine vm = null;
try
{
    // vmc is my instance of VimClient
    vm = (VirtualMachine)vmc.GetView(tmp, null); } catch (VimException e) {     throw new MyNamespace.Exceptions.VirtualMachineNotFoundException("Couldn't find the VirtualMachine by id: " + virtualMachineId, e); }

To the more general part:

As far a I know, there is no exact documentation for the API provided by this dll. I would love to see this in the future. But until we get something like that, the MOB is your friend and it can always show you the Properties you want to use and the "paths" you can take to get to a target.

Hope this helps, keep asking please 😃

Greetings,

Kjellski

0 Kudos
nikhilxp64
Enthusiast
Enthusiast

So what I still dont get is where in the MOB you pick up the value field for the MOR.

Attached is a snapshot of what my VM folder looks like in the MOB. I just put in "1" in the value field of the VM MOR and it seems to accept it. So is it always the integet value that shows up in that MOB page? Or is it something else?

Also where did you get the Virtual Machine ID from?

ThanksCapture1.PNG.

0 Kudos
nikhilxp64
Enthusiast
Enthusiast

So I even though I don't understand if the "1" I entered as the MOR value is right - it still points to the correct VM. And I managed to retrieve some of its runtime properties. So Im happy. Smiley Happy

Now if I was to try and retrieve a list of all the VMs on a particular host using the Vim DLL, how do should I be going about it? The was I would do this with the web-services was with the RetrieveProperties method.

0 Kudos
lamw
Community Manager
Community Manager

The MoRef ID is generated by vCenter or ESX(i) host, depending on what you're connected to.

In the screenshot, you only have a single VM and the MoRef ID is 1 as you mentioned. If you create another VM, you'll see another MoRef ID and if you delete/re-create the same VM, you will see the MoRef ID changes.

The MoRef ID can be retrieve for any of the managed entities (e.g. Datacenter, Cluster, VirtualMachine, etc)

Here are few articles that could be helpful, there is a vSphere SDK for Perl script that shows you how to extract the MoRef ID for various managed entities, you can easily translate that into C# example:

http://www.virtuallyghetto.com/2011/11/vsphere-moref-managed-object-reference.html

http://www.virtuallyghetto.com/2011/11/when-do-vsphere-morefs-change.html

http://blogs.vmware.com/vsphere/2012/02/uniquely-identifying-virtual-machines-in-vsphere-and-vcloud-...

0 Kudos
nikhilxp64
Enthusiast
Enthusiast

Thanks, those were very useful links.

0 Kudos
Kjellski
Contributor
Contributor

Yeah the big lamw in here, I'm sorta kinda proud now 😃

Would you mind if I take these Links into the original post to provide these at the right point?

Also, is there a handy enumerable in the VimClient namespaces that could be used to always

use the right String as the type property in the ManagedObjectReference?

Thanks for sharing and keep up the good work!

Greetings,

Kjellski

0 Kudos
lamw
Community Manager
Community Manager

Yes, feel free to include any of links that are helpful. I am also working on an Intro API series here http://blogs.vmware.com/vsphere/2012/02/introduction-to-the-vsphere-api-part-1.html, be sure to follow that for some useful information.

I'm not familiar with the C# SDK, but there should be a type/val as explained by Steve Jin here - http://www.doublecloud.org/2011/06/managedobjectreference-vs-managedobject/ that allows you to identify the MoRef Type.

Thanks

0 Kudos
grattojf
Contributor
Contributor

Thanks a *lot* !!

You've done the hard work I was kind afraid to start. I was planning on building a small app that browses throught our various vCenters to inventory our VMs in the broad lines (disk size, cpus, etc). Our current inventory is a gigantic mess; I wanted an app that can be run from anywhere without the need to log onto a typical client. You've made my day !

Just to show how abysmal VMWare's documentation and search facilities are, I got your link onto the vmware.com domain from .. StackOverflow (c# - Which VMware API should I use? - Stack Overflow) .

Such a big company, with so much resources, you'd think they'd do a better job at documenting and maintaining web sites... oh well.

Thanks again, I feel on surer footing now, thanks to your tremendous efforts.

0 Kudos