Run Program in Guest Operating System on VMware

Integrating VIX API into vSphere API is a great decision VMware made for its vSphere 5.0 release. Instead of working on two separate APIs, you now have one to deal with. It also solves the portability issue of VIX APIs which is tied to a specific platform – VIX has three versions for Windows, 32-bit Linux, and 64-bit Linux.

In the same week of vSphere 5.0 release, I added the support of vSphere 5 in vSphere Java API. Later on, I wrote an article on how VIX is implemented in the open source API. The article did not include any sample but high level introduction, design decisions, and a few API signatures.

I knew it’s not enough – we engineers like samples. Here is the first of a few samples I write to illustrate the usage of the APIs. In the future, I will create a higher level abstraction as part of the API, like what you can get from PowerCLI’s Invoke-VmScript cmdlet. (Update: it’s done. Check out the sample using the higher level API)

The follow sample is a simple VI Java code that runs a PowerShell script in a Windows guest OS. Note that the path of the PowerShell on your machine could be different. Please verify it and the PowerShell script file before you run the program.

import java.net.URL;

import com.vmware.vim25.GuestProgramSpec;
import com.vmware.vim25.NamePasswordAuthentication;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.GuestAuthManager;
import com.vmware.vim25.mo.GuestOperationsManager;
import com.vmware.vim25.mo.GuestProcessManager;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;

public class GuestRunProgram
{
  public static void main(String[] args) throws Exception
  {
    ServiceInstance si = new ServiceInstance(new URL("https://8.8.8.8/sdk"), "Administrator", "doublecloud.org", true);
    Folder rootFolder = si.getRootFolder();

    ManagedEntity[] mes = new InventoryNavigator(rootFolder).searchManagedEntities("VirtualMachine");
    if(mes==null || mes.length ==0)
    {
      return;
    }

    GuestOperationsManager gom = si.getGuestOperationsManager();

    VirtualMachine vm = (VirtualMachine) mes[0];

    if(!"guestToolsRunning".equals(vm.getGuest().toolsRunningStatus))
    {
      System.out.println("The VMware Tools is not running in the Guest OS on VM: " + vm.getName());
      System.out.println("Exiting...");
      return;
    }

    GuestAuthManager gam = gom.getAuthManager(vm);
    NamePasswordAuthentication npa = new NamePasswordAuthentication();
    npa.username = "Administrator";
    npa.password = "vijava";

    GuestProgramSpec spec = new GuestProgramSpec();
    spec.programPath = "C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe";
    spec.arguments = "-command \"c:\\temp\\policy.ps1\"";

    GuestProcessManager gpm = gom.getProcessManager(vm);
    long pid = gpm.startProgramInGuest(npa, spec);
    System.out.println("pid: " + pid);

    si.getServerConnection().logout();
  }
}

Before you run the code, make sure your VMware Tools is installed in the guest OS, and up to date. To find it out, you can go to the guest OS and click on the VMware Tools icon on the taskbar. It should tell you the versions and build number. In my case, the version is 8.6.0 build 425873.

Alternatively, you can right click on the virtual machine and select “Install/Upgrade VMware Tools.” The wizard will guide you through the installation or upgrading.

Now you’ve seen the code and hopefully have run the program. You may ask, “Wait a second, how can I get the standard output of the command I run remotely?”

A great question indeed! Unfortunately there is no direct support for you to get back the output other than the process ID. But we techies are creative at problem solving. The workaround is to redirect the output of the command to a file, and then download the file. Please stay tuned for next sample on how to download a file from a guest OS.

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

29 Comments

  1. Steve
    Posted March 13, 2012 at 10:43 am | Permalink

    Hi, love the API and using it to help with deployment of test systems.

    Is there any way to tell when a GuestProgram has finished? You also hint at a way of getting the result from a command but dont include any sample code

    Cheers
    Steve

  2. Posted March 13, 2012 at 10:53 am | Permalink

    Thanks Steve,
    Glad you like it. To tell whether a process is done, please consider this method defined in GuestProcessDirector:
    public GuestProcessInfo[] listProcesses(long[] pids)
    If you can get return back, then it’s still up running; otherwise it’s done.
    Good luck!
    Steve

  3. Felipe Krause
    Posted February 28, 2013 at 4:12 pm | Permalink

    Hi,
    Great post, I would like to know if there is a way to create a temporary file to save the output form the command dinammically?

    Thanks,
    Felipe

  4. Posted February 28, 2013 at 7:42 pm | Permalink

    I think you can use > output.txt after your command.
    Steve

  5. Felipe Krause
    Posted March 1, 2013 at 11:55 am | Permalink

    @Steve Jin

    It does not work. I already did that, and no file is created with the output.

    Any idea?

  6. Felipe Krause
    Posted March 1, 2013 at 11:57 am | Permalink

    @Felipe Krause

    The cmd line from GuestProcessInfo is:

    GuestProcessInfo.cmdLine: “C:\Windows\system32\hostname.exe” > C:\output.txt

    the ” is put by default.

  7. Felipe Krause
    Posted March 1, 2013 at 12:22 pm | Permalink

    Now it is working:

    GuestProgramSpec spec = new GuestProgramSpec();
    spec.programPath = POWERSHELL_EXE;
    //spec.programPath = cmd;
    spec.arguments = “-command “+cmd+” > “+C_CMDEXEC_OUTPUT_TXT;

    **I did not realize before, but I need to start the cmd with the powershell. Using only the cmd + output will not work.

  8. Posted March 1, 2013 at 2:09 pm | Permalink

    Thanks for sharing. The pipeline works only within a shell environment. PowerShell definitely fits that.

    Steve

  9. Sai
    Posted August 2, 2013 at 9:54 am | Permalink

    Nice Article.

    Did you see any limitations in using startProgramInGuest(npa, spec);

    Example:
    Execute a powershell which starts a new process?
    Execute a powershell script which executes msiexec.exe to install a new software on to the guest?

    Any idea if these kind of operations allowed

  10. Posted August 5, 2013 at 1:05 am | Permalink

    Hi Sai,

    Glad you like it. I have not tried the PowerShell commands as you suggested. I believe it should not a problem. You may want to include full path to the PowerShell interpreter, not just the command itself.

    Good luck and let me know any tips/tricks to make it work.

    Steve

  11. apapap
    Posted September 27, 2013 at 3:37 am | Permalink

    Hi Steve,

    Seems interesting!!!!

    I am trying to run “ipconfig” on “cmd” i.e. the windows command prompt.

    I tried the following code:

    GuestProgramSpec spec = new GuestProgramSpec();
    spec.programPath = “C:\\Windows\\System32\\cmd.exe”;
    spec.arguments = “ipconfig > \”C:\\ipconfig.txt\” “;

    Please check if this is the correct way to execute commands using the library on the command prompt.

    Is this library only restricted to “Windows”?
    Also, can we connect to linux machines and execute commands there?

  12. Sharu
    Posted October 1, 2013 at 2:55 pm | Permalink

    Hi Steve,

    When I execute the above program,the process get started but not visible in the foreground.I mean if I start Firefox one process gets created running in the background.Is there any way to make these programs visible running in guest machine.

  13. Bud
    Posted October 14, 2013 at 3:28 pm | Permalink

    Hey Steve,

    Have you run into issues where output redirecting in Windows guests (2008 R2 in my case) does not work when using startProgramInGuest?

    As an example, I’m passing the programPath as “C:\\Windows\\System32\\hostname.exe”, with arguments as “> C:\\testout.txt”. Regardless of the output path, the redirection of output to a file never seems to work.

    Thanks!

  14. Posted October 14, 2013 at 9:47 pm | Permalink

    Hey Bud,

    The redirection works only in a Shell command, not from any program. So if you change the program path to the cmd.exe and run your hostname as part of the command parameters, it should then work.

    Good luck!

    Steve

  15. Bud
    Posted October 23, 2013 at 9:03 am | Permalink

    Steve – that’s super helpful. We’ll give that a shot. Thank you!

  16. Posted October 23, 2013 at 10:49 am | Permalink

    You are very welcome Bud, let me know if it works or not.

    Steve

  17. Samy
    Posted November 15, 2013 at 10:25 am | Permalink

    Hi Steve.. i tried to run your program.. it gives an error..
    i debugged it.. the following line gives an error..
    “long pid = gpm.startProgramInGuest(npa, spec);”

    The error is “Exception in thread “main” java.rmi.RemoteException: VI SDK invoke exception:com.vmware.vim25.InvalidRequest”

    Please help! I am waiting for your reply!

    Thanks,
    Samy.

  18. Posted November 15, 2013 at 2:27 pm | Permalink

    Hi Samy, as the exception name suggests, the arguments passed into the API are not valid… What did you pass in?

    Steve

  19. Samy
    Posted November 16, 2013 at 3:08 am | Permalink

    Dear Steve,
    Server: ESXi 5.1
    I am using Vsphere Client 5.1..
    My quest os is Windows 7 and ubuntu..
    My requirement is”i want to open a ShortCut that i created in guest os desktop for script file.. when i click the desktop shortcut the script is running..”
    i tried my requirement with your code.. it didn’t work.. so first i tried to open a notepad in guest os..then i got the exception error which i mentioned above.. i mentioned the program also.. So if you help for my requirement.. it will be very helpful..

    Thank you,
    Samy.

  20. Posted November 16, 2013 at 3:48 am | Permalink

    I don’t expect your requirement would work. Why not call your scripts directly? Also remember to include shell executable in your parameter.

    Good luck,

    Steve

  21. Prabhu
    Posted November 18, 2013 at 8:53 am | Permalink

    Samy :
    Dear Steve,
    Here is the complete program..
    Can you tell me the mistake what i did?Please correct it.. it will be helpful for me!!
    package com.vmware.vim25.mo.samples.vm;
    import java.net.URL;
    import com.vmware.vim25.GuestProgramSpec;
    import com.vmware.vim25.NamePasswordAuthentication;
    import com.vmware.vim25.mo.Folder;
    import com.vmware.vim25.mo.GuestAuthManager;
    import com.vmware.vim25.mo.GuestOperationsManager;
    import com.vmware.vim25.mo.GuestProcessManager;
    import com.vmware.vim25.mo.InventoryNavigator;
    import com.vmware.vim25.mo.ManagedEntity;
    import com.vmware.vim25.mo.ServiceInstance;
    import com.vmware.vim25.mo.VirtualMachine;
    import java.rmi.RemoteException;
    public class Openshortcut
    {
    public static void main(String[] args) throws Exception
    {
    ServiceInstance si = new ServiceInstance(new URL(“https://192.168.80.140/sdk”), “root”, “xyxyxy”,true);
    Folder rootFolder = si.getRootFolder();
    ManagedEntity[] mes = new InventoryNavigator(rootFolder).searchManagedEntities(“VirtualMachine”);
    if(mes==null || mes.length ==0)
    {
    return;
    }
    String vmname = “VM Win 7″;
    GuestOperationsManager gom = si.getGuestOperationsManager();
    VirtualMachine vm = (VirtualMachine) new InventoryNavigator(
    rootFolder).searchManagedEntity(“VirtualMachine”,vmname);
    if(!”guestToolsRunning”.equals(vm.getGuest().toolsRunningStatus))
    {
    System.out.println(“The VMware Tools is not running in the Guest OS on VM: ” + vm.getName());
    System.out.println(“Exiting…”);
    return;
    }
    GuestAuthManager gam = gom.getAuthManager(vm);
    NamePasswordAuthentication npa = new NamePasswordAuthentication();
    npa.username = “xyxyxy”;
    npa.password = “xyxyxy”;
    GuestProgramSpec spec = new GuestProgramSpec();
    spec.programPath = “C:\\Windows\\system32\\notepad.exe”;
    GuestProcessManager gpm = gom.getProcessManager(vm);
    long pid = gpm.startProgramInGuest(npa, spec);
    System.out.println(“pid: ” + pid);
    si.getServerConnection().logout();
    }
    }
    Thanks,
    Samy.

  22. Samy
    Posted November 19, 2013 at 5:03 am | Permalink

    Dear Steve,

    One Humble Request please remove my old comments which contains program examples from your blog..

    Please remove sir,

    I am waiting for your actions,

    Thank you,
    Samy.

  23. Sandipan Sen
    Posted January 2, 2014 at 9:51 am | Permalink

    Hi Steve,
    I’m new to the vsphere api. I was trying your above code found and NullPointerException in the following line:
    GuestOperationsManager gom = si.getGuestOperationsManager();

    Cant find the root of the problem. Help from you would be highly appreciated.

    Thanks,
    Sandipan

  24. Posted January 2, 2014 at 12:23 pm | Permalink

    Hi Sandipan,

    What version of vSphere are you using? There seems to be a bug in vSphere 5.1.

    Steve

  25. Sandipan Sen
    Posted January 3, 2014 at 1:03 am | Permalink

    Hi Steve,
    I have tried to execute your program with with different versions of vijava(like vsphere 5.5(beta),vsphere5.2) but every time si.getGuestOperationsManager() is returning a null value.
    Is there in any other alternative way of executing programs in guest OS.
    I have Esxi 4.1 box and it has a free license.

    I’m really at my wits end. Please help
    Thanks,
    Sandipan

  26. Posted January 3, 2014 at 2:50 pm | Permalink

    You need to try a different version of vSphere server. The bug is on the server side, not vijava API. ESXi 4.1 does not support guest related API. Try 5.0 instead.

    Steve

  27. Alex M
    Posted January 28, 2014 at 6:21 am | Permalink

    Hi Steve

    Help, please, in understanding.

    I permanently get: com.vmware.vim25.NoPermission on long pid = gpm.startProgramInGuest(npa, spec);
    whats can be wrong.

    Thanks
    Alex

  28. Posted January 28, 2014 at 10:36 am | Permalink

    As the exception says, your login user does NOT have permission to execute the command. Try it with root user to see if you’ll still get the exception.

    Steve

  29. Alex M
    Posted January 28, 2014 at 11:03 am | Permalink

    Thanks, but if all was be so easy, I’ll resolved this. User is Administrator(i mean it consist in Administrator group )on the particular host. Maybe this some settings for VM in vSphere, maybe something should be enable for “inGuest” manipulation.

2 Trackbacks

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=""> <strike> <strong>

  • NEED HELP?


    My consulting helps clients with virtualization and cloud computing, including VMware infrastructure automation and orchestration, vSphere management APIs, and deep product integration with hypervisors. Current training offerings include vSphere APIs training, vCenter Orchestrator training, and etc. Should you, or someone you know, need these consulting services or training, 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.