mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge pull request #1118 from karuturi/CLOUDSTACK-9081
CLOUDSTACK-9081 Migration of vm across clusters fails in clustered MS setupStorage motion of vm across clusters/xenserver-pools fails in a clustered management server setup. In xen storage motion we have to send a migrate_receive command to the destination host, followed by migrate_send command to the source host. The sr and network detials of the destination host have to be passed in migrate_send command on the source. While migrating across clusters the source and destination resources are seperate objects. To pass this information across resources we have to send seperate migrate with storage receive and send commands to the resource. In a clustered ms setup these commands may have to be forwarded to another ms as the resource may be owned by it. The serilization of the command and answer objects fails in such case as it doesn't understand the xapi sr and network objects. Made a change to serialize these objects in the resource layer and pass the around as strings in the command and answer objects. Reviewed-By: @likitha Author: @devdeep Tested-By: @sailajamada * pr/1118: CLOUDSTACK-9081 Migration of vm across clusters fails in clustered MS setup Signed-off-by: Remi Bergsma <github@remi.nl>
This commit is contained in:
commit
f823d06dd9
@ -26,8 +26,8 @@ import com.cloud.agent.api.to.VolumeTO;
|
||||
|
||||
public class MigrateWithStorageReceiveAnswer extends Answer {
|
||||
|
||||
Map<VolumeTO, Object> volumeToSr;
|
||||
Map<NicTO, Object> nicToNetwork;
|
||||
Map<VolumeTO, String> volumeToSr;
|
||||
Map<NicTO, String> nicToNetwork;
|
||||
Map<String, String> token;
|
||||
|
||||
public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Exception ex) {
|
||||
@ -37,7 +37,7 @@ public class MigrateWithStorageReceiveAnswer extends Answer {
|
||||
token = null;
|
||||
}
|
||||
|
||||
public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Map<VolumeTO, Object> volumeToSr, Map<NicTO, Object> nicToNetwork,
|
||||
public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Map<VolumeTO, String> volumeToSr, Map<NicTO, String> nicToNetwork,
|
||||
Map<String, String> token) {
|
||||
super(cmd, true, null);
|
||||
this.volumeToSr = volumeToSr;
|
||||
@ -45,11 +45,11 @@ public class MigrateWithStorageReceiveAnswer extends Answer {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public Map<VolumeTO, Object> getVolumeToSr() {
|
||||
public Map<VolumeTO, String> getVolumeToSr() {
|
||||
return volumeToSr;
|
||||
}
|
||||
|
||||
public Map<NicTO, Object> getNicToNetwork() {
|
||||
public Map<NicTO, String> getNicToNetwork() {
|
||||
return nicToNetwork;
|
||||
}
|
||||
|
||||
|
||||
@ -27,11 +27,11 @@ import com.cloud.agent.api.to.VolumeTO;
|
||||
|
||||
public class MigrateWithStorageSendCommand extends Command {
|
||||
VirtualMachineTO vm;
|
||||
Map<VolumeTO, Object> volumeToSr;
|
||||
Map<NicTO, Object> nicToNetwork;
|
||||
Map<VolumeTO, String> volumeToSr;
|
||||
Map<NicTO, String> nicToNetwork;
|
||||
Map<String, String> token;
|
||||
|
||||
public MigrateWithStorageSendCommand(VirtualMachineTO vm, Map<VolumeTO, Object> volumeToSr, Map<NicTO, Object> nicToNetwork, Map<String, String> token) {
|
||||
public MigrateWithStorageSendCommand(VirtualMachineTO vm, Map<VolumeTO, String> volumeToSr, Map<NicTO, String> nicToNetwork, Map<String, String> token) {
|
||||
this.vm = vm;
|
||||
this.volumeToSr = volumeToSr;
|
||||
this.nicToNetwork = nicToNetwork;
|
||||
@ -42,11 +42,11 @@ public class MigrateWithStorageSendCommand extends Command {
|
||||
return vm;
|
||||
}
|
||||
|
||||
public Map<VolumeTO, Object> getVolumeToSr() {
|
||||
public Map<VolumeTO, String> getVolumeToSr() {
|
||||
return volumeToSr;
|
||||
}
|
||||
|
||||
public Map<NicTO, Object> getNicToNetwork() {
|
||||
public Map<NicTO, String> getNicToNetwork() {
|
||||
return nicToNetwork;
|
||||
}
|
||||
|
||||
|
||||
@ -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<VolumeTO, StorageFilerTO> 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<VolumeTO, Object> volumeToSr = new HashMap<VolumeTO, Object>();
|
||||
final Map<VolumeTO, String> volumeToSr = new HashMap<VolumeTO, String>();
|
||||
for (final Map.Entry<VolumeTO, StorageFilerTO> 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<NicTO, Object> nicToNetwork = new HashMap<NicTO, Object>();
|
||||
final Map<NicTO, String> nicToNetwork = new HashMap<NicTO, String>();
|
||||
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);
|
||||
|
||||
@ -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<VolumeTO, Object> volumeToSr = command.getVolumeToSr();
|
||||
final Map<NicTO, Object> nicToNetwork = command.getNicToNetwork();
|
||||
final Map<VolumeTO, String> volumeToSr = command.getVolumeToSr();
|
||||
final Map<NicTO, String> nicToNetwork = command.getNicToNetwork();
|
||||
final Map<String, String> 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<String, String> other = new HashMap<String, String>();
|
||||
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<VDI, SR> vdiMap = new HashMap<VDI, SR>();
|
||||
for (final Map.Entry<VolumeTO, Object> 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<VolumeTO, String> 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<VM> vms = VM.getByNameLabel(connection, vmSpec.getName());
|
||||
@ -88,16 +92,10 @@ public final class XenServer610MigrateWithStorageSendCommandWrapper extends Comm
|
||||
|
||||
// Create the vif map.
|
||||
final Map<VIF, Network> vifMap = new HashMap<VIF, Network>();
|
||||
for (final Map.Entry<NicTO, Object> 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<NicTO, String> 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.
|
||||
|
||||
@ -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<VolumeTO, Object> volumeToSr = new HashMap<VolumeTO, Object>();
|
||||
volumeToSr.put(volume1, sr1);
|
||||
volumeToSr.put(volume2, sr2);
|
||||
final Map<VolumeTO, String> volumeToSr = new HashMap<VolumeTO, String>();
|
||||
Gson gson = new Gson();
|
||||
volumeToSr.put(volume1, gson.toJson(sr1));
|
||||
volumeToSr.put(volume2, gson.toJson(sr2));
|
||||
|
||||
final Map<NicTO, Object> nicToNetwork = new HashMap<NicTO, Object>();
|
||||
nicToNetwork.put(nic1, network1);
|
||||
nicToNetwork.put(nic2, network2);
|
||||
final Map<NicTO, String> nicToNetwork = new HashMap<NicTO, String>();
|
||||
nicToNetwork.put(nic1, gson.toJson(network1));
|
||||
nicToNetwork.put(nic2, gson.toJson(network2));
|
||||
|
||||
final Map<String, String> token = new HashMap<String, String>();
|
||||
|
||||
@ -366,11 +368,11 @@ public class XenServer610WrapperTest {
|
||||
final VolumeTO volume1 = Mockito.mock(VolumeTO.class);
|
||||
final VolumeTO volume2 = Mockito.mock(VolumeTO.class);
|
||||
|
||||
final Map<VolumeTO, Object> volumeToSr = new HashMap<VolumeTO, Object>();
|
||||
volumeToSr.put(volume1, new String("a"));
|
||||
volumeToSr.put(volume2, new String("b"));
|
||||
final Map<VolumeTO, String> volumeToSr = new HashMap<VolumeTO, String>();
|
||||
volumeToSr.put(volume1, "a");
|
||||
volumeToSr.put(volume2, "b");
|
||||
|
||||
final Map<NicTO, Object> nicToNetwork = new HashMap<NicTO, Object>();
|
||||
final Map<NicTO, String> nicToNetwork = new HashMap<NicTO, String>();
|
||||
final Map<String, String> token = new HashMap<String, String>();
|
||||
|
||||
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<VolumeTO, Object> volumeToSr = new HashMap<VolumeTO, Object>();
|
||||
volumeToSr.put(volume1, sr1);
|
||||
volumeToSr.put(volume2, sr2);
|
||||
Gson gson = new Gson();
|
||||
final Map<VolumeTO, String> volumeToSr = new HashMap<VolumeTO, String>();
|
||||
volumeToSr.put(volume1, gson.toJson(sr1));
|
||||
volumeToSr.put(volume2, gson.toJson(sr2));
|
||||
|
||||
final Map<NicTO, Object> nicToNetwork = new HashMap<NicTO, Object>();
|
||||
nicToNetwork.put(nic1, new String("a"));
|
||||
nicToNetwork.put(nic2, new String("b"));
|
||||
final Map<NicTO, String> nicToNetwork = new HashMap<NicTO, String>();
|
||||
nicToNetwork.put(nic1, "a");
|
||||
nicToNetwork.put(nic2, "b");
|
||||
|
||||
final Map<String, String> token = new HashMap<String, String>();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user