vCenter Server tasks represent system activities that do not complete immediately, such as migrating a virtual machine. They are initiated by high-level activities performed with the vSphere Client in real time and activities that you schedule to occur at a later time or on a recurring basis.
The vCenter Server Tasks system is composed of definitions and operations. In this blog post the examples are written in Java with the usage of the vSphere Web Service SDK (vim25 library).
Definitions
The definitions represent a static information in the vCenter Server Tasks system such as task ids, faults, localization resources.
It is possible to manage task definitions through the vCenter Server’s ExtensionManager. One can create/delete task definitions by registering/unregistering new extensions in the ExtensionManager.
Above all, the Extension class has the following fields:
1 2 3 4 5 6 7 |
[youtube]<code>class Extension { ... ExtensionTaskTypeInfo[] taskList;[ ExtensionFaultTypeInfo[] faultList; ExtensionResourceInfo[] resourceList; ... } |
These fields are used to manage tasks’ static information. In this blog we will take a deep dive into definitions managed from the ExtensionManager.
Note: This information must be available in the vCenter Server Task Manager before an actual task is created with the specific ID. For example if a task with ID com.acme.task.MyTaskType is created, but the definition for this task is not available this will result in an error and the task will not be created.
Tasks
Defines information about the task itself. The taskID field uniquely identifies a task and is used during task creation. The ExtensionTaskTypeInfo field of the Extension can be used to create a new task definition.
1 2 3 4 5 |
final ExtensionTaskTypeInfo extensionTaskInfo = new ExtensionTaskTypeInfo(); extensionTaskInfo.setTaskID("com.acme.task.MyTaskType"); final List<extensiontasktypeinfo> taskInfos = extension.getTaskList(); taskInfos.add(extensionTaskInfo);</extensiontasktypeinfo> |
Faults
Defines information about the fault. Faults are used to specify the error type when a task fails. The faultID field uniquely identifies a fault. The ExtensionFaultTypeInfo field of the Extension can be used to create a new fault definition.
1 2 3 4 5 |
final ExtensionFaultTypeInfo extensionFaultInfo = new ExtensionFaultTypeInfo();(); extensionFaultInfo.setFaultID("com.acme.fault"); final List<ExtensionFaultTypeInfo> faultInfos = extension.getFaultList(); faultInfos.add(extensionFaultInfo); |
Localization
The localization definitions represent all bundles used for localization of task and fault definitions. To localize a task one should define the label and summary properties of the task and the summary property of the fault.
For example if we want to create localization bundle for the task with id com.acme.task.MyTaskType and the fault with id com.acme.fault then the resource bundle should look as follows:
1 2 3 |
com.acme.task.MyTaskType.label = "Task Label" com.acme.task.MyTaskType.summary = "Description of the Task" com.acme.fault.summary = "Description of the Fault" |
When registering an Extension one can provide a set of locales for multiple languages. For instance, this can be achieved with the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
final ExtensionResourceInfo extResourceInfo = new ExtensionResourceInfo(); extResourceInfo.setLocale("en"); extResourceInfo.setModule("resources"); final List<keyvalue> data = extResourceInfo.getData(); final KeyValue taskLabel = new KeyValue(); taskLabel.setKey("com.acme.task.MyTaskType.label"); taskLabel.setValue("Task Label"); data.add(taskLabel); final KeyValue taskSummary = new KeyValue(); taskSummary.setKey("com.acme.task.MyTaskType.summary"); taskSummary.setValue("Task Summary"); data.add(taskSummary); final KeyValue faultSummary = new KeyValue(); faultSummary.setKey("com.acme.fault.summary"); faultSummary.setValue("Fault Summary"); data.add(faultSummary); final List<extensionresourceinfo> resourceInfos = extension.getResourceList(); resourceInfos.add(extResourceInfo);</extensionresourceinfo></keyvalue> |
Operations
The operations are executed based on the static information already present in the vCenter task system. These operations include:
- Create Task
- Cancel Task
- Update Task (description, progress)
- Change State (error, success)
The operations maneuver the task through its lifecycle. The task’s lifecycle starts with its creation and ends when the task is marked as successful or failed. During this period the task’s description and progress can be updated.
Task’s instance lifecycle is defined as follows:
How to manage task’s lifecycle
In this section few code snippets will be presented which manage the lifecycle of a task. To invoke the VIM APIs the Java vim25 library is used. The first step is to have an authenticated VimPortType instance which will be used to make all the required API calls.
1 2 3 4 5 |
final VimPortType vimPort = vimSessionInfo.getVimPort(); final ServiceContent serviceContent = vimPort.retrieveServiceContent(serviceInstanceRef); final ManagedObjectReference taskMgr = serviceContent.getTaskManager(); final ManagedObjectReference rootFolder = serviceContent.getRootFolder(); |
Having the VimPortType instance and the TaskManager instance, we can start tasking around. As a first step we need a task in existence, so let us create one.
1 |
final TaskInfo task = vimPort.createTask(taskMgr, rootFolder, "com.acme.task.MyTaskType", "[email protected]", false, null, null); |
The above command creates a task with the following properties:
- identified by the taskID: com.acme.task.MyTaskType.
- associated with the rootFolder.
- The task is initiated from the [email protected] user.
- The task can not be canceled. For cancelable tasks the cancelTask API will terminate the task if in queued or running state, for non cancelable tasks it will throw an exception.
- The parentTaskKey and the activationId are not to be used.
Having created a task, it will be queued for execution. To move the task into a running state, the setTaskState API can be used as:
1 |
vimPort.setTaskState(task.getTask(), TaskInfoState.RUNNING, null, null); |
A running task represents a finite amount of work executing in the background. It is always a best practice to keep up the users with the latest updates, that is why the task should be updated whenever possible with the latest information. The task’s progress and description can be used to keep the user with the latest updates.
The description of the task is subject to the localization currently used, detailed information on how this can be done can be found from the VIM LocalizableMesage data object.
1 2 3 4 5 |
final LocalizableMessage locMsg = new LocalizableMessage(); locMsg.setKey("com.vmware.acme.task.details"); locMsg.setMessage("Configuring endpoints"); task.setDescription(locMsg); vimPort.setTaskDescription(task.getTask(), locMsg); |
The following is a simple example of task’s progress update:
1 2 3 4 5 6 |
vimPort.updateProgress(task.getTask(), 10); ... vimPort.updateProgress(task.getTask(), 50); ... vimPort.updateProgress(task.getTask(), 100); // at this point the task progress is at 100% and the task should be completed as successful. |
If the task is not cancelable, as it is in the examples above then there are only two possible outcomes, either the task succeeds or fails. Both of them are done by updating the state of the task.
To mark a task as failure we must choose one fault from the already defined fault definitions. In the example above we have registered an Extension which contains one fault with faultID: com.vmware.acme.fault . We can create a VimFault using this id and then update the task to display the needed information.
Let us first define a class extending the VimFault and setting the correct faultID.
1 2 3 4 5 6 7 8 9 |
public class SampleFault extends VimFault { public SampleFault() { this.faultMessage = getFaultMessage(); final LocalizableMessage msg = new LocalizableMessage(); msg.setKey("com.vmware.acme.fault.summary"); this.faultMessage.add(msg); } } |
Using a SampleFault instance we can create a localized fault and update the task with it. This way in the vSphere Client a localized message will be displayed in the tasks stack trace information.
1 2 3 4 |
final LocalizedMethodFault localized = new LocalizedMethodFault(); localized.setFault(new SampleFault()); task.setError(localized); vimPort.setTaskState(task.getTask(), state, null, localized); |
We will mark the end of this blog post, by marking a task as successful in its simplest form:
1 |
vimPort.setTaskState(task.getTask(), TaskInfoState.SUCCESS, null, null); |
The task that we have managed is shown in the bellow screenshot of the Recent Tasks.
vCenter Server tasks are a fundamental way to track long-running operations – recommended for any solution integrating with vSphere.