Calling VMware VIX API from Java

A user asked if J/Invoke could be used to automate VMWare server/workstation. Yes, very easily.

VMware provides a VIX automation API that allows users to write programs to automate virtual machine operations. The VIX API is available as a C API which makes it very easy to call it from Java using J/Invoke.

The following Java code uses J/Invoke to open a virtual machine and power it on using vix.dll:

package vix;

import com.jinvoke.Callback;
import com.jinvoke.Charset;
import com.jinvoke.JInvoke;
import com.jinvoke.NativeImport;

@NativeImport(library="C:\\Program Files\\VMware\\VMware VIX\\ws-3\\32bit\\vix.dll", charset=Charset.ANSI)
public class Vix {
    
    public static void main(String[] args) {
        JInvoke.initialize();
        String vmxPath = "I:\\VirtualMachines\\Windows2003ServerEE\\Windows Server 2003 Enterprise Edition.vmx";

        int    jobHandle  =   VIX_INVALID_HANDLE  ;
        int [] hostHandle = { VIX_INVALID_HANDLE };
        int [] vmHandle   = { VIX_INVALID_HANDLE };

        try {
            // Connect
            jobHandle = VixHost_Connect(VIX_API_VERSION, VIX_SERVICEPROVIDER_VMWARE_WORKSTATION, 
                    "127.0.0.1" , 0, null, null, 0, VIX_INVALID_HANDLE, null, null);
            long result = VixJob_Wait(jobHandle, VIX_PROPERTY_JOB_RESULT_HANDLE, hostHandle, VIX_PROPERTY_NONE);
            if (result != VIX_OK) {
                System.out.println("Error in connecting " + result);
                return;
            }
            Vix_ReleaseHandle(jobHandle);
            
            // Open VM
            jobHandle = VixVM_Open(hostHandle[0], vmxPath, null, null);
            result = VixJob_Wait(jobHandle, VIX_PROPERTY_JOB_RESULT_HANDLE, vmHandle, VIX_PROPERTY_NONE);
            if (result != VIX_OK) {
                System.out.println("Error in opening VM: " + result);
                return;
            }
            Vix_ReleaseHandle(jobHandle);
            
            // Power On VM
            jobHandle = VixVM_PowerOn(vmHandle[0], VIX_VMPOWEROP_LAUNCH_GUI, VIX_INVALID_HANDLE, null, null);
            result = VixJob_Wait(jobHandle, VIX_PROPERTY_NONE, null, VIX_PROPERTY_NONE);
            if (result != VIX_OK) {
                System.out.println("Error in powering VM on: " + result);
                return;
            }
            Vix_ReleaseHandle(jobHandle);
            
            // Power Off VM
            jobHandle = VixVM_PowerOff(vmHandle[0], VIX_VMPOWEROP_NORMAL, null,  null);
            result = VixJob_Wait(jobHandle, VIX_PROPERTY_NONE, null, VIX_PROPERTY_NONE);
            if (result != VIX_OK) {
                System.out.println("Error in powering VM off: " + result);
                return;
            }   
        } finally {
            Vix_ReleaseHandle(jobHandle);
            Vix_ReleaseHandle(vmHandle[0]);
            VixHost_Disconnect(hostHandle[0]);
        }
    }
    
    
    public static native int  VixHost_Connect(int apiVersion,
        int hostType,
        String hostName,
        int hostPort,
        String userName,
        String password,
        int options,
        int propertyListHandle,
        Callback callbackProc,
        byte[] clientData);

    public static native void VixHost_Disconnect(int hostHandle);
    public static native void Vix_ReleaseHandle(int handle);
    public static native long VixJob_Wait(int jobHandle, int firstPropertyID, int[] handle, int propertyNone);
    
    public static native int VixVM_Open(int hostHandle,
        String vmxFilePathName,
        Callback callbackProc,
        byte[] clientData);

    public static native int VixVM_PowerOn(int vmHandle,
        int powerOnOptions,
        int propertyListHandle,
        Callback callbackProc,
        byte[] clientData);
    
    public static native int VixVM_PowerOff(int vmHandle,
        int powerOffOptions,
        Callback callbackProc,
        byte[] clientData);
    
    public static final int VIX_API_VERSION                         = 3;
    public static final int VIX_SERVICEPROVIDER_DEFAULT             = 1;
    public static final int VIX_SERVICEPROVIDER_VMWARE_SERVER       = 2;
    public static final int VIX_SERVICEPROVIDER_VMWARE_WORKSTATION  = 3;
    public static final int VIX_INVALID_HANDLE                      = 0;
    public static final int VIX_PROPERTY_NONE                       = 0;
    public static final int VIX_PROPERTY_JOB_RESULT_HANDLE          = 3010;
    public static final int VIX_VMPOWEROP_NORMAL                    = 0;
    public static final int VIX_VMPOWEROP_SUPPRESS_SNAPSHOT_POWERON = 0x0080;
    public static final int VIX_VMPOWEROP_LAUNCH_GUI                = 0x0200;

    public static final long VIX_OK                                 = 0;
    
}

The code has almost been a straight port from C. Run the Java code with the C:\Program Files\VMware\VMware VIX\ws-3\32bit set as the current directory to ensure that the dependent dlls of vix.dll can be loaded. Optionally, copy the vix dlls to the directory from which the Java code is running, or place them in the java.library.path.


Warning: Access denied for user: 'dbo211916462@%' to database 'db211916462' query: INSERT INTO watchdog (uid, type, message, severity, link, location, referer, hostname, timestamp) VALUES (0, 'php', '<em>Access denied for user: &amp;#039;dbo211916462@%&amp;#039; to database &amp;#039;db211916462&amp;#039;\nquery: INSERT INTO accesslog (title, path, url, hostname, uid, sid, timer, timestamp) values(&amp;#039;Calling VMware VIX API from Java&amp;#039;, &amp;#039;node/58&amp;#039;, &amp;#039;&amp;#039;, &amp;#039;38.107.191.111&amp;#039;, 0, &amp;#039;943b14022beb766d6f911266c5b2b3ff&amp;#039;, 279, 1283597531)</em> in <em>/homepages/34/d211454162/htdocs/JInvokeDrupal/includes/database.mysql.inc</em> on line <em>172</em>.', 2, '', 'http://www.jinvoke.com/Vmware-VIX-API-from-Java', '', '38.107.191.111', 1283597531) in /homepages/34/d211454162/htdocs/JInvokeDrupal/includes/database.mysql.inc on line 172

Warning: Access denied for user: 'dbo211916462@%' to database 'db211916462' query: INSERT INTO watchdog (uid, type, message, severity, link, location, referer, hostname, timestamp) VALUES (0, 'php', '<em>Access denied for user: &amp;#039;dbo211916462@%&amp;#039; to database &amp;#039;db211916462&amp;#039;\nquery: INSERT INTO sessions (sid, uid, cache, hostname, session, timestamp) VALUES (&amp;#039;943b14022beb766d6f911266c5b2b3ff&amp;#039;, 0, 0, &amp;#039;38.107.191.111&amp;#039;, &amp;#039;messages|a:1:{s:5:\\&amp;quot;error\\&amp;quot;;a:1:{i:0;s:458:\\&amp;quot;user warning: Access denied for user: &amp;amp;#039;dbo211916462@%&amp;amp;#039; to database &amp;amp;#039;db211916462&amp;amp;#039;\\nquery: INSERT INTO accesslog (title, path, url, hostname, uid, sid, timer, timestamp) values(&amp;amp;#039;Calling VMware VIX API from Java&amp;amp;#039;, &amp;amp;#039;node/58&amp;amp;#039;, &amp;amp in /homepages/34/d211454162/htdocs/JInvokeDrupal/includes/database.mysql.inc on line 172