How to Download File from Guest Operating System on VMware
In my last few posts I discussed how to use the Guest Operating System Management API to run program, set/read environment variables. From this post, I will talk about how to move files to and from a Guest Operating System, and advanced features like moving whole directory only implemented in the Guest Operating System Management API.
The vSphere API as of version 5.0 integrates VIX API. It provides basic APIs for downloading and uploading a file to a guest operating system. The basic idea is to use HTTPs protocol. When downloading a file from a guest operating system, the caller gets a URL which can be downloaded using GET method. You can even download it with a browser. To upload a file to a guest operating system, the caller gets a URL too, but has to be used with PUT method. How does ESXi move a file to and from a guest operating system? It’s transparent and we shouldn’t care.
There are more features provided by the vSphere API, for example, to create a temporary file, rename (in UNIX term, move) a file or directory, etc. These additional features can alternatively be implemented with running commands in the guest operating system. Again, you have to know the type of the guest operating system for a right command if you choose that way. This is really not a big deal because you have to provide operating sytem specific paths anyway.
Although the vSphere API works fine, I found it’s too low level, meaning you have to handle many details like URL, input and output stream, etc. Ideally, all that the caller should specify is: file path in a guest operating system, and local file path. That is exactly what I did in the guest operating system management API announced last week.
Let’s take a look at a sample code: (To run it, first check out the simple prerequisites in a previous post)
/*============================================================================= Copyright (c) 2012 Steve Jin, All Rights Reserved. http://www.doublecloud.org =============================================================================*/ package org.doublecloud.vi.vmware.guest.samples; import java.net.URL; import org.doublecloud.vi.vmware.guest.GuestProcessDirector; import com.vmware.vim25.mo.Folder; 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 GuestDownloadFile { 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; } VirtualMachine vm = (VirtualMachine) mes[0]; System.out.println("guest tool status:" + vm.getGuest().toolsRunningStatus); 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; } GuestFileDirector fd = new GuestFileDirector(vm, "Administrator", "vijava"); fd.downloadFile("c:\\temp\\steveproxy.jar", "C:\\temp\\steveproxy.jar"); fd.downloadDirectory("C:\\temp1\\download", "C:\\temp1\\download_dl"); si.getServerConnection().logout(); } }As you can see from the code, it downloads a file called “c:\\temp\\steveproxy.jar” (the vSphere Java code generator) in guest operating system to a local file with same name. Even better, it downloads a whole directory and its subdirectories recursively in a single call. This is not a feature in basic vSphere API but in the guest operating system management API. Note that if you archive a directory using zip/tar/gzip/7z at source and extract it at destination, the performance will be likely much better because of compression and reduced SSL session creation.
I know it could be confusing which parameter for what operating system. As a convention, the first parameter is always the source, and the second destination despite it is upload or download.

Hi Steve,
Thanks for your posting about download files/directory from the Guest OS.
I reused your codes and test in Windows platfroms (the guest OS is Windows, the machine where to run the program is also in windows platform). I have successfully downloaded the files and directory.
Then I move the program under the linux platfrom (where our scripts will be hosted), I was failed to download the directory:
java.io.IOException: Server returned HTTP response code: 500 for URL:
https://10.200.97.90:443/guestFile?id=45&token=52554745-8a6d-4d8f-b516-1458ebe439ca45
at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1612)
at
sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at java.net.URL.openStream(URL.java:1035)
at
Have you gotten any idea?
Thanks
Terry
Hi Steve,
Thanks for your posting, I reuse this codes, and test in Windows platform (The guest OS is Windows 7, the Os running the program is WinXP), it works! I successfully download the file and directory.
Then I copy the program to linux platform (where our scripts will be hosted), I am failed to download the directory, I got HTTPs 500 errors. (As it is a server side error, so I guest there are some difference between the request sends from Linux platform and Windows platform).
Have you got any idea about such issue?
Thanks,
Terry
Hi Terry,
Thanks for reporting the success and issue. For the Linux VM, did you have VMware Tools installed? It’s required.
Steve
Hi Steve,
Just when I run the program in Linux platform it will fail. (The guest OS is still Windows which has VM tools installed). Here is the exception I get:
java.io.IOException: Server returned HTTP response code: 500 for URL:
https://10.200.97.90:443/guestFile?id=45&token=52554745-8a6d-4d8f-b516-1458ebe439ca45
at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1612)
at
sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at java.net.URL.openStream(URL.java:1035)
at
Hi Steve,
Finally, I figure out the root case (sorry, I decode the vmguest.jar to peek into). When I use GuestFileDirector.uploadDirectory to upload the directory from Linux to Windows platform (download directory also has same issue), it will fail. The reason is, Linux uses “/” but windows use “\” as file separator. When uploading, I replace all the “/” in the path by “\\”, it works.
Thanks for your tool, especially vijava, it is so great that help us to build our test tool very smoothly.
-Terry
Thanks for sharing your trick with the community Terry!
-Steve