use of com.cloud.agent.api.MigrateWithStorageSendAnswer in project cloudstack by apache.
the class XenServerStorageMotionStrategy method migrateVmWithVolumesAcrossCluster.
private Answer migrateVmWithVolumesAcrossCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost, Host destHost, Map<VolumeInfo, DataStore> volumeToPool) throws AgentUnavailableException {
try {
List<Pair<VolumeTO, String>> volumeToStorageUuid = new ArrayList<>();
for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
VolumeInfo volumeInfo = entry.getKey();
StoragePool storagePool = storagePoolDao.findById(volumeInfo.getPoolId());
VolumeTO volumeTo = new VolumeTO(volumeInfo, storagePool);
if (storagePool.isManaged()) {
String iqn = handleManagedVolumePreMigration(volumeInfo, storagePool, destHost);
volumeToStorageUuid.add(new Pair<>(volumeTo, iqn));
} else {
volumeToStorageUuid.add(new Pair<>(volumeTo, ((StoragePool) entry.getValue()).getPath()));
}
}
// Migration across cluster needs to be done in three phases.
// 1. Send a migrate receive command to the destination host so that it is ready to receive a vm.
// 2. Send a migrate send command to the source host. This actually migrates the vm to the destination.
// 3. Complete the process. Update the volume details.
MigrateWithStorageReceiveCommand receiveCmd = new MigrateWithStorageReceiveCommand(to, volumeToStorageUuid);
MigrateWithStorageReceiveAnswer receiveAnswer = (MigrateWithStorageReceiveAnswer) agentMgr.send(destHost.getId(), receiveCmd);
if (receiveAnswer == null) {
s_logger.error("Migration with storage of vm " + vm + " to host " + destHost + " failed.");
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
} else if (!receiveAnswer.getResult()) {
s_logger.error("Migration with storage of vm " + vm + " failed. Details: " + receiveAnswer.getDetails());
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
}
MigrateWithStorageSendCommand sendCmd = new MigrateWithStorageSendCommand(to, receiveAnswer.getVolumeToSr(), receiveAnswer.getNicToNetwork(), receiveAnswer.getToken());
MigrateWithStorageSendAnswer sendAnswer = (MigrateWithStorageSendAnswer) agentMgr.send(srcHost.getId(), sendCmd);
if (sendAnswer == null) {
handleManagedVolumesAfterFailedMigration(volumeToPool, destHost);
s_logger.error("Migration with storage of vm " + vm + " to host " + destHost + " failed.");
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
} else if (!sendAnswer.getResult()) {
handleManagedVolumesAfterFailedMigration(volumeToPool, destHost);
s_logger.error("Migration with storage of vm " + vm + " failed. Details: " + sendAnswer.getDetails());
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
}
MigrateWithStorageCompleteCommand command = new MigrateWithStorageCompleteCommand(to);
MigrateWithStorageCompleteAnswer answer = (MigrateWithStorageCompleteAnswer) agentMgr.send(destHost.getId(), command);
if (answer == null) {
s_logger.error("Migration with storage of vm " + vm + " failed.");
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
} else if (!answer.getResult()) {
s_logger.error("Migration with storage of vm " + vm + " failed. Details: " + answer.getDetails());
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
} else {
// Update the volume details after migration.
updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos(), srcHost);
}
return answer;
} catch (OperationTimedoutException e) {
s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e);
throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId());
}
}
use of com.cloud.agent.api.MigrateWithStorageSendAnswer in project cloudstack by apache.
the class VirtualMachineManagerImplTest method initializeMockConfigForMigratingVmWithVolumes.
private void initializeMockConfigForMigratingVmWithVolumes() throws OperationTimedoutException, ResourceUnavailableException {
// Mock the source and destination hosts.
when(_srcHostMock.getId()).thenReturn(5L);
when(_destHostMock.getId()).thenReturn(6L);
when(_hostDao.findById(5L)).thenReturn(_srcHostMock);
when(_hostDao.findById(6L)).thenReturn(_destHostMock);
// Mock the vm being migrated.
when(_vmMock.getId()).thenReturn(1L);
when(_vmMock.getHypervisorType()).thenReturn(HypervisorType.XenServer);
when(_vmMock.getState()).thenReturn(State.Running).thenReturn(State.Running).thenReturn(State.Migrating).thenReturn(State.Migrating);
when(_vmMock.getHostId()).thenReturn(5L);
when(_vmInstance.getId()).thenReturn(1L);
when(_vmInstance.getServiceOfferingId()).thenReturn(2L);
when(_vmInstance.getInstanceName()).thenReturn("myVm");
when(_vmInstance.getHostId()).thenReturn(5L);
when(_vmInstance.getType()).thenReturn(VirtualMachine.Type.User);
when(_vmInstance.getState()).thenReturn(State.Running).thenReturn(State.Running).thenReturn(State.Migrating).thenReturn(State.Migrating);
// Mock the work item.
when(_workDao.persist(any(ItWorkVO.class))).thenReturn(_work);
when(_workDao.update("1", _work)).thenReturn(true);
when(_work.getId()).thenReturn("1");
doNothing().when(_work).setStep(ItWorkVO.Step.Done);
// Mock the vm guru and the user vm object that gets returned.
_vmMgr._vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru>();
// UserVmManagerImpl userVmManager = mock(UserVmManagerImpl.class);
// _vmMgr.registerGuru(VirtualMachine.Type.User, userVmManager);
// Mock the iteration over all the volumes of an instance.
Iterator<VolumeVO> volumeIterator = mock(Iterator.class);
when(_volsDao.findUsableVolumesForInstance(anyLong())).thenReturn(_rootVols);
when(_rootVols.iterator()).thenReturn(volumeIterator);
when(volumeIterator.hasNext()).thenReturn(true, false);
when(volumeIterator.next()).thenReturn(_volumeMock);
// Mock the disk offering and pool objects for a volume.
when(_volumeMock.getDiskOfferingId()).thenReturn(5L);
when(_volumeMock.getPoolId()).thenReturn(200L);
when(_volumeMock.getId()).thenReturn(5L);
when(_diskOfferingDao.findById(anyLong())).thenReturn(_diskOfferingMock);
when(_storagePoolDao.findById(200L)).thenReturn(_srcStoragePoolMock);
when(_storagePoolDao.findById(201L)).thenReturn(_destStoragePoolMock);
// Mock the volume to pool mapping.
when(_volumeToPoolMock.get(5L)).thenReturn(201L);
when(_destStoragePoolMock.getId()).thenReturn(201L);
when(_srcStoragePoolMock.getId()).thenReturn(200L);
when(_destStoragePoolMock.isLocal()).thenReturn(false);
when(_diskOfferingMock.getUseLocalStorage()).thenReturn(false);
when(_poolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(mock(StoragePoolHostVO.class));
// Mock hypervisor guru.
HypervisorGuru guruMock = mock(HypervisorGuru.class);
when(_hvGuruMgr.getGuru(HypervisorType.XenServer)).thenReturn(guruMock);
when(_srcHostMock.getClusterId()).thenReturn(3L);
when(_destHostMock.getClusterId()).thenReturn(3L);
// Mock the commands and answers to the agent.
PrepareForMigrationAnswer prepAnswerMock = mock(PrepareForMigrationAnswer.class);
when(prepAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(PrepareForMigrationCommand.class))).thenReturn(prepAnswerMock);
MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class);
when(migAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock);
MigrateWithStorageReceiveAnswer migRecAnswerMock = mock(MigrateWithStorageReceiveAnswer.class);
when(migRecAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageReceiveCommand.class))).thenReturn(migRecAnswerMock);
MigrateWithStorageSendAnswer migSendAnswerMock = mock(MigrateWithStorageSendAnswer.class);
when(migSendAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageSendCommand.class))).thenReturn(migSendAnswerMock);
MigrateWithStorageCompleteAnswer migCompleteAnswerMock = mock(MigrateWithStorageCompleteAnswer.class);
when(migCompleteAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageCompleteCommand.class))).thenReturn(migCompleteAnswerMock);
CheckVirtualMachineAnswer checkVmAnswerMock = mock(CheckVirtualMachineAnswer.class);
when(checkVmAnswerMock.getResult()).thenReturn(true);
when(checkVmAnswerMock.getState()).thenReturn(PowerState.PowerOn);
when(_agentMgr.send(anyLong(), isA(CheckVirtualMachineCommand.class))).thenReturn(checkVmAnswerMock);
// Mock the state transitions of vm.
Pair<Long, Long> opaqueMock = new Pair<Long, Long>(_vmMock.getHostId(), _destHostMock.getId());
when(_vmSnapshotMgr.hasActiveVMSnapshotTasks(anyLong())).thenReturn(false);
when(_vmInstanceDao.updateState(State.Running, Event.MigrationRequested, State.Migrating, _vmMock, opaqueMock)).thenReturn(true);
when(_vmInstanceDao.updateState(State.Migrating, Event.OperationSucceeded, State.Running, _vmMock, opaqueMock)).thenReturn(true);
}
use of com.cloud.agent.api.MigrateWithStorageSendAnswer in project cloudstack by apache.
the class XenServer610MigrateWithStorageSendCommandWrapper method execute.
@Override
public Answer execute(final MigrateWithStorageSendCommand command, final XenServer610Resource xenServer610Resource) {
final Connection connection = xenServer610Resource.getConnection();
final VirtualMachineTO vmSpec = command.getVirtualMachine();
final List<Pair<VolumeTO, Object>> volumeToSr = command.getVolumeToSr();
final List<Pair<NicTO, Object>> 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 Pair<VolumeTO, Object> entry : volumeToSr) {
if (entry.second() instanceof SR) {
final SR sr = (SR) entry.second();
final VDI vdi = xenServer610Resource.getVDIbyUuid(connection, entry.first().getPath());
vdiMap.put(vdi, sr);
} else {
throw new CloudRuntimeException("The object " + entry.second() + " passed is not of type SR.");
}
}
final Set<VM> vms = VM.getByNameLabel(connection, vmSpec.getName());
VM vmToMigrate = null;
if (vms != null) {
vmToMigrate = vms.iterator().next();
}
// Create the vif map.
final Map<VIF, Network> vifMap = new HashMap<VIF, Network>();
for (final Pair<NicTO, Object> entry : nicToNetwork) {
if (entry.second() instanceof Network) {
final Network network = (Network) entry.second();
final VIF vif = xenServer610Resource.getVifByMac(connection, vmToMigrate, entry.first().getMac());
vifMap.put(vif, network);
} else {
throw new CloudRuntimeException("The object " + entry.second() + " passed is not of type Network.");
}
}
// Check migration with storage is possible.
task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other);
try {
// poll every 1 seconds.
final long timeout = xenServer610Resource.getMigrateWait() * 1000L;
xenServer610Resource.waitForTask(connection, task, 1000, timeout);
xenServer610Resource.checkForSuccess(connection, task);
} catch (final Types.HandleInvalid e) {
s_logger.error("Error while checking if vm " + vmName + " can be migrated.", e);
throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated.", e);
}
// Migrate now.
task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other);
try {
// poll every 1 seconds.
final long timeout = xenServer610Resource.getMigrateWait() * 1000L;
xenServer610Resource.waitForTask(connection, task, 1000, timeout);
xenServer610Resource.checkForSuccess(connection, task);
} catch (final Types.HandleInvalid e) {
s_logger.error("Error while migrating vm " + vmName, e);
throw new CloudRuntimeException("Error while migrating vm " + vmName, e);
}
final Set<VolumeTO> volumeToSet = null;
return new MigrateWithStorageSendAnswer(command, volumeToSet);
} catch (final CloudRuntimeException e) {
s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e);
return new MigrateWithStorageSendAnswer(command, e);
} catch (final Exception e) {
s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e);
return new MigrateWithStorageSendAnswer(command, e);
} finally {
if (task != null) {
try {
task.destroy(connection);
} catch (final Exception e) {
s_logger.debug("Unable to destroy task " + task.toString() + " on host " + xenServer610Resource.getHost().getUuid() + " due to " + e.toString());
}
}
}
}
Aggregations