Want to vMotion a VM from one vCenter server to another vCenter using vSphere API?

As part of one of customers case, I was testing vMotion across two 6.0 vCenter servers those are connected to the same SSO domain. As we know already, when 2 vCenter servers are connected to the same SSO domain, you can manage both VCs using web client. Initially I tested vMotion from web client and later in order to automate bulk VMs migration across vCenter, I was looking for vSphere APIs and I could find below 2 vSphere APIs.

1. RelocateVM_Task() under VirtualMachine Managed object
2. placevm() under ClusterComputeResource managed object

I went through above vSphere API reference and I could see RelocateVM_Task() API was already there. However, in vSphere 6.0, it is improved greatly in order to support vMotion between 2 vCenters. On the other hand, placeVM() API was new brand API introduced in vSphere 6.0. Initially, I decided to try RelocateVM_Task() API for automating vMotion across 2 vCenters with same SSO domain. After automating this, I tested my java SDK script on vCenters with same SSO domain and it worked with no any issues. Later, I just thought lets give a try across vCenters those are connected to the different SSO domains and to my surprise, it worked like charm. is it not super cool? How easy it is now to migrate your workloads across data-centers/VCs/Clusters!.

So vMotion between 2 completely different vCenter is supported in vSphere 6.0 but there is NO UI support from web client at the moment. If you want to this functionality i.e. vMotion between 2 VCs with different SSO domains. vSphere API is the only way.

After successful vMotion across different SSO domains, I was really excited and thought to play with this little more by creating a DRS cluster in both VCs. I created a VM-VM affinity rule with couple of VMs in DRS cluster in VC1 as shown in below screenshot.


Now I initiated vMotion from first VC to DRS cluster in second VC using same Java SDK script and I could see the DRS rule associated the migrated VM also got migrated as shown in below screen shot. How cool is that!


Below is the complete code sample which can help you quickly to vMotion from a VC to other VC.

Note that this sample works fine with VCs with same SSO or VCs with different SSO. You do not even need to have shared storage between both VCs. This script will work fine within the same VC as well (with some change).

Same script is available on my git hub repository: ExVC_vMotion.java

[java]<code lang="java">
//:: # Author: Vikas Shitole
//:: # Website: www.vThinkBeyondVM.com
//:: # Product/Feature: vCenter Server/DRS/vMotion
//:: # Description: Extended Cross VC vMotion using RelocateVM_Task() API. vMotion between vCenters (with same SSO domain or different SSO domain)</code>

package com.vmware.yavijava;

import java.net.MalformedURLException;
import java.net.URL;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ServiceLocator;
import com.vmware.vim25.ServiceLocatorCredential;
import com.vmware.vim25.ServiceLocatorNamePassword;
import com.vmware.vim25.VirtualDevice;
import com.vmware.vim25.VirtualDeviceConfigSpec;
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
import com.vmware.vim25.VirtualDeviceDeviceBackingInfo;
import com.vmware.vim25.VirtualEthernetCard;
import com.vmware.vim25.VirtualMachineMovePriority;
import com.vmware.vim25.VirtualMachineRelocateSpec;
import com.vmware.vim25.mo.ClusterComputeResource;
import com.vmware.vim25.mo.Datastore;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;

public class ExVC_vMotion {

public static void main(String[] args) throws Exception {
//Parameters you need to pass
System.out.println("Usage: ExVC_vMotion srcVCIP srcVCusername srcVCpassword destVCIP destVCusername destVCpassword destHostIP");

URL url1 = null;
url1 = new URL("https://"+args[0]+"/sdk");
} catch ( MalformedURLException urlE)
System.out.println("The URL provided is NOT valid. Please check it.");

String srcusername = args[1];
String srcpassword = args[2];
String DestVC=args[3];
String destusername=args[4];
String destpassword = args[5];
String destvmhost=args[6];

//Hardcoded parameters for simplification
String vmName="VM1"; //VM name to be migrated
String vmNetworkName="VM Network"; //destination vSphere VM port group name where VM will be migrated
String destClusterName="ClusterVC2"; //Destination VC cluster where VM will be migrated
String destdatastoreName="DS1"; //destination datastore where VM will be migrated
String destVCThumpPrint="c7:bc:0c:a3:15:35:57:bd:fe:ac:60:bf:87:25:1c:07:a9:31:50:85"; //SSL Thumbprint (SHA1) of the destination VC

// Initialize source VC
ServiceInstance vc1si = new ServiceInstance(url1, srcusername,
srcpassword, true);
URL url2 = null;
url2 = new URL("https://"+DestVC+"/sdk");
} catch ( MalformedURLException urlE)
System.out.println("The URL provided is NOT valid. Please check it.");

// Initialize destination VC

ServiceInstance vc2si = new ServiceInstance(url2, destusername,
destpassword, true);
Folder vc1rootFolder = vc1si.getRootFolder();
Folder vc2rootFolder = vc2si.getRootFolder();

//Virtual Machine Object to be migrated
VirtualMachine vm = null;
vm = (VirtualMachine) new InventoryNavigator(vc1rootFolder)
.searchManagedEntity("VirtualMachine", vmName);

//Destination host object where VM will be migrated
HostSystem host = null;
host = (HostSystem) new InventoryNavigator(vc2rootFolder)
.searchManagedEntity("HostSystem", destvmhost);
ManagedObjectReference hostMor=host.getMOR();

//Destination cluster object creation
ClusterComputeResource cluster = null;
cluster = (ClusterComputeResource) new InventoryNavigator(vc2rootFolder)
.searchManagedEntity("ClusterComputeResource", destClusterName);

//Destination datastore object creation
Datastore ds=null;
ds = (Datastore) new InventoryNavigator(vc2rootFolder)
.searchManagedEntity("Datastore", destdatastoreName);
ManagedObjectReference dsMor=ds.getMOR();

VirtualMachineRelocateSpec vmSpec=new VirtualMachineRelocateSpec();

//VM device spec for the VM to be migrated
VirtualDeviceConfigSpec vdcSpec=new VirtualDeviceConfigSpec();
VirtualDevice[] devices= vm.getConfig().getHardware().getDevice();
for(VirtualDevice device:devices){

if(device instanceof VirtualEthernetCard){

VirtualDeviceDeviceBackingInfo vddBackingInfo= (VirtualDeviceDeviceBackingInfo) device.getBacking();


VirtualDeviceConfigSpec[] vDeviceConSpec={vdcSpec};

//Below is code for ServiceLOcator which is key for this vMotion happen
ServiceLocator serviceLoc=new ServiceLocator();
ServiceLocatorCredential credential=new ServiceLocatorNamePassword();
((ServiceLocatorNamePassword) credential).setPassword(destpassword);
((ServiceLocatorNamePassword) credential).setUsername(destusername);

String instanceUuid=vc2si.getServiceContent().getAbout().getInstanceUuid();
System.out.println("VM relocation started….please wait");
boolean flag=false;
vm.relocateVM_Task(vmSpec, VirtualMachineMovePriority.highPriority);
System.out.println("VM is relocated to 2nd vCenter server");


– There is one imp parameter you need to pass into migration spec i.e. Destination VC Thumbprint. There are several ways to get it as shown here. I personally used below way to get the destination VC thumbprint.
From google chrome browser : URL box of the VC (besides https:// lock symbol)>>view site information >> Certificate information >> Details >> Scroll down till last as shown in below screenshot


– For the sake of simplicity, I have hard-coded some parameters, you can change it based on your environment.
– You can scale the same code to vMotion multiple VMs across vCenter server
– As I said, there is another API for vMotion across VCs, please take a look at this post on  placevm()

If you want to automate the same use case using PowerCLI, here is great post by William Lam.

If you have still not setup your YAVI JAVA Eclipse environment:Getting started tutorial

Important tutorials to start with: Part I & Part II