diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java b/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java index 37d43124235..694e7642858 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java @@ -26,8 +26,8 @@ import com.cloud.agent.api.to.VolumeTO; public class MigrateWithStorageReceiveAnswer extends Answer { - Map volumeToSr; - Map nicToNetwork; + Map volumeToSr; + Map nicToNetwork; Map token; public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Exception ex) { @@ -37,7 +37,7 @@ public class MigrateWithStorageReceiveAnswer extends Answer { token = null; } - public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Map volumeToSr, Map nicToNetwork, + public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Map volumeToSr, Map nicToNetwork, Map token) { super(cmd, true, null); this.volumeToSr = volumeToSr; @@ -45,11 +45,11 @@ public class MigrateWithStorageReceiveAnswer extends Answer { this.token = token; } - public Map getVolumeToSr() { + public Map getVolumeToSr() { return volumeToSr; } - public Map getNicToNetwork() { + public Map getNicToNetwork() { return nicToNetwork; } diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java b/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java index 47a09c83630..3c703ca695f 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java @@ -27,11 +27,11 @@ import com.cloud.agent.api.to.VolumeTO; public class MigrateWithStorageSendCommand extends Command { VirtualMachineTO vm; - Map volumeToSr; - Map nicToNetwork; + Map volumeToSr; + Map nicToNetwork; Map token; - public MigrateWithStorageSendCommand(VirtualMachineTO vm, Map volumeToSr, Map nicToNetwork, Map token) { + public MigrateWithStorageSendCommand(VirtualMachineTO vm, Map volumeToSr, Map nicToNetwork, Map token) { this.vm = vm; this.volumeToSr = volumeToSr; this.nicToNetwork = nicToNetwork; @@ -42,11 +42,11 @@ public class MigrateWithStorageSendCommand extends Command { return vm; } - public Map getVolumeToSr() { + public Map getVolumeToSr() { return volumeToSr; } - public Map getNicToNetwork() { + public Map getNicToNetwork() { return nicToNetwork; } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java index 68814ef39c4..a377a80774e 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java @@ -22,6 +22,7 @@ package com.cloud.hypervisor.xenserver.resource.wrapper.xen610; import java.util.HashMap; import java.util.Map; +import com.google.gson.Gson; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -55,19 +56,28 @@ public final class XenServer610MigrateWithStorageReceiveCommandWrapper extends C final Map volumeToFiler = command.getVolumeToFiler(); try { + // In a cluster management server setup, the migrate with storage receive and send + // commands and answers may have to be forwarded to another management server. This + // happens when the host/resource on which the command has to be executed is owned + // by the second management server. The serialization/deserialization of the command + // and answers fails as the xapi SR and Network class type isn't understand by the + // agent attache. Seriliaze the SR and Network objects here to a string and pass in + // the answer object. It'll be deserialzed and object created in migrate with + // storage send command execution. + Gson gson = new Gson(); // Get a map of all the SRs to which the vdis will be migrated. - final Map volumeToSr = new HashMap(); + final Map volumeToSr = new HashMap(); for (final Map.Entry entry : volumeToFiler.entrySet()) { final StorageFilerTO storageFiler = entry.getValue(); final SR sr = xenServer610Resource.getStorageRepository(connection, storageFiler.getUuid()); - volumeToSr.put(entry.getKey(), sr); + volumeToSr.put(entry.getKey(), gson.toJson(sr)); } // Get the list of networks to which the vifs will attach. - final Map nicToNetwork = new HashMap(); + final Map nicToNetwork = new HashMap(); for (final NicTO nicTo : vmSpec.getNics()) { final Network network = xenServer610Resource.getNetwork(connection, nicTo); - nicToNetwork.put(nicTo, network); + nicToNetwork.put(nicTo, gson.toJson(network)); } final XsLocalNetwork nativeNetworkForTraffic = xenServer610Resource.getNativeNetworkForTraffic(connection, TrafficType.Storage, null); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java index 6d4afde3a96..616660964e5 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import com.google.gson.Gson; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -54,30 +55,33 @@ public final class XenServer610MigrateWithStorageSendCommandWrapper extends Comm final Connection connection = xenServer610Resource.getConnection(); final VirtualMachineTO vmSpec = command.getVirtualMachine(); - final Map volumeToSr = command.getVolumeToSr(); - final Map nicToNetwork = command.getNicToNetwork(); + final Map volumeToSr = command.getVolumeToSr(); + final Map nicToNetwork = command.getNicToNetwork(); final Map token = command.getToken(); final String vmName = vmSpec.getName(); Task task = null; try { + // In a cluster management server setup, the migrate with storage receive and send + // commands and answers may have to be forwarded to another management server. This + // happens when the host/resource on which the command has to be executed is owned + // by the second management server. The serialization/deserialization of the command + // and answers fails as the xapi SR and Network class type isn't understand by the + // agent attache. Seriliaze the SR and Network objects here to a string and pass in + // the answer object. It'll be deserialzed and object created in migrate with + // storage send command execution. + Gson gson = new Gson(); final Map other = new HashMap(); other.put("live", "true"); // Create the vdi map which tells what volumes of the vm need to go // on which sr on the destination. final Map vdiMap = new HashMap(); - for (final Map.Entry entry : volumeToSr.entrySet()) { - final Object srObj = entry.getValue(); - if (srObj instanceof SR) { - final SR sr = (SR) srObj; - final VolumeTO volume = entry.getKey(); - final VDI vdi = xenServer610Resource.getVDIbyUuid(connection, volume.getPath()); - vdiMap.put(vdi, sr); - } else { - throw new CloudRuntimeException("The object " + srObj + " passed is not of type SR."); - } + for (final Map.Entry entry : volumeToSr.entrySet()) { + SR sr = gson.fromJson(entry.getValue(), SR.class); + VDI vdi = xenServer610Resource.getVDIbyUuid(connection, entry.getKey().getPath()); + vdiMap.put(vdi, sr); } final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); @@ -88,16 +92,10 @@ public final class XenServer610MigrateWithStorageSendCommandWrapper extends Comm // Create the vif map. final Map vifMap = new HashMap(); - for (final Map.Entry entry : nicToNetwork.entrySet()) { - final Object networkObj = entry.getValue(); - if (networkObj instanceof Network) { - final Network network = (Network) networkObj; - final NicTO nic = entry.getKey(); - final VIF vif = xenServer610Resource.getVifByMac(connection, vmToMigrate, nic.getMac()); - vifMap.put(vif, network); - } else { - throw new CloudRuntimeException("The object " + networkObj + " passed is not of type Network."); - } + for (final Map.Entry entry : nicToNetwork.entrySet()) { + Network network = gson.fromJson(entry.getValue(), Network.class); + VIF vif = xenServer610Resource.getVifByMac(connection, vmToMigrate, entry.getKey().getMac()); + vifMap.put(vif, network); } // Check migration with storage is possible. diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java index 70ddfad0a80..d5177da02a1 100644 --- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.google.gson.Gson; import org.apache.xmlrpc.XmlRpcException; import org.junit.Test; import org.junit.runner.RunWith; @@ -301,13 +302,14 @@ public class XenServer610WrapperTest { final Network network1 = Mockito.mock(Network.class); final Network network2 = Mockito.mock(Network.class); - final Map volumeToSr = new HashMap(); - volumeToSr.put(volume1, sr1); - volumeToSr.put(volume2, sr2); + final Map volumeToSr = new HashMap(); + Gson gson = new Gson(); + volumeToSr.put(volume1, gson.toJson(sr1)); + volumeToSr.put(volume2, gson.toJson(sr2)); - final Map nicToNetwork = new HashMap(); - nicToNetwork.put(nic1, network1); - nicToNetwork.put(nic2, network2); + final Map nicToNetwork = new HashMap(); + nicToNetwork.put(nic1, gson.toJson(network1)); + nicToNetwork.put(nic2, gson.toJson(network2)); final Map token = new HashMap(); @@ -366,11 +368,11 @@ public class XenServer610WrapperTest { final VolumeTO volume1 = Mockito.mock(VolumeTO.class); final VolumeTO volume2 = Mockito.mock(VolumeTO.class); - final Map volumeToSr = new HashMap(); - volumeToSr.put(volume1, new String("a")); - volumeToSr.put(volume2, new String("b")); + final Map volumeToSr = new HashMap(); + volumeToSr.put(volume1, "a"); + volumeToSr.put(volume2, "b"); - final Map nicToNetwork = new HashMap(); + final Map nicToNetwork = new HashMap(); final Map token = new HashMap(); final MigrateWithStorageSendCommand migrateStorageCommand = new MigrateWithStorageSendCommand(vmSpec, volumeToSr, nicToNetwork, token); @@ -408,13 +410,14 @@ public class XenServer610WrapperTest { final NicTO nic1 = Mockito.mock(NicTO.class); final NicTO nic2 = Mockito.mock(NicTO.class); - final Map volumeToSr = new HashMap(); - volumeToSr.put(volume1, sr1); - volumeToSr.put(volume2, sr2); + Gson gson = new Gson(); + final Map volumeToSr = new HashMap(); + volumeToSr.put(volume1, gson.toJson(sr1)); + volumeToSr.put(volume2, gson.toJson(sr2)); - final Map nicToNetwork = new HashMap(); - nicToNetwork.put(nic1, new String("a")); - nicToNetwork.put(nic2, new String("b")); + final Map nicToNetwork = new HashMap(); + nicToNetwork.put(nic1, "a"); + nicToNetwork.put(nic2, "b"); final Map token = new HashMap();