Hello everyone,
I'am very enthousiast to write this first blog post and share what I've learned about programing with VMware sdk in Java.
In this tutorial, I am going to talk about a project that i started few month ago but I didn't have time to finish so I am going to share with you some sample codes that you can use to retrieve datas from your VMware infrastructure.
I know that programming with the VMware Java SDK can be a real pain and especially when we deal with the propertyCollector and filters, and require lot of lines of code to retreive a simple object.
So decided to try the VI Java API which is a set of Java libraries that sits on top of the existing vSphere SDK Web Services interface. This API is also much faster and symplify your code a lot.
But before talking about this great API, let me first introduce the basis of the vSphere SDK.
1) Object Model and Property Collector
Imagine you want to retrieve the names of all hosts in the inventory, or maybe you want to monitor for changes to the power state of all VMs in the inventory, or you want to keep track of the host that each VM is running on, you have to use the property collector.
In order to retrieve properties, perform operations or modify entities within the vSphere API, it is important to understand the vSphere Object Model’s structure and relationships. The vSphere API consists of three types of objects:
- Managed Object: is a server side object like VMs or Hosts
- Managed Object Reference: is a client reference to a Managed Object
- Data Object: contains information about a Managed Object and can also be used to transfer data between a client and server
So PropertyCollector gives you the ability to retrieve properties of the ManagedObject and also monitor the changes of any properties you interested in.
In order to use the PropertyCollector to retrieve informations from Managed Object, you need to specify what data you want to retrieve and this is done with something called PropertyFilterSpec and this object has at least 2 properties:
PropertySpec : What property you want to retrieve, the name of a VM for exemple
ObjectSpec: It identifies the starting object in the inventory
TraversalSpec: (optional): Define how to traverse the inventory
And those objects have properties that take objects that you need to create and you can already see that it requires many lines of code before retrieving the name of a VM or whatever properties you want to get from your vCenter.
2) VI Java API Introduction
Virtual Infrastructure API is an open source project created by Steve Jin from VMware R&D. It aims to simplify the use of VI SDK and improve the performance.
This API encapsulate the PropertyCollector behind Java methods and provide a all bunch of ManagedObject that will allow you to manipulate vmware objects without any effort.
The picture below represent the object architecture that will be very helpful to code you program and you will see further in this article that I manipulate those objects to retrieve specific properties.
Let's go back to my own projet where my goal was to recreate a vSphere "VM advance settings" panel in order to do modification of multiple VM at the same times.
Think about it, your boss ask you to apply VM advanced settings such as "isolation.tools" for security reason to VMs of the whole infrastructure. You can certainly spend an hour on a PowerCLI script which is something I did before my project, or having a flexible GUI tool that conatins all the predifined settings and allow admins to modify settings of 1000 VMs in one shot.
What you need to start coding a VI Java API project:
-Your favorite IDE (for my project I used NetBeans IDE 7.3.1
- The VMware Java SDK which is a Jar file called vim25, you can download it here: http://www.vmware.com/support/developer/vc-sdk/index.html
- The Vi Java API, you can download it here: http://sourceforge.net/projects/vijava/files/
- You are good to go!
3) Start coding
Create a new project and add the correct Jar files to your project (the Jar from the VMware SDK and the Jar from the VI Java API).
Now I am going to explain line of code from my project that you can easily use an modify.
3.1) Connect to vCenter
public ServiceInstance Initialisation(String url, String username, String password) throws RemoteException, MalformedURLException{ ServiceInstance si = new ServiceInstance(new URL(url), username, password, true); return si; }
This is the methode I use to connect my vCenter Server. The initialisation method take 3 parameters which are:
- Url: this is the URL of the vCenter plateform and it look like this https://192.168.1.1/sdk
- Username: nothing special
- Password: nothing special
This method will return a ServiceInstance object which will be used to have access to your infrastructure root folder. If you're doing GUI app, don't call this method from the UI thread otherwise it will freeze your Java window.
3.2) Retrieve ManagedEntity from Inventory Navigator
public ManagedEntity[] RetreiveVM(ServiceInstance si) throws InvalidProperty, RuntimeFault, RemoteException{ Folder rootFolder = si.getRootFolder(); ManagedEntity[] mes = new InventoryNavigator(rootFolder).searchManagedEntities("VirtualMachine"); return mes; }
This method take the ServiceInstance object that we got in the previous section. Here we have to create a rootFolder object from our ServiceInstance object.
And next we can already retrieve ManagedObject (VirtualMachine in my exemple) with the searchManagedEntities method and fill the mes[] table with all the VMs of your infrastructure.
From the InventoryNavigator object, you can use:
-searchManagedEntities("VirtualMachine")
-searchManagedEntities("HostSystem")
-searchManagedEntities("Datacenter")
With these method, you can already retrieve VMs from your vCenter. The next will be to retrieve information of the VM and you will see that in the next section.
3.3) Convert ManagedEntity object and retrieve VM properties
First of all, you will have to convert the "mes" object into a "virtualMachine" object. Then you are free to exploit the hundreds of properties of the VM object.
public void setSelectedVM(int index) { VirtualMachine vm = (VirtualMachine) mes[index]; System.out.println("Guest OS:"+vm.getSummary().getConfig().guestFullName); System.out.println("VM Version:"+vm.getConfig().version); System.out.println("CPU:"+vm.getConfig().getHardware().numCPU+" vCPU"); System.out.println("Memory:"+vm.getConfig().getHardware().memoryMB+" MB"); System.out.println("Memory Overhead:"+(long)vm.getConfig().initialOverhead.initialMemoryReservation/1000000f+" MB"); System.out.println("VMware Tools:"+vm.getGuest().toolsRunningStatus); System.out.println("IP Addresses:"+vm.getSummary().getGuest().getIpAddress()); System.out.println("State:"+vm.getGuest().guestState); }
Here is almost all the information you can get in the General Section of the Sumary tab in the vSphere client. But you can actually retrieve every single attribute that are visible in the vSphere Client, and you can see the screenshot below showing the tones of object available:
And here is screenshot of a part of my app where you can recognize the option tab of a VM's setting.
3.4) Retrieve hardware properties
Let's dive into hardware properties. For each VMs, I want to be able to get the the hardware objects and retrieve properties from them. For each virtualMachine object, you can use this code to get the attached hardware:
for (VirtualDevice vd : vm.getConfig().getHardware().getDevice()) { try { if (vd instanceof VirtualMachineVideoCard) { VirtualMachineVideoCard vVideoCard = (VirtualMachineVideoCard) vd; } else if (vd instanceof VirtualMachineVMCIDevice) { VirtualMachineVMCIDevice vVMCI = (VirtualMachineVMCIDevice) vd; } else if (vd instanceof VirtualSCSIPassthrough) { VirtualSCSIPassthrough vSCSI = (VirtualSCSIPassthrough) vd; } else if (vd instanceof VirtualDisk) { VirtualDisk vDisk = (VirtualDisk) vd; VirtualDiskFlatVer2BackingInfo vbi = (VirtualDiskFlatVer2BackingInfo) vd.getBacking(); } else if (vd instanceof VirtualCdrom) { VirtualCdrom vCDrom = (VirtualCdrom) vd; if (vCDrom.getBacking() instanceof VirtualCdromRemoteAtapiBackingInfo) { } else if (vCDrom.getBacking() instanceof VirtualCdromAtapiBackingInfo) { VirtualCdromAtapiBackingInfo vabi = (VirtualCdromAtapiBackingInfo) vCDrom.getBacking(); } else if (vCDrom.getBacking() instanceof VirtualCdromIsoBackingInfo) { VirtualCdromIsoBackingInfo vibi = (VirtualCdromIsoBackingInfo) vCDrom.getBacking(); } else if (vCDrom.getBacking() instanceof VirtualCdromRemotePassthroughBackingInfo) { VirtualCdromRemotePassthroughBackingInfo vpbi = (VirtualCdromRemotePassthroughBackingInfo) vCDrom.getBacking(); } } else if (vd instanceof VirtualEthernetCard) { VirtualEthernetCard vEth = (VirtualEthernetCard) vd; } } catch (Exception e) { } }
With those lines of code, you can easily retrieve the following hardware devices: VideoCard, VMCIDevice, VirtualSCSIPassThrough, VirtualDisk, VirtualCdrom and VirtualEthernetCard.
There are still missing hardware that I didn't have time to integrate in my project but you have the most of it here.
So let's take for exemple the VirtualEthernetCard. In my app, I have a Java class for each hardware type and and I pass each hardware objects to the constructor of the corresponding hardware classes.
This is a sample code to see you VM's network card properties:
VirtualEthernetCard vEth = (VirtualEthernetCard) vd; if (vEth instanceof VirtualE1000) { System.out.println("Adapter type: E1000"); } else if (vEth instanceof VirtualE1000E) { System.out.println("Adapter type: E1000E"); } else if (vEth instanceof VirtualPCNet32) { System.out.println("Adapter type: PCnet32"); } else if (vEth instanceof VirtualVmxnet) { System.out.println("Adapter type: Vmxnet"); } else if (vEth instanceof VirtualVmxnet2) { System.out.println(Adapter type: "Vmxnet2"); } else if (vEth instanceof VirtualVmxnet3) { System.out.println("Adapter type: Vmxnet3"); } System.out.println("connected"+vEth.getConnectable().connected); System.out.println("Connect at power on"+vEth.getConnectable().startConnected); System.out.println("Manual"+vEth.addressType); System.out.println("MAC address:"+vEth.macAddress);