Map<String, String> token = cmd.getToken();
final String vmName = vmSpec.getName();
State state = s_vms.getState(_cluster, vmName);
Set<VolumeTO> volumeToSet = null;
boolean migrated = false;
Task task = null;
synchronized (_cluster.intern()) {
s_vms.put(_cluster, _name, vmName, State.Stopping);
}
try {
Set<VM> vms = VM.getByNameLabel(connection, vmSpec.getName());
VM vmToMigrate = vms.iterator().next();
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.
Map<VDI, SR> vdiMap = new HashMap<VDI, SR>();
for (Map.Entry<VolumeTO, Object> entry : volumeToSr.entrySet()) {
if (entry.getValue() instanceof SR) {
SR sr = (SR)entry.getValue();
VDI vdi = getVDIbyUuid(connection, entry.getKey().getPath());
vdiMap.put(vdi, sr);
} else {
throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type SR.");
}
}
// Create the vif map.
Map<VIF, Network> vifMap = new HashMap<VIF, Network>();
for (Map.Entry<NicTO, Object> entry : nicToNetwork.entrySet()) {
if (entry.getValue() instanceof Network) {
Network network = (Network)entry.getValue();
VIF vif = getVifByMac(connection, vmToMigrate, entry.getKey().getMac());
vifMap.put(vif, network);
} else {
throw new CloudRuntimeException("The object " + entry.getValue() + " 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.
long timeout = (_migratewait) * 1000L;
waitForTask(connection, task, 1000, timeout);
checkForSuccess(connection, task);
} catch (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.
long timeout = (_migratewait) * 1000L;
waitForTask(connection, task, 1000, timeout);
checkForSuccess(connection, task);
} catch (Types.HandleInvalid e) {
s_logger.error("Error while migrating vm " + vmName, e);
throw new CloudRuntimeException("Error while migrating vm " + vmName, e);
}
migrated = true;
return new MigrateWithStorageSendAnswer(cmd, volumeToSet);
} catch (CloudRuntimeException e) {
s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e);
return new MigrateWithStorageSendAnswer(cmd, e);
} catch (Exception e) {
s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e);
return new MigrateWithStorageSendAnswer(cmd, e);
} finally {
if (task != null) {
try {
task.destroy(connection);
} catch (Exception e) {
s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.uuid +" due to " +
e.toString());
}
}
// Keep cluster/vm sync happy.