Home > vSphere API > How to Import and Export OVF Packages

How to Import and Export OVF Packages

This article is based on a similar one at vSphere Java API home page. At that time, one of VMware community members sent me an email for samples of using OvfManager APIs. Then I went to office on a Saturday writing two samples, which have been validated by several folks as “working” samples.

The purpose of the samples are to illustrate the vSphere APIs. Let’s take a look at them one by one.

First, ExportOvfToLocal.java. This sample shows how to download either a VM or vApp to your local machine. The typical flow is:

  • Find the VM or vApp
  • Call their exportVm() or exportVApp() methods and get HttpNfcLease
  • Set lease time out
  • Wait for HttpNfcLease until it’s ready
  • From the HttpNfcLease.info property, find the all URLs from which you download the vmdk files
  • Call OvfManager.createDescriptor() API to create the content of ovf and save it to a file along with downloaded vmdk files.
  • Release the lease by calling httpNfcLeaseComplete() method
/*================================================================================
Copyright (c) 2008 VMware, Inc. All Rights Reserved.
<pre>Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

 * Neither the name of VMware, Inc. nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior
written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
================================================================================*/
package com.vmware.vim25.mo.samples.ovf;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

import com.vmware.vim25.HttpNfcLeaseDeviceUrl;
import com.vmware.vim25.HttpNfcLeaseInfo;
import com.vmware.vim25.HttpNfcLeaseState;
import com.vmware.vim25.OvfCreateDescriptorParams;
import com.vmware.vim25.OvfCreateDescriptorResult;
import com.vmware.vim25.OvfFile;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.HttpNfcLease;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualApp;
import com.vmware.vim25.mo.VirtualMachine;

/**
 * Exports VMDK(s) and OVF Descriptor for a VM or a vApp.
 * http://vijava.sf.net
 * @author Steve Jin (sjin at vmware.com)
 */

public class ExportOvfToLocal
{
   public static LeaseProgressUpdater leaseProgUpdater;

	 public static void main(String[] args) throws Exception
	  {
	    if (args.length != 7)
	    {
	      System.out.println("java ExportOvfToLocal <SdkUrl> <username> <password> <VappOrVmName> <hostip> <VirtualMachine|VirtualApp> <localDir>");
	      System.out.println("java ExportOvfToLocal https://10.20.152.74/sdk root password NewVM1 10.20.152.74 VirtualMachine C:\\Temp\\ovf\\");
	      return;
	    }

	    ServiceInstance si = new ServiceInstance(new URL(args[0]), args[1], args[2], true);

	    String vAppOrVmName = args[3];
	    String hostip = args[4];
	    String entityType = args[5];
	    String targetDir = args[6];

	    HostSystem host = (HostSystem) si.getSearchIndex().findByIp(null, hostip, false);

	    System.out.println("Host Name : " + host.getName());
	    System.out.println("Network : " + host.getNetworks()[0].getName());
	    System.out.println("Datastore : " + host.getDatastores()[0].getName());

	    InventoryNavigator iv = new InventoryNavigator(si.getRootFolder());

	    HttpNfcLease hnLease = null;

	    ManagedEntity me = null;
	    if (entityType.equals("VirtualApp"))
	    {
	      me = iv.searchManagedEntity("VirtualApp", vAppOrVmName);
	      hnLease = ((VirtualApp)me).exportVApp();
	    }
	    else
	    {
	      me = iv.searchManagedEntity("VirtualMachine", vAppOrVmName);
	      hnLease = ((VirtualMachine)me).exportVm();
	    }

	    // Wait until the HttpNfcLeaseState is ready
	    HttpNfcLeaseState hls;
	    for(;;)
	    {
	      hls = hnLease.getState();
	      if(hls == HttpNfcLeaseState.ready)
	      {
	        break;
	      }
	      if(hls == HttpNfcLeaseState.error)
	      {
	        si.getServerConnection().logout();
	        return;
	      }
	    }

	    System.out.println("HttpNfcLeaseState: ready ");
	    HttpNfcLeaseInfo httpNfcLeaseInfo = hnLease.getInfo();
	    httpNfcLeaseInfo.setLeaseTimeout(300*1000*1000);
	    printHttpNfcLeaseInfo(httpNfcLeaseInfo);

	    //Note: the diskCapacityInByte could be many time bigger than
	    //the total size of VMDK files downloaded.
	    //As a result, the progress calculated could be much less than reality.
	    long diskCapacityInByte = (httpNfcLeaseInfo.getTotalDiskCapacityInKB()) * 1024;

	    leaseProgUpdater = new LeaseProgressUpdater(hnLease, 5000);
	    leaseProgUpdater.start();

	    long alredyWrittenBytes = 0;
	    HttpNfcLeaseDeviceUrl[] deviceUrls = httpNfcLeaseInfo.getDeviceUrl();
	    if (deviceUrls != null)
	    {
	      OvfFile[] ovfFiles = new OvfFile[deviceUrls.length];
	      System.out.println("Downloading Files:");
	      for (int i = 0; i < deviceUrls.length; i++)
	      {
	        String deviceId = deviceUrls[i].getKey();
	        String deviceUrlStr = deviceUrls[i].getUrl();
	        String diskFileName = deviceUrlStr.substring(deviceUrlStr.lastIndexOf("/") + 1);
	        String diskUrlStr = deviceUrlStr.replace("*", hostip);
	        String diskLocalPath = targetDir + diskFileName;
	        System.out.println("File Name: " + diskFileName);
	        System.out.println("VMDK URL: " + diskUrlStr);
	        String cookie = si.getServerConnection().getVimService().getWsc().getCookie();
	        long lengthOfDiskFile = writeVMDKFile(diskLocalPath, diskUrlStr, cookie, alredyWrittenBytes, diskCapacityInByte);
	        alredyWrittenBytes += lengthOfDiskFile;
	        OvfFile ovfFile = new OvfFile();
	        ovfFile.setPath(diskFileName);
	        ovfFile.setDeviceId(deviceId);
	        ovfFile.setSize(lengthOfDiskFile);
	        ovfFiles[i] = ovfFile;
	      }

	      OvfCreateDescriptorParams ovfDescParams = new OvfCreateDescriptorParams();
	      ovfDescParams.setOvfFiles(ovfFiles);
	      OvfCreateDescriptorResult ovfCreateDescriptorResult =
	        si.getOvfManager().createDescriptor(me, ovfDescParams);

	      String ovfPath = targetDir + vAppOrVmName + ".ovf";
	      FileWriter out = new FileWriter(ovfPath);
	      out.write(ovfCreateDescriptorResult.getOvfDescriptor());
	      out.close();
	      System.out.println("OVF Desriptor Written to file: " + ovfPath);
	    }

	    System.out.println("Completed Downloading the files");
	    leaseProgUpdater.interrupt();
	    hnLease.httpNfcLeaseProgress(100);
	    hnLease.httpNfcLeaseComplete();

	    si.getServerConnection().logout();
	  }

	private static void printHttpNfcLeaseInfo(HttpNfcLeaseInfo info)
	{
		System.out.println("########################  HttpNfcLeaseInfo  ###########################");
		System.out.println("Lease Timeout: " + info.getLeaseTimeout());
		System.out.println("Total Disk capacity: "	+ info.getTotalDiskCapacityInKB());
		HttpNfcLeaseDeviceUrl[] deviceUrlArr = info.getDeviceUrl();
		if (deviceUrlArr != null)
		{
			int deviceUrlCount = 1;
			for (HttpNfcLeaseDeviceUrl durl : deviceUrlArr)
			{
				System.out.println("HttpNfcLeaseDeviceUrl : "
						+ deviceUrlCount++);
				System.out.println("	Device URL Import Key: "
						+ durl.getImportKey());
				System.out.println("	Device URL Key: " + durl.getKey());
				System.out.println("	Device URL : " + durl.getUrl());
				System.out.println("	SSL Thumbprint : "	+ durl.getSslThumbprint());
			}
		}
		else
		{
			System.out.println("No Device URLS Found");
		}
	}

	private static long writeVMDKFile(String localFilePath, String diskUrl, String cookie,
			long bytesAlreadyWritten, long totalBytes) throws IOException
	{
		HttpsURLConnection conn = getHTTPConnection(diskUrl, cookie);
		InputStream in = conn.getInputStream();
		OutputStream out = new FileOutputStream(new File(localFilePath));
		byte[] buf = new byte[102400];
		int len = 0;
		long bytesWritten = 0;
		while ((len = in.read(buf)) > 0)
		{
			out.write(buf, 0, len);
			bytesWritten += len;
			int percent = (int)(((bytesAlreadyWritten + bytesWritten) * 100) / totalBytes);
			leaseProgUpdater.setPercent(percent);
			System.out.println("written: " + bytesWritten);
		}
		in.close();
		out.close();
		return bytesWritten;
	}

	private static HttpsURLConnection getHTTPConnection(String urlStr, String cookieStr) throws IOException
	{
		HostnameVerifier hv = new HostnameVerifier()
		{
			public boolean verify(String urlHostName, SSLSession session)
			{
				return true;
			}
		};
		HttpsURLConnection.setDefaultHostnameVerifier(hv);
		URL url = new URL(urlStr);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

		conn.setDoInput(true);
		conn.setDoOutput(true);
		conn.setAllowUserInteraction(true);
		conn.setRequestProperty("Cookie",	cookieStr);
		conn.connect();
		return conn;
	}

}

Second, ImportLocalOvfVApp.java. This sample shows how to upload a VM or vApp. The flow is:

  • Read in the *.ovf file and call OvfManager().createImportSpec() method
  • From a ResoucePool, call its importVApp() method() and get HttpNfcLease object
  • Wait until the lease is ready
  • Upload the vmdk files using the URL provided by the lease object
  • Release the lease by calling httpNfcLeaseComplete() method

Note: with VI Java API 5.0 GA, remove the line “ovfDescriptor = escapeSpecialChars(ovfDescriptor);” becuase escaping is added to underlying engine.

/*================================================================================
Copyright (c) 2008 VMware, Inc. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

 * Neither the name of VMware, Inc. nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior
written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
================================================================================*/
package com.vmware.vim25.mo.samples.ovf;

import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import com.vmware.vim25.*;
import com.vmware.vim25.mo.ComputeResource;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.HttpNfcLease;
import com.vmware.vim25.mo.ResourcePool;
import com.vmware.vim25.mo.ServiceInstance;

/**
 * Deploy VM or vApp from local disk to an ESX(i) server
 * http://vijava.sf.net
 * @author Steve Jin (sjin at vmware.com)
 */

public class ImportLocalOvfVApp
{
	private static final int CHUCK_LEN = 64 * 1024;

	public static LeaseProgressUpdater leaseUpdater;

	public static void main(String[] args) throws Exception
	{
		if (args.length < 6)
		{
			System.out.println(
			"java ImportLocalOvfVApp <targetURL> <username> <password> <hostip> <OVFFile LocalPath> <NewVMName>");
			System.out.println(
			"java ImportLocalOvfVApp https://10.20.140.47/sdk Administrator password 10.17.204.115 E:/Downloads/Nostalgia.ovf NewVM");
			return;
		}

		ServiceInstance si = new ServiceInstance(new URL(args[0]), args[1], args[2], true);

		String ovfLocal = args[4];
		String hostip = args[3];
		String newVmName = args[5];

		HostSystem host = (HostSystem) si.getSearchIndex().findByIp(null, hostip, false);

		System.out.println("Host Name : " + host.getName());
		System.out.println("Network : " + host.getNetworks()[0].getName());
		System.out.println("Datastore : " + host.getDatastores()[0].getName());

		Folder vmFolder = (Folder) host.getVms()[0].getParent();

		OvfCreateImportSpecParams importSpecParams = new OvfCreateImportSpecParams();
		importSpecParams.setHostSystem(host.getMOR());
		importSpecParams.setLocale("US");
		importSpecParams.setEntityName(newVmName);
		importSpecParams.setDeploymentOption("");
		OvfNetworkMapping networkMapping = new OvfNetworkMapping();
		networkMapping.setName("Network 1");
		networkMapping.setNetwork(host.getNetworks()[0].getMOR()); // network);
		importSpecParams.setNetworkMapping(new OvfNetworkMapping[] { networkMapping });
		importSpecParams.setPropertyMapping(null);

		String ovfDescriptor = readOvfContent(ovfLocal);
		if (ovfDescriptor == null)
		{
			si.getServerConnection().logout();
			return;
		}

		ovfDescriptor = escapeSpecialChars(ovfDescriptor);
		System.out.println("ovfDesc:" + ovfDescriptor);

		ResourcePool rp = ((ComputeResource)host.getParent()).getResourcePool();

		OvfCreateImportSpecResult ovfImportResult = si.getOvfManager().createImportSpec(
				ovfDescriptor, rp, host.getDatastores()[0], importSpecParams);

		if(ovfImportResult==null)
		{
			si.getServerConnection().logout();
			return;
		}

		long totalBytes = addTotalBytes(ovfImportResult);
		System.out.println("Total bytes: " + totalBytes);

		HttpNfcLease httpNfcLease = null;

		httpNfcLease = rp.importVApp(ovfImportResult.getImportSpec(), vmFolder, host);

		// Wait until the HttpNfcLeaseState is ready
		HttpNfcLeaseState hls;
		for(;;)
		{
			hls = httpNfcLease.getState();
			if(hls == HttpNfcLeaseState.ready || hls == HttpNfcLeaseState.error)
			{
				break;
			}
		}

		if (hls.equals(HttpNfcLeaseState.ready))
		{
			System.out.println("HttpNfcLeaseState: ready ");
			HttpNfcLeaseInfo httpNfcLeaseInfo = (HttpNfcLeaseInfo) httpNfcLease.getInfo();
			printHttpNfcLeaseInfo(httpNfcLeaseInfo);

			leaseUpdater = new LeaseProgressUpdater(httpNfcLease, 5000);
			leaseUpdater.start();

			HttpNfcLeaseDeviceUrl[] deviceUrls = httpNfcLeaseInfo.getDeviceUrl();

			long bytesAlreadyWritten = 0;
			for (HttpNfcLeaseDeviceUrl deviceUrl : deviceUrls)
			{
				String deviceKey = deviceUrl.getImportKey();
				for (OvfFileItem ovfFileItem : ovfImportResult.getFileItem())
				{
					if (deviceKey.equals(ovfFileItem.getDeviceId()))
					{
						System.out.println("Import key==OvfFileItem device id: " + deviceKey);
						String absoluteFile = new File(ovfLocal).getParent() + File.separator + ovfFileItem.getPath();
						String urlToPost = deviceUrl.getUrl().replace("*", hostip);
						uploadVmdkFile(ovfFileItem.isCreate(), absoluteFile, urlToPost, bytesAlreadyWritten, totalBytes);
						bytesAlreadyWritten += ovfFileItem.getSize();
						System.out.println("Completed uploading the VMDK file:" + absoluteFile);
					}
				}
			}

			leaseUpdater.interrupt();
			httpNfcLease.httpNfcLeaseProgress(100);
			httpNfcLease.httpNfcLeaseComplete();
		}
		si.getServerConnection().logout();
	}

	public static long addTotalBytes(OvfCreateImportSpecResult ovfImportResult)
	{
		OvfFileItem[] fileItemArr = ovfImportResult.getFileItem();

		long totalBytes = 0;
		if (fileItemArr != null)
		{
			for (OvfFileItem fi : fileItemArr)
			{
				printOvfFileItem(fi);
				totalBytes += fi.getSize();
			}
		}
		return totalBytes;
	}

	private static void uploadVmdkFile(boolean put, String diskFilePath, String urlStr,
			long bytesAlreadyWritten, long totalBytes) throws IOException
	{
		HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
		{
			public boolean verify(String urlHostName, SSLSession session)
			{
				return true;
			}
		});

		HttpsURLConnection conn = (HttpsURLConnection) new URL(urlStr).openConnection();
		conn.setDoOutput(true);
		conn.setUseCaches(false);
		conn.setChunkedStreamingMode(CHUCK_LEN);
		conn.setRequestMethod(put? "PUT" : "POST"); // Use a post method to write the file.
		conn.setRequestProperty("Connection", "Keep-Alive");
		conn.setRequestProperty("Content-Type",	"application/x-vnd.vmware-streamVmdk");
		conn.setRequestProperty("Content-Length", Long.toString(new File(diskFilePath).length()));

		BufferedOutputStream bos = new BufferedOutputStream(conn.getOutputStream());

		BufferedInputStream diskis = new BufferedInputStream(new FileInputStream(diskFilePath));
		int bytesAvailable = diskis.available();
		int bufferSize = Math.min(bytesAvailable, CHUCK_LEN);
		byte[] buffer = new byte[bufferSize];

		long totalBytesWritten = 0;
		while (true)
		{
			int bytesRead = diskis.read(buffer, 0, bufferSize);
			if (bytesRead == -1)
			{
				System.out.println("Total bytes written: " + totalBytesWritten);
				break;
			}

			totalBytesWritten += bytesRead;
			bos.write(buffer, 0, bufferSize);
			bos.flush();
			System.out.println("Total bytes written: " + totalBytesWritten);
			int progressPercent = (int) (((bytesAlreadyWritten + totalBytesWritten) * 100) / totalBytes);
			leaseUpdater.setPercent(progressPercent);
		}

		diskis.close();
		bos.flush();
		bos.close();
		conn.disconnect();
	}

	public static String readOvfContent(String ovfFilePath)	throws IOException
	{
		StringBuffer strContent = new StringBuffer();
		BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(ovfFilePath)));
		String lineStr;
		while ((lineStr = in.readLine()) != null)
		{
			strContent.append(lineStr);
		}
		in.close();
		return strContent.toString();
	}

	private static void printHttpNfcLeaseInfo(HttpNfcLeaseInfo info)
	{
		System.out.println("================ HttpNfcLeaseInfo ================");
		HttpNfcLeaseDeviceUrl[] deviceUrlArr = info.getDeviceUrl();
		for (HttpNfcLeaseDeviceUrl durl : deviceUrlArr)
		{
			System.out.println("Device URL Import Key: " + durl.getImportKey());
			System.out.println("Device URL Key: " + durl.getKey());
			System.out.println("Device URL : " + durl.getUrl());
			System.out.println("Updated device URL: " + durl.getUrl());
		}
		System.out.println("Lease Timeout: " + info.getLeaseTimeout());
		System.out.println("Total Disk capacity: " + info.getTotalDiskCapacityInKB());
		System.out.println("==================================================");
	}

	private static void printOvfFileItem(OvfFileItem fi)
	{
		System.out.println("================ OvfFileItem ================");
		System.out.println("chunkSize: " + fi.getChunkSize());
		System.out.println("create: " + fi.isCreate());
		System.out.println("deviceId: " + fi.getDeviceId());
		System.out.println("path: " + fi.getPath());
		System.out.println("size: " + fi.getSize());
		System.out.println("==============================================");
	}

	public static String escapeSpecialChars(String str)
	{
		str = str.replaceAll("<", "&lt;");
		return str.replaceAll(">", "&gt;"); // do not escape "&" -> "&amp;", "\"" -> "&quot;"
	}
}

While you are downloading or uploading the files, you would also like to update the progress with the httpNfcLease.httpNfcLeaseProgress() API. This is done periodically in a separate thread with both samples. Note that the size calculation is not accurate, so you may find mismatch there.

/*================================================================================
Copyright (c) 2008 VMware, Inc. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

 * Neither the name of VMware, Inc. nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior
written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
================================================================================*/
package com.vmware.vim25.mo.samples.ovf;

import com.vmware.vim25.mo.HttpNfcLease;

/**
 * http://vijava.sf.net
 * @author Steve Jin (sjin at vmware.com)
 */

public class LeaseProgressUpdater extends Thread
{
	private HttpNfcLease httpNfcLease = null;
	private int progressPercent = 0;
	private int updateInterval;

	public LeaseProgressUpdater(HttpNfcLease httpNfcLease, int updateInterval)
	{
		this.httpNfcLease = httpNfcLease;
		this.updateInterval = updateInterval;
	}

	public void run()
	{
		while (true)
		{
			try
			{
				httpNfcLease.httpNfcLeaseProgress(progressPercent);
				Thread.sleep(updateInterval);
			}
			catch(InterruptedException ie)
			{
				break;
			}
			catch(Exception e)
			{
				throw new RuntimeException(e);
			}
		}
	}

	public void setPercent(int percent)
	{
		this.progressPercent = percent;
	}
}

You can import an OVF package from a URL using vSphere Client. How to implement it using the API? Easy. Instead of reading from a local file, you read from the URL. I leave it to you to try out.

For more details, check out the code repository. I have tested both samples in a round trip: export a VM to a local disk, and then import it back. The imported VM works well.

Marcus Ludvigson from Lawson sent me an email with a fix for unfinished upload disk file issue that happens occasionally. You need to add the following two sections of code into uploadVmdkFile() method.

conn.setDoInput(true);
try
{
  DataInputStream dis = new DataInputStream(conn.getInputStream());
  dis.close();
} catch (Exception e) {}
Categories: vSphere API Tags: ,
  1. Alan Vella
    May 17th, 2012 at 08:41 | #1

    @Steve Jin

    Hi Steve,

    After downloading the VMDKs I need to tar them up in an OVA package. Knowing the size of the VMDKs to be downloaded before I actually download them would allow me to stream the VMDKs directly into the OVA package – as opposed to downloading the VMDKs first THEN creating the OVA package. This would save me storage space and time.

    I would also like to show the progress in process of the whole operation but I can’t do this properly without knowing the size of the VMDKs to be downloaded.

    By the way, thank you for your prompt replies and well done for your excellent blog!

    Alan.

  2. Eric
    June 6th, 2012 at 11:16 | #2

    Hello Steve,

    In your example, if the ESX server doesn’t contain any VM, the result of
    Folder vmFolder = (Folder) host.getVms()[0].getParent();

    is a Null pointer exception.

    Do you know what we can do to import a OVF on a empty ESX server ? This
    is not so easy to know what to put in this Folder variable.

    If you have any idea ;-)

    Thanks for your nice article.

    Bye

  3. Rini
    June 10th, 2012 at 14:15 | #3

    I have the same issue. What did you mean by ” Invalid host system id”…
    I can print my host system’s summary info…

    Getting the same invalidtype exception… Please advice

  4. RB
    June 10th, 2012 at 16:16 | #4

    InvalidType exception went away when I replaced “US” with “en-US” in importSpecParams.setLocale(“en-US”);

    Now I am seeing the following exception: I am trying to create the VM on a cluster.

    om.vmware.vim25.InvalidHostState
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.lang.Class.newInstance0(Class.java:355)
    at java.lang.Class.newInstance(Class.java:308)
    at com.vmware.vim25.ws.XmlGen.fromXml(XmlGen.java:201)
    at com.vmware.vim25.ws.XmlGen.parseSoapFault(XmlGen.java:80)
    at com.vmware.vim25.ws.WSClient.invoke(WSClient.java:132)
    at com.vmware.vim25.ws.VimStub.createImportSpec(VimStub.java:1193)
    at com.vmware.vim25.mo.OvfManager.createImportSpec(OvfManager.java:69)

    How should i set the HostSystem?

    Right now I am doing thsi:
    importSpecParams.setHostSystem(cluster.getHosts()[0].getMOR());

    Also finding the resource pool like this:
    rp = (ResourcePool) new InventoryNavigator(
    cluster).searchManagedEntities(“ResourcePool”)[0];

    And using that pool to create the importspec:
    OvfCreateImportSpecResult ovfImportResult = si.getOvfManager().createImportSpec(
    ovfDescriptor, rp, dst, importSpecParams);

  5. Kathy
    July 8th, 2012 at 22:46 | #5

    Hi steve,

    I can download vmdk and create ovf description, but I can’t create manifest file. Do you know what’s problem with me? And how to create manifest file. Please~~~ Thanks.

  6. Deepika
    July 10th, 2012 at 01:47 | #6

    The code to import OVF works fine if my disk is a VM. What is the procedure to import a vApp? The present code says “Unsupported element VirtualSystemCollection”. How can I resolve this?
    The export class provides two methos “exportVM()” and “exportVApp()”. Isn’t there a similar thing in importing as well? like, importVApp and inportVM?

  7. Kathy
    July 11th, 2012 at 09:12 | #7

    I try to use httpNfcLeaseGetManifest to get manifest data, but it returns null. Do you know how to get manifest data? And I have a question about exporting ovf by vSphere Client, vSphere SDK, and ovftool. Which one is the fast method? If Steve know that, please kindly tell me. Thank you very much.

  8. mike
    August 28th, 2012 at 12:52 | #8

    Hi Steve,
    Is it possible to load vmdk file directly via datastore URL path (e.g. https://192.168.2.1/folder/mxue-vm-3?dcPath=MYCENTER&dsName=mystore) instead of deviceURL from HttpNfcLease? We have to set up security certificates for each ESX server host if we use deviceURL. We are hoping to do operations all through vSphere server connection (VI Instance) and that’s why we are trying loading vmdk via datastore url based on vSphere server IP. Our tests failed as the created VM gets powered on but cannot find OS. The vmdk does not seem to be really loaded though the vmdk gets loaded to datastore. Can you offer some insights or suggests?

    thanks

  9. Mahesh
    September 21st, 2012 at 08:26 | #9

    Hi Steve,

    I can import ovf file, But want to Import OVA file, I tried lot but giving following error.

    Exception in thread “main” java.rmi.RemoteException: VI SDK invoke exception:org.dom4j.DocumentException: null Nested exception: null
    at com.vmware.vim25.ws.WSClient.invoke(WSClient.java:182)
    at com.vmware.vim25.ws.WSClient.invoke(WSClient.java:124)
    at com.vmware.vim25.ws.VimStub.createImportSpec(VimStub.java:1251)
    at com.vmware.vim25.mo.OvfManager.createImportSpec(OvfManager.java:69)

    I tried it by increasing heap size while running but fails, any clue or suggestion.

    mahesh

  10. Tony Fountaine
    November 29th, 2012 at 05:31 | #10

    Hi Steve,
    We are using your code for importing an OVF into vSphere, however it is not uploading the included iso file correctly. It seems to upload fine however it appears to be a blank iso on the datastore. It works fine when importing via the VSphere Client. I have noticed that the vmdk files have create=false and the iso file has create=true. It is reporting the correct number of bytes uploaded.

  11. Tony Fountaine
    December 3rd, 2012 at 04:48 | #11

    @Tony Fountaine
    Hi All,
    I found the answer here
    Just needed to add one more line of code:
    conn.setRequestProperty(“Overwrite”, “t”);

  12. EE
    January 18th, 2013 at 04:33 | #12

    Can this be done exactly the same but only using OVA instead of OVF file?

  13. hagit
    March 8th, 2013 at 00:16 | #13

    in case you want to import ovf to an existing vapp

    need to call vapp.importVapp(ovfImportResult.getImportSpec(), null, null)

    otherwise it fail
    The SteveProxy.jar does not have a java translation to this case

    Thanks for the wonderful examples

Comment pages
1 2 767
  1. No trackbacks yet.