Task Monitoring Example
Using the ListView Object
Use the ViewManager’s
ListView
method to specify the set
of tasks that you want to monitor.
The following example uses the
ViewManager
service interface with a
ListView
method to access and
manipulate
Task
objects. This example
uses the property collector to monitor tasks that are created in the process of
virtual machine cloning. This program creates two clones of the specified
virtual machine and then monitors the tasks and prints out status and reference
values when the tasks have completed.
The following steps describe the procedure for
creating a program that uses the ListView managed object.
You can run the example below as a stand-alone
program against your own server by copying the code sections into a .java file,
compiling it, and then using the following command line syntax:
>cloneVMTask server-name username password
vm-name
- Import the vSphere Web Services API libraries:import com.vmware.vim25.*;
- Import the necessary Java (and JAX-WS connection, bindings, and SOAP) libraries:import java.util.*; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.xml.ws.BindingProvider; import javax.xml.ws.soap.SOAPFaultException;
- Create the cloneVMTask class to create cloned virtual machine Tasks on a host, so we can demonstrate how to monitor these Tasks.public class cloneVMTask {
- Declare variables for the service instance objects and methods:// Services and methods static ManagedObjectReference pCollector; static ManagedObjectReference viewMgr; static ServiceContent serviceContent; static VimPortType methods; /** * getVmRef() retrieves a reference to the specified virtual machine. * * vmName - name of the virtual machine specified on the command line * * This function retrieves references to all of the virtual machines * in the datacenter and looks for a match to the specified name. */
- Create a function that retrieves references to all of the virtual machines in the datacenter and looks for a match to the specified name. The function in this example usesgetVMRef(String, vmName), which retrieves a reference to the virtual machine that you specify on the command line (vmName) when you run this sample. The function also initializes the vmRef variable to null.private static ManagedObjectReference getVmRef( String vmName ) throws Exception { ManagedObjectReference vmRef = null;
- Use a container view to collect references to all virtual machines in the datacenter.List<String> vmList = new ArrayList<String>(); vmList.add("VirtualMachine"); ManagedObjectReference cViewRef = methods.createContainerView(viewMgr, serviceContent.getRootFolder(), vmList, true);
- Create anObjectSpecto define the beginning of the traversal. Use thesetObjmethod to specify that the container view is the root object for this traversal. Set thesetSkipmethod to true to indicate that you don't want to include the container in the results.ObjectSpec oSpec = new ObjectSpec(); oSpec.setObj(cViewRef); oSpec.setSkip(true);
- Create a traversal spec to select all objects in the view.TraversalSpec tSpec = new TraversalSpec(); tSpec.setName("traverseEntities"); tSpec.setPath("view"); tSpec.setSkip(false); tSpec.setType("ContainerView");
- Add the traversal spec to the object spec.oSpec.getSelectSet().add(tSpec);
- Specify the property for retrieval (virtual machine name).PropertySpec pSpec = new PropertySpec(); pSpec.setType("VirtualMachine"); pSpec.getPathSet().add("name");
- Create a PropertyFilterSpec and add the object and property specs to it.PropertyFilterSpec fSpec = new PropertyFilterSpec(); fSpec.getObjectSet().add(oSpec); fSpec.getPropSet().add(pSpec);
- Create a list for the filters and add the spec to it.List<PropertyFilterSpec> fSpecList = new ArrayList<PropertyFilterSpec>(); fSpecList.add(fSpec);
- Get the data from the server.RetrieveOptions ro = new RetrieveOptions(); RetrieveResult props = methods.retrievePropertiesEx(pCollector,fSpecList,ro);
- Go through the returned list and look for a match to the specifiedvmName.if (props != null) { for (ObjectContent oc : props.getObjects()) { String vmname = null; List<DynamicProperty> dps = oc.getPropSet(); if (dps != null) { for (DynamicProperty dp : dps) { vmname = (String) dp.getVal(); // If the name of this virtual machine matches // the specified name, save the managed object reference. if (vmname.equals(vmName)) { vmRef = oc.getObj(); break; } } if (vmRef != null) { break; } } } } if (vmRef == null) { System.out.println("Specified Virtual Machine not found."); throw new Exception(); } return vmRef; }
- Get the folder that contains the specified virtual machine (VirtualMachine.parent)private static ManagedObjectReference getVMParent(ManagedObjectReference vmRef) throws Exception {
- Create anObject Specto define the property collection. Use thesetObjmethod to specify that the vmRef is the root object for this traversal. Set thesetSkipmethod to true to indicate that you don't want to include the virtual machine in the results.// don't include the virtual machine in the results ObjectSpec oSpec = new ObjectSpec(); oSpec.setObj(vmRef); oSpec.setSkip(false);
- Specify the property for retrieval (virtual machine parent).PropertySpec pSpec = new PropertySpec(); pSpec.setType("VirtualMachine"); pSpec.getPathSet().add("parent");
- Create a PropertyFilterSpec and add the object and property specs to it.PropertyFilterSpec fSpec = new PropertyFilterSpec(); fSpec.getObjectSet().add(oSpec); fSpec.getPropSet().add(pSpec);
- Create a list for the filters and add the property filter spec to it.List<PropertyFilterSpec> fSpecList = new ArrayList<PropertyFilterSpec>(); fSpecList.add(fSpec);
- Get the data from the server.RetrieveOptions ro = new RetrieveOptions(); RetrieveResult props = methods.retrievePropertiesEx(pCollector,fSpecList,ro);
- Get the parent folder reference.ManagedObjectReference folderRef = null; if (props != null) { for (ObjectContent oc : props.getObjects()) { List<DynamicProperty> dps = oc.getPropSet(); if (dps != null) { for (DynamicProperty dp : dps) { folderRef = (ManagedObjectReference) dp.getVal(); } } } } if (folderRef == null) { System.out.println("Folder not found."); throw new Exception(); } return folderRef; }Now that we have the reference information for the virtual machine that you specified on the command line (vmRef) and a reference for the parent directory (folderRef), we are ready to create the clone virtual machines.
- To create clones, use thecloneVMmethod and pass in thevmRefthat we retrieved previously.private static void cloneVM(ManagedObjectReference vmRef) throws Exception {
- After you have created the clone managed object, create a clone specification. Use default values whenever possible.VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec(); VirtualMachineRelocateSpec vmrs = new VirtualMachineRelocateSpec(); cloneSpec.setLocation(vmrs); cloneSpec.setPowerOn(true); cloneSpec.setTemplate(false);
- Get the destination folder for the clone virtual machines (VirtualMachine.parent). The clones will be created in the same folder that contains the specified virtual machine (vmName).ManagedObjectReference folder = getVMParent( vmRef );
- Create two clone virtual machines.ManagedObjectReference cloneTask = methods.cloneVMTask( vmRef, folder, "clone__1", cloneSpec); ManagedObjectReference cloneTask2 = methods.cloneVMTask( vmRef, folder, "clone__2", cloneSpec);
- Create a list view for the clone tasks.List<ManagedObjectReference> taskList = new ArrayList<ManagedObjectReference>(); taskList.add(cloneTask); taskList.add(cloneTask2); ManagedObjectReference cloneTaskList = methods.createListView(viewMgr, taskList);Next we will set up a property filter for WaitForUpdatesEx. This includes creating an object spec, a traversal spec, a property spec, a filter spec, and finally a property filter. The next six steps will describe these procedures.
- Create an object spec to start the traversal.ObjectSpec oSpec = new ObjectSpec(); oSpec.setObj(cloneTaskList); oSpec.setSkip(true);
- Create a traversal spec to select the list of tasks in the view.TraversalSpec tSpec = new TraversalSpec(); tSpec.setName("traverseTasks"); tSpec.setPath("view"); tSpec.setSkip(false); tSpec.setType("ListView");
- Add the traversal spec to the object spec.oSpec.getSelectSet().add(tSpec);
- Create property spec for Task.info.state and Task.info.result.PropertySpec pSpec = new PropertySpec(); pSpec.setType("Task"); pSpec.setAll(false); pSpec.getPathSet().add("info.state"); pSpec.getPathSet().add("info.result");
- Create a filter spec.PropertyFilterSpec fSpec = new PropertyFilterSpec(); fSpec.getObjectSet().add(oSpec); fSpec.getPropSet().add(pSpec);
- Create the filter.ManagedObjectReference pFilter = methods.createFilter(pCollector, fSpec, true);In the next section, we use thewaitForUpdatesExmethod to look for a change incloneTask.info.stateandcloneTask.info.result. When the state is “success”,cloneTask.info.resultis the managed object reference of the clone. Note that the order of property retrieval is not guaranteed, and it may take more than one call towaitForUpdatesExto retrieve both properties for a task.This code does not set a time-out (WaitOptions.maxWaitSecondsis unset), so after it has retrieved all of the property values,waitForUpdatesExwill block the thread, waiting for the TCP connection with the vSphere Server to time-out.How a client application handles the session depends on the particular context. (The client can callWaitForUpdatesExfrom its own thread, look for specific updates and then stop calling the method.)For more information aboutWaitOptionsand thewaitForUpdatesExmethod, see Client Data Synchronization (WaitForUpdatesEx).
- Initialize wait loop (?)String version = ""; Boolean wait = true; WaitOptions waitOptions = new WaitOptions(); while ( wait ) {
- Call WaitForUpdatesEx.UpdateSet uSet = methods.waitForUpdatesEx(pCollector, version, waitOptions); if (uSet == null) { wait = false; } else {
- Get the version for subsequent calls to WaitForUpdatesEx.version = uSet.getVersion();
- Get the list of property updates.List<PropertyFilterUpdate> pfUpdates = uSet.getFilterSet(); for (PropertyFilterUpdate pfu : pfUpdates) {
- Get the list of object updates produced by the filter.List<ObjectUpdate> oUpdates = pfu.getObjectSet(); for (ObjectUpdate ou : oUpdates) {
- Look for ObjectUpdate.kind=MODIFY (property modified).if (ou.getKind() == ObjectUpdateKind.MODIFY) { String name = ""; TaskInfoState state; ManagedObjectReference cloneRef = new ManagedObjectReference();
- Get the changed data.List<PropertyChange> pChanges = ou.getChangeSet();
- Retrieve the name of the propertyfor (PropertyChange pc : pChanges) { name = pc.getName(); //The task property names are info.state or info.result; //pc.val is an xsd:anyType: //-- for info.state, it is the state value //-- for info.result, it is the clone reference if (name.equals("info.state")) { state = (TaskInfoState)pc.getVal(); System.out.println("State is "+state.value()); } else if (name.equals("info.result")) { cloneRef = (ManagedObjectReference)pc.getVal(); System.out.println("Clone reference is "+cloneRef.getValue()); } }Authentication is handled using a TrustManager and supplying a host name verifier method. (The host name verifier is declared in the main function.)For the purposes of this example, this TrustManager implementation will accept all certificates. This is only appropriate for a development environment. Production code should implement certificate support.private static class TrustAllTrustManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public boolean isServerTrusted( java.security.cert.X509Certificate[] certs) { return true; } public boolean isClientTrusted( java.security.cert.X509Certificate[] certs) { return true; } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } }Now we are set to retrieve the task information, so we implement the main method.// cloneVMTask( server, user, password, virtual-machine ) public static void main(String [] args) throws Exception {
- We create variables to hold the values passed in from the command line.String serverName = args[0]; String userName = args[1]; String password = args[2]; String vmName = args[3]; String url = "https://"+serverName+"/sdk/vimService";
- Add variables for access to the API methods and services.// -- ManagedObjectReference for the ServiceInstance on the Server // -- VimService for access to the vSphere Web service // -- VimPortType for access to methods // -- ServiceContent for access to managed object services ManagedObjectReference SVC_INST_REF = new ManagedObjectReference(); VimService vimService;
- Declare a host name verifier that will automatically enable the connection. The host name verifier is invoked during the SSL handshake.HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { return true; } };
- Create the trust manager.javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManager tm = new TrustAllTrustManager(); trustAllCerts[0] = tm; // Create the SSL context javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL"); // Create the session context javax.net.ssl.SSLSessionContext sslsc = sc.getServerSessionContext(); // Initialize the contexts; the session context takes the trust manager. sslsc.setSessionTimeout(0); sc.init(null, trustAllCerts, null); // Use the default socket factory to create the socket for the secure connection javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
- Set the default host name verifier to enable the connection.HttpsURLConnection.setDefaultHostnameVerifier(hv);
- Set up the manufactured managed object reference for the ServiceInstanceSVC_INST_REF.setType("ServiceInstance"); SVC_INST_REF.setValue("ServiceInstance");
- Create a VimService object to obtain a VimPort binding provider. The BindingProvider provides access to the protocol fields in request/response messages. Retrieve the request context which will be used for processing message requests.vimService = new VimService(); methods = vimService.getVimPort(); Map<String, Object> ctxt = ((BindingProvider) methods).getRequestContext();
- Store the Server URL in the request context and specifytrueto maintain the connection between the client and server. The client API will include the Server's HTTP cookie in its requests to maintain the session. If you do not set this to true, the Server will start a new session with each request.ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url); ctxt.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);
- Retrieve the ServiceContent object and login.serviceContent = methods.retrieveServiceContent(SVC_INST_REF); methods.login(serviceContent.getSessionManager(), userName, password, null);
- Get references to the property collector and the view manager.pCollector = serviceContent.getPropertyCollector(); viewMgr = serviceContent.getViewManager();
- Get a reference to the specified virtual machine.ManagedObjectReference vmRef = getVmRef( vmName );
- Clone the virtual machine and wait for the result.cloneVM( vmRef );
- Close the connection.methods.logout(serviceContent.getSessionManager()); } }For general task monitoring, it is a best practice to use aViewManagerto monitor specific tasks. See theAPI Referencefor more information about using views.