Creating Your Own Task and Event in vSphere

vSphere has a powerful extension mechanism that allows you to add new features as integral part of the platform. Many vendors have already leveraged this by providing plug-ins so that users can manage their components seamlessly within same vSphere Client.

You can actually do more than that with the extension. The following sample shows how to create your own task and event with vSphere API. The code should be self explanatory therefore I don’t elaborate much here. Note that you must run the sample with a vCenter server as extensibility is implemented only in vCenter.

Lost VMs or Containers? Too Many Consoles? Too Slow GUI? Time to learn how to "Google" and manage your VMware and clouds in a fast and secure HTML5 App.

When running the code, you can see a new task created and progresses with 10% every second in the “Recent Tasks” pane of vSphere Client. When the task is done, you will also see a new event posted in the “Tasks & Events” tab of the host you associate the task with.

What can you do with this capability? Here are two typical use cases:

  1. Use it in your vSphere Client plug-in so that progress of a chosen operation is visible to all logged in users. In that case, you don’t need to create additional extension;
  2. Use it in your server extension applications such as VMware Site Recovery Manager.

You can also use it in a utility program as this sample, but may be an over use of this feature.

package com.vmware.vim25.mo.samples;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Calendar;

import com.vmware.vim25.Description;
import com.vmware.vim25.Extension;
import com.vmware.vim25.ExtensionEventTypeInfo;
import com.vmware.vim25.ExtensionResourceInfo;
import com.vmware.vim25.ExtensionTaskTypeInfo;
import com.vmware.vim25.KeyValue;
import com.vmware.vim25.TaskInfo;
import com.vmware.vim25.TaskInfoState;
import com.vmware.vim25.mo.ExtensionManager;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.Task;
import com.vmware.vim25.mo.TaskManager;

public class CreateCustomTask
{
  final static String EXTENSION_KEY = "DoubleCloud";

  public static void main(String[] args) throws RemoteException, MalformedURLException, InterruptedException
  {
    if (args.length != 3)
    {
      System.out.println("java CreateCustomTask <SdkUrl> <username> <password>");
      System.out.println("java CreateCustomTask https://192.168.8.8/sdk administrator password");
      return;
    }

    ServiceInstance si = new ServiceInstance(new URL(args[0]), args[1], args[2], true);
    ManagedEntity[] mes =  new InventoryNavigator(si.getRootFolder()).searchManagedEntities("HostSystem");
    HostSystem host = (HostSystem) mes[0];

    ExtensionManager em = si.getExtensionManager();
    if(em.findExtension(EXTENSION_KEY)==null)
    {
      em.registerExtension(createExtension());
    }

    //allow a little time for vCenter to persist the extension data
    Thread.sleep(3000);

    TaskManager tm = si.getTaskManager();
    TaskInfo ti = tm.createTask(host, "AcmeBackupTask", "Administrator", true);
    Task task = new Task(si.getServerConnection(), ti.getTask());

    //change the state to running before updating the progress
    task.setTaskState(TaskInfoState.running, null, null);
    for(int i=1; i<=10; i++)
    {
      System.out.println("percentage done: " + i*10);
      task.updateProgress(i*10);
      Thread.sleep(1000);
    }
    task.setTaskState(TaskInfoState.success, null, null);

    //remove extension. you can leave it there and no need to register next time
    em.unregisterExtension(EXTENSION_KEY);
    si.getServerConnection().logout();
  }

  private static Extension createExtension()
  {
    Extension extension = new Extension();

    Description desc = new Description();
    desc.setLabel("DoubleCloud");
    desc.setSummary("A sample extension with a new type of task.");

    ExtensionTaskTypeInfo etti = new ExtensionTaskTypeInfo();
    etti.setTaskID("AcmeBackupTask");

    ExtensionEventTypeInfo eeti = new ExtensionEventTypeInfo();
    eeti.setEventID("AcmeBackupEvent");

    KeyValue kv1 = new KeyValue();
    kv1.setKey("AcmeBackupTask.category");
    kv1.setValue("info");

    KeyValue kv2 = new KeyValue();
    kv2.setKey("AcmeBackupTask.label");
    kv2.setValue("Acme backup task");

    KeyValue kv3 = new KeyValue();
    kv3.setKey("AcmeBackupTask.fullFormat");
    kv3.setValue("Acme backup virtual machines on host {hostname}");

    ExtensionResourceInfo eri = new ExtensionResourceInfo();
    eri.setLocale("en");
    eri.setModule("task");
    eri.setData(new KeyValue[] {kv1, kv2, kv3});

    extension.setDescription(desc);
    extension.setKey(EXTENSION_KEY);
    extension.setVersion("1.0.0");
    extension.setLastHeartbeatTime(Calendar.getInstance());
    extension.setCompany("Acme Inc.");
    extension.setTaskList(new ExtensionTaskTypeInfo[] { etti });
    extension.setEventList(new ExtensionEventTypeInfo[] { eeti });
    extension.setResourceList(new ExtensionResourceInfo[] { eri });

    return extension;
  }
}
package com.vmware.vim25.mo.samples;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Calendar;

import com.vmware.vim25.Description;
import com.vmware.vim25.Extension;
import com.vmware.vim25.ExtensionEventTypeInfo;
import com.vmware.vim25.ExtensionResourceInfo;
import com.vmware.vim25.ExtensionTaskTypeInfo;
import com.vmware.vim25.KeyValue;
import com.vmware.vim25.TaskInfo;
import com.vmware.vim25.TaskInfoState;
import com.vmware.vim25.mo.ExtensionManager;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.Task;
import com.vmware.vim25.mo.TaskManager;

public class CreateCustomTask
{
final static String EXTENSION_KEY = “DoubleCloud”;

public static void main(String[] args) throws RemoteException, MalformedURLException, InterruptedException
{
if (args.length != 3)
{
System.out.println(“java CreateCustomTask <SdkUrl> <username> <password>”);
System.out.println(“java CreateCustomTask https://192.168.8.8/sdk administrator password”);
return;
}

ServiceInstance si = new ServiceInstance(new URL(args[0]), args[1], args[2], true);
ManagedEntity[] mes =  new InventoryNavigator(si.getRootFolder()).searchManagedEntities(“HostSystem”);
HostSystem host = (HostSystem) mes[0];

ExtensionManager em = si.getExtensionManager();
if(em.findExtension(EXTENSION_KEY)==null)
{
em.registerExtension(createExtension());
}

//allow a little time for vCenter to persist the extension data
Thread.sleep(3000);

TaskManager tm = si.getTaskManager();
TaskInfo ti = tm.createTask(host, “AcmeBackupTask”, “Administrator”, true);
Task task = new Task(si.getServerConnection(), ti.getTask());

//change the state to running before updating the progress
task.setTaskState(TaskInfoState.running, null, null);
for(int i=1; i<=10; i++)
{
System.out.println(“percentage done: ” + i*10);
task.updateProgress(i*10);
Thread.sleep(1000);
}
task.setTaskState(TaskInfoState.success, null, null);

//remove extension. you can leave it there and no need to register next time
em.unregisterExtension(EXTENSION_KEY);
si.getServerConnection().logout();
}

private static Extension createExtension()
{
Extension extension = new Extension();

Description desc = new Description();
desc.setLabel(“DoubleCloud”);
desc.setSummary(“A sample extension with a new type of task.”);

ExtensionTaskTypeInfo etti = new ExtensionTaskTypeInfo();
etti.setTaskID(“AcmeBackupTask”);

ExtensionEventTypeInfo eeti = new ExtensionEventTypeInfo();
eeti.setEventID(“AcmeBackupEvent”);

KeyValue kv1 = new KeyValue();
kv1.setKey(“AcmeBackupTask.category”);
kv1.setValue(“info”);

KeyValue kv2 = new KeyValue();
kv2.setKey(“AcmeBackupTask.label”);
kv2.setValue(“Acme backup task”);

KeyValue kv3 = new KeyValue();
kv3.setKey(“AcmeBackupTask.fullFormat”);
kv3.setValue(“Acme backup virtual machines on host {hostname}”);

ExtensionResourceInfo eri = new ExtensionResourceInfo();
eri.setLocale(“en”);
eri.setModule(“task”);
eri.setData(new KeyValue[] {kv1, kv2, kv3});

extension.setDescription(desc);
extension.setKey(EXTENSION_KEY);
extension.setVersion(“1.0.0”);
extension.setLastHeartbeatTime(Calendar.getInstance());
extension.setCompany(“Acme Inc.”);
extension.setTaskList(new ExtensionTaskTypeInfo[] { etti });
extension.setEventList(new ExtensionEventTypeInfo[] { eeti });
extension.setResourceList(new ExtensionResourceInfo[] { eri });

return extension;
}
}

This entry was posted in vSphere API and tagged , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

33 Comments

  1. Posted September 9, 2010 at 4:56 am | Permalink

    Wow! It’s really awesome feture of vCenter.
    Steve is there any ability to set IP address (ip,netmask, gateway) to concrete ethernet adapater of VM by means of vCenter???

    I’ve tried a lot of things but unfortunatelly still there is no results.

  2. Posted September 11, 2010 at 12:35 am | Permalink

    Do you mean you want to change the networking setting like IP address by connecting to vCenter server? What API have you tried?

    Steve

  3. Yogesh
    Posted May 3, 2011 at 1:43 am | Permalink

    Hi,

    I have used this in our product, but when I call findExtention on ExtensionManager it returns me a extension object with empty ResourceList. Do you know why this must be happening. I wanted to updateExtension due to some reasons and so I added some more events and resoure info list for new event keys and next updateExtension. But it overrides old values and the description in vSphere for old events is seen as XXX.

    Does any one know about this ? Please revert back if any solution / information.

    Regards,
    Yogesh G

  4. Bob Fletcher
    Posted May 23, 2011 at 4:51 am | Permalink

    This is the most comprehensive description I could find of how to do this- thanks!

    But there’s always one more question…

    In my case I was wondering how to specify some elements of the formatted message when an event is posted, rather than when the event type is specified in an extension.

    If I leave the formatted message empty in the definition and attempt to set it at creation-time, it is filled in with what looks like an identifier for this property, e.g. “event.com.my.event.blah”

    So, next, I assume that the {} syntax can be used for argument replacement at event-creation time. I assume that the use of {} in the formatted message will correspond to the arguments in the eventTypeSchema.
    However, I find that if I try to specify an XML event type schema using VI Java, the SOAP parser seems to be confused by the unexpected XML, (somewhat like the story of the boy called “Robert Drop Table” in xkcd!).

    The error trace is:
    —-
    Unexpected element tag “EventType” seen

    while parsing serialized value of type string
    at line 1, column 737

    while parsing property “eventTypeSchema” of static type string

    while parsing serialized DataObject of type vim.Extension.EventTypeInfo
    at line 1, column 678

    while parsing property “eventList” of static type ArrayOfExtensionEventTypeInfo

    while parsing serialized DataObject of type vim.Extension
    at line 1, column 377

    while parsing call information for method RegisterExtension
    at line 1, column 285

    while parsing SOAP body
    at line 1, column 271

    while parsing SOAP envelope
    at line 1, column 38

    while parsing HTTP request for method registerExtension
    on object of type vim.ExtensionManager
    at line 1, column 0
    —————————–

    Is there some way of “escaping” the XML, or is there another way of defining arguments for replacement at event creation time?

    Thanks!

  5. Bob Fletcher
    Posted May 23, 2011 at 5:09 am | Permalink

    @Bob Fletcher
    And of course, immediately after posting, I had a d’oh moment. Simply turn the of the eventTypeSchema into < and > and it works a treat. Hope this is of use to someone else…

  6. Posted May 23, 2011 at 10:21 am | Permalink

    Hi Bob,

    Glad you find it useful. If you want to include XML data in any string using vijava, you want to escape the 5 special characters like & etc.

    -Steve

  7. Bob Fletcher
    Posted May 25, 2011 at 7:30 am | Permalink

    Great, thanks!

    I’m afraid I have a follow-up question…

    I find that when creating custom tasks as described, I get an error in the “Task” field of the corresponding event listing which looks like: “**NO DESCRIPTION FOR: AcmeBackup Task”.

    Where should this description be defined?

    I assumed the the “.fullFormat” key-value pair defined this, and have also tried using a “.summary” key as suggested elsewhere.

    I’ve also tried setting Task.setTaskDescription at creation time, but this resulted in an invalid request error…

    I’m using vSphere 5.0.0 beta if that’s relevant.

    Thanks!

  8. Frank Yang
    Posted June 2, 2011 at 11:16 am | Permalink

    @Yogesh
    Your obervation is correct. The resource list is always Unset in MOB and you won’t find it in returned extension object either. It is by design according to VMware. On the same token, updating resource list is actually creating a new one. So you will have to include previously defined events, in addition to new ones, in your call. BTW, the resources are stored in files not database: C:\Program Files\VMware\Infrastructure\VirtualCenter Server\extensions. However I will still use Web Service calls to alter these files to be safe.

  9. Frank Yang
    Posted June 2, 2011 at 12:54 pm | Permalink

    @Bob Fletcher
    You have noticed the column head reads “Task”. So the key is “.label”, whose value shows up in othe two places as you may already see, and you should see “Acme backup event” after running Steve’s sample. I have tried my other apps with 5.0 and nothing is broken yet. So I doubt the version is the cause. It behaves as expected in both my C# and Java codes. I did observe this once while migrating my codes from C# to Java. Somehow it disappeared after I restarted my Java dev environment for a different reason.

  10. Prithvee
    Posted December 6, 2011 at 6:33 am | Permalink

    This is about task notification. How can we post event which is not task?

  11. QuanT
    Posted January 31, 2012 at 9:13 pm | Permalink

    In my server extension, I define my event with ExtensionEventTypeInfo(), and in there I define the eventTypeSchema property with an XML that contains 1 argument (snip) chassisstring.
    I also register a message resource for use with this event type, which contains the .fullformat string as “Show {chassis} info”.

    Question: when I post an event, how should I pass in a value for this argument so that it replaces the {chassis} argument when displayed?

    To post an event of the above type, I first create an ExtendedEvent object and do a PostEvent(), but can’t find a way to get the event .fullformat string to show the {chassis} value. I played with the ExtendedEvent.data as well as ExtendedEvent.dynamicProperty but none worked.

  12. angelo
    Posted February 3, 2012 at 8:33 am | Permalink

    Hi I have successfully registered a task and can update its using task.setTaskState(state, null, null), where state is either TaskInfoState.error or TaskInfoState.success. The problem I am having is setting the status message when I have an error. The documentation suggests

    LocalizedMethodFault msg = new LocalizedMethodFault();
    msg.localizedMessage = “My error message”;
    msg.fault = null;
    vmTask.setTaskState(TaskInfoState.error, null, msg);

    But if I do this I get an exception thrown com.vmware.vim25.InvalidRequest
    This is driving me nuts. Does anyone have any idea? Should the localizedMessage be a key value lookup into a message catalogue somewhere?

  13. QuanT
    Posted February 10, 2012 at 1:12 pm | Permalink

    @QuanT
    The answer is to use EventEx instead of ExtendedEvent

  14. deepak
    Posted May 10, 2012 at 2:24 pm | Permalink

    @angelo

    Hi angelo, I’m hitting the same issue. were you able to fix it?

  15. syed
    Posted May 14, 2012 at 10:05 am | Permalink

    Hi

    We are working on a vCenter plugin which has a number of custom tasks/events associated with it. We have successfully managed to achieve this using your example.

    The problem: Tasks/Events can be registered easily but when we unregister the plugin and then register it again with some new messages for Tasks/Events the old messages are shown instead of the new ones. I have noticed that on registration it creates .vmsg files in the following location:

    “C:\Program Files\VMware\Infrastructure\VirtualCenter Server\extensions\PLUGIN-KEY\locale\en\”

    Apparently these files also contain the updated strings each time the plugin is updated and registered with new strings. Inspecting the tasks from the mob somehow shows the old strings. When the tasks are run they still show those old strings that were supposed to have been updated. This is annoying.

    It appears as if the only way to update those messages is to reinstall the vcenter and then register the extension. Even in that case the strings can only be updated once unless the vCenter is reinstalled. Can someone please give an explanation for this behavior of plugin or point out what could have gone wrong?

  16. Posted May 14, 2012 at 6:23 pm | Permalink

    Good question. I haven’t gone that far to delete anything. What if you delete the .vmsf file after the unregistration? Please make sure to back it up though.
    Steve

  17. syed
    Posted May 15, 2012 at 3:49 am | Permalink

    It appears as if that file has no effect on the string/messages shown inside the mob. So even when the plugin is registered and the file is deleted, the custom tasks continue to show the same old messages. If I delete these files after unregistering, they are created again when the plugin is registered but still this has no effect on the messages shown inside the mob.

    Can you please explain why those old messages continue to appear even after I re-register the plugin with the new ones? I have a feeling that there is some sort of key-value cache or database that does not get updated if we try to input a message having a key already present in that database.

  18. Posted May 15, 2012 at 10:23 pm | Permalink

    If that is the case, I think the information is also stored inside database, therefore recreated if the file is missing. You may want to open a SR with VMware support on this.

    Steve

  19. syed
    Posted May 16, 2012 at 4:18 am | Permalink

    Hi Steve

    Thanks for your response. I have noticed that the information is cached somewhere and is not updated when a plugin is registered. If the vCenter services are restarted then everything is read again (probably from the text files) and the information in custom tasks or any other custom strings gets updated.

  20. angelo
    Posted June 18, 2012 at 4:00 am | Permalink

    Deepak, no I never worked it out and worked around it, haven’t had time to return to it. I would appreciate an example if you managed to find out how to do it.
    QuanT, do you have an example of using EventEx to generate meaningful messages.

  21. Tejaswi
    Posted December 24, 2012 at 5:25 am | Permalink

    how to create VM with the help pf Vsphere API?

  22. Posted December 26, 2012 at 12:47 pm | Permalink

    check out the source code of the API package – there is a sample showing how to create a new VM there.
    Steve

  23. kim
    Posted February 5, 2013 at 4:24 am | Permalink

    how to get vm lists from 1 cluster using vi java?
    i m getting all the vms’s list ,but it does not display from which cluster they are belongs to…
    need ur help

  24. AJ
    Posted February 26, 2013 at 7:30 pm | Permalink

    @angelo

    Since vSphere 5.1 forces to specify “fault’ along for setTaskState with TaskInfostate.ERROR, I’m also running into same issue. Were you able to fix it?

  25. John
    Posted June 23, 2014 at 4:45 pm | Permalink

    So I am able to do this fine, but I am having some trouble when it comes to updating the task with an ERROR state. All works fine when I update the task to a success state, but when I update the task with an error state I must be doing it wrong because the recent tasks pane breaks and I see this message (from the recent tasks pane):
    “faultCode:Server.Processing faultString:’An error error occurred while serializing server response(s). ‘faultDetail:’null’ ”

    I see someone here is having a similar problem: https://communities.vmware.com/message/2047506

    Except they are getting an invalid argument error.

    Can you provide an example of how to correctly set an error state on a task. I think that this would really complete this post.

  26. Nikolas
    Posted February 4, 2015 at 4:52 am | Permalink

    Hi Steve,

    I’m trying to create a task in a specific Virtual Machine, to advert the VM User that the VM is “busy”, and unable to manage snapshots. Is it possible?

    I’ve also tried unabling doing snapshots, but I didn’t succes. Do you know what should I do?

    Thanks!

  27. Posted February 4, 2015 at 10:18 am | Permalink

    Hi Nikolas,

    Are you trying to do something within the guest OS running on the VM and therefore want to disable snapshot function of the VM in vSphere Client?

    Steve

  28. Nikolas
    Posted February 4, 2015 at 11:06 am | Permalink

    Hi Steve,

    Yes, something like that. I’m trying to copy the VM disks with a little program I’m developing. First of all, I do a snapshot in order to “liberate” the disks. Therefore I would like to disable snapshot function of the VM in vSphere Client during the operation.

    Thank you for your attention and I look forward to your comment!

    Nikolas

  29. Posted February 4, 2015 at 9:49 pm | Permalink

    Even if your vm is busy, the snapshot can still go forward. What is your concern?

    Steve

  30. Nikolas
    Posted February 5, 2015 at 3:21 am | Permalink

    My main problem is that I can’t disable the snapshot function of the VM in vSphere Client while the copy is beeing made. And the second concern would be to show the VM user the progress bar of the copy.

    Thanks a lot!

    Nikolas

  31. Posted February 6, 2015 at 12:27 pm | Permalink

    There is a private API for you to do this, but not exposed. You can ask VMware for help.

  32. abhilasha
    Posted February 20, 2015 at 1:26 am | Permalink

    @angelo

    Since vSphere 5.1 forces to specify “fault’ along for setTaskState with TaskInfostate.ERROR,
    I’m also running into same issue. It gives me InvalidMessageFault .Were you able to fix it?

    can you please provide the example to set the Task state to error.

  33. ZC
    Posted October 7, 2015 at 4:17 am | Permalink

    Hi Steve,
    How would this example change for The vSphere Web Client 6.0 and it’s change in localization handling?

    The client still displays the task name as “AcmeBackupTask.label”, even though there is a translation key defined for it.

    KeyValue kv2 = new KeyValue();
    kv2.setKey(“AcmeBackupTask.label”);
    kv2.setValue(“Acme backup task”);

    Thanks!

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  • NEED HELP?


    My company has created products like vSearch ("Super vCenter"), vijavaNG APIs, EAM APIs, ICE tool. We also help clients with virtualization and cloud computing on customized development, training. Should you, or someone you know, need these products and services, please feel free to contact me: steve __AT__ doublecloud.org.

    Me: Steve Jin, VMware vExpert who authored the VMware VI and vSphere SDK by Prentice Hall, and created the de factor open source vSphere Java API while working at VMware engineering. Companies like Cisco, EMC, NetApp, HP, Dell, VMware, are among the users of the API and other tools I developed for their products, internal IT orchestration, and test automation.