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.
RetrievePropertiesEx()
and WaitForUpdatesEx()
in this
example ignore the possibility of additional chunks of data returned by the property
collector. For more information about chunking in property collector results, see Server Data Transmission.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
Procedure
-
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 uses
getVMRef(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 an
ObjectSpec to define the
beginning of the traversal. Use the
setObj method to specify
that the container view is the root object for this traversal. Set the
setSkip method 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 specified
vmName.
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 an
Object Spec to define the
property collection. Use the
setObj method to specify
that the vmRef is the root object for this traversal. Set the
setSkip method 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 the
cloneVM method and pass in
the
vmRef
that 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 the waitForUpdatesEx method to look for a change in cloneTask.info.state and cloneTask.info.result. When the state is “success”, cloneTask.info.result is 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 to waitForUpdatesEx to retrieve both properties for a task.
This code does not set a time-out (WaitOptions.maxWaitSeconds is unset), so after it has retrieved all of the property values, waitForUpdatesEx will 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 call WaitForUpdatesEx from its own thread, look for specific updates and then stop calling the method.)
For more information about WaitOptions and the waitForUpdatesEx method, 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 property
for (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 ServiceInstance
SVC_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 specify
true to 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()); } }
Note:For general task monitoring, it is a best practice to use a ViewManager to monitor specific tasks. See the API Reference for more information about using views.