restrict pre and post migration commands to only kvm hosts where vm has CLVM/CLVM-NG volumes

This commit is contained in:
Pearl Dsilva 2026-03-30 15:15:37 -04:00
parent 93782bb5f1
commit f84a507224
2 changed files with 48 additions and 45 deletions

View File

@ -3116,21 +3116,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final VirtualMachineTO to = toVmTO(profile);
logger.info("Sending PreMigrationCommand to source host {} for VM {}", srcHostId, vm.getInstanceName());
final PreMigrationCommand preMigCmd = new PreMigrationCommand(to, vm.getInstanceName());
Answer preMigAnswer = null;
try {
preMigAnswer = _agentMgr.send(srcHostId, preMigCmd);
if (preMigAnswer == null || !preMigAnswer.getResult()) {
final String details = preMigAnswer != null ? preMigAnswer.getDetails() : "null answer returned";
final String msg = "Failed to prepare source host for migration: " + details;
logger.error("Failed to prepare source host {} for migration of VM {}: {}", srcHostId, vm.getInstanceName(), details);
throw new CloudRuntimeException(msg);
}
logger.info("Successfully prepared source host {} for migration of VM {}", srcHostId, vm.getInstanceName());
} catch (final AgentUnavailableException | OperationTimedoutException e) {
logger.error("Failed to send PreMigrationCommand to source host {}: {}", srcHostId, e.getMessage(), e);
throw new CloudRuntimeException("Failed to prepare source host for migration: " + e.getMessage(), e);
if (vm.getHypervisorType() == HypervisorType.KVM && hasClvmVolumes(vm.getId())) {
executePreMigrationCommand(to, vm.getInstanceName(), srcHostId);
}
final PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
@ -3264,21 +3251,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
logger.warn("Error while checking the vm {} on host {}", vm, dest.getHost(), e);
}
migrated = true;
try {
logger.info("Executing post-migration tasks for VM {} on destination host {}", vm.getInstanceName(), dstHostId);
final PostMigrationCommand postMigrationCommand = new PostMigrationCommand(to, vm.getInstanceName());
final Answer postMigrationAnswer = _agentMgr.send(dstHostId, postMigrationCommand);
if (vm.getHypervisorType() == HypervisorType.KVM && hasClvmVolumes(vm.getId())) {
try {
logger.info("Executing post-migration tasks for VM {} with CLVM volumes on destination host {}", vm.getInstanceName(), dstHostId);
final PostMigrationCommand postMigrationCommand = new PostMigrationCommand(to, vm.getInstanceName());
final Answer postMigrationAnswer = _agentMgr.send(dstHostId, postMigrationCommand);
if (postMigrationAnswer == null || !postMigrationAnswer.getResult()) {
final String details = postMigrationAnswer != null ? postMigrationAnswer.getDetails() : "null answer returned";
logger.warn("Post-migration tasks failed for VM {} on destination host {}: {}. Migration completed but some cleanup may be needed.",
vm.getInstanceName(), dstHostId, details);
} else {
logger.info("Successfully completed post-migration tasks for VM {} on destination host {}", vm.getInstanceName(), dstHostId);
if (postMigrationAnswer == null || !postMigrationAnswer.getResult()) {
final String details = postMigrationAnswer != null ? postMigrationAnswer.getDetails() : "null answer returned";
logger.warn("Post-migration tasks failed for VM {} on destination host {}: {}. Migration completed but some cleanup may be needed.",
vm.getInstanceName(), dstHostId, details);
} else {
logger.info("Successfully completed post-migration tasks for VM {} on destination host {}", vm.getInstanceName(), dstHostId);
}
} catch (Exception e) {
logger.warn("Exception during post-migration tasks for VM {} on destination host {}: {}. Migration completed but some cleanup may be needed.",
vm.getInstanceName(), dstHostId, e.getMessage(), e);
}
} catch (Exception e) {
logger.warn("Exception during post-migration tasks for VM {} on destination host {}: {}. Migration completed but some cleanup may be needed.",
vm.getInstanceName(), dstHostId, e.getMessage(), e);
}
updateClvmLockHostForVmVolumes(vm.getId(), dstHostId);
@ -4965,21 +4954,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
// Step 1: Send PreMigrationCommand to source host to convert CLVM volumes to shared mode
// This must happen BEFORE PrepareForMigrationCommand on destination to avoid lock conflicts
logger.info("Sending PreMigrationCommand to source host {} for VM {}", srcHostId, vm.getInstanceName());
final PreMigrationCommand preMigCmd = new PreMigrationCommand(to, vm.getInstanceName());
Answer preMigAnswer = null;
try {
preMigAnswer = _agentMgr.send(srcHostId, preMigCmd);
if (preMigAnswer == null || !preMigAnswer.getResult()) {
final String details = preMigAnswer != null ? preMigAnswer.getDetails() : "null answer returned";
final String msg = "Failed to prepare source host for migration: " + details;
logger.error("Failed to prepare source host {} for migration of VM {}: {}", srcHostId, vm.getInstanceName(), details);
throw new CloudRuntimeException(msg);
}
logger.info("Successfully prepared source host {} for migration of VM {}", srcHostId, vm.getInstanceName());
} catch (final AgentUnavailableException | OperationTimedoutException e) {
logger.error("Failed to send PreMigrationCommand to source host {}: {}", srcHostId, e.getMessage(), e);
throw new CloudRuntimeException("Failed to prepare source host for migration: " + e.getMessage(), e);
if (vm.getHypervisorType() == HypervisorType.KVM && hasClvmVolumes(vm.getId())) {
executePreMigrationCommand(to, vm.getInstanceName(), srcHostId);
}
// Step 2: Send PrepareForMigrationCommand to destination host
@ -6406,6 +6382,32 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
return findClusterAndHostIdForVm(vm, false);
}
private boolean hasClvmVolumes(long vmId) {
List<VolumeVO> volumes = _volsDao.findByInstance(vmId);
return volumes.stream()
.map(v -> _storagePoolDao.findById(v.getPoolId()))
.anyMatch(pool -> pool != null && ClvmLockManager.isClvmPoolType(pool.getPoolType()));
}
private void executePreMigrationCommand(VirtualMachineTO to, String vmInstanceName, long srcHostId) {
logger.info("Sending PreMigrationCommand to source host {} for VM {} with CLVM volumes", srcHostId, vmInstanceName);
final PreMigrationCommand preMigCmd = new PreMigrationCommand(to, vmInstanceName);
Answer preMigAnswer = null;
try {
preMigAnswer = _agentMgr.send(srcHostId, preMigCmd);
if (preMigAnswer == null || !preMigAnswer.getResult()) {
final String details = preMigAnswer != null ? preMigAnswer.getDetails() : "null answer returned";
final String msg = "Failed to prepare source host for migration: " + details;
logger.error("Failed to prepare source host {} for migration of VM {}: {}", srcHostId, vmInstanceName, details);
throw new CloudRuntimeException(msg);
}
logger.info("Successfully prepared source host {} for migration of VM {}", srcHostId, vmInstanceName);
} catch (final AgentUnavailableException | OperationTimedoutException e) {
logger.error("Failed to send PreMigrationCommand to source host {}: {}", srcHostId, e.getMessage(), e);
throw new CloudRuntimeException("Failed to prepare source host for migration: " + e.getMessage(), e);
}
}
@Override
public Pair<Long, Long> findClusterAndHostIdForVm(long vmId) {
VMInstanceVO vm = _vmDao.findById(vmId);

View File

@ -2233,8 +2233,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
boolean hasClvmSource = volumeDataStoreMap.keySet().stream()
.map(v -> _storagePoolDao.findById(v.getPoolId()))
.anyMatch(p -> p != null && (p.getPoolType() == StoragePoolType.CLVM || p.getPoolType() == StoragePoolType.CLVM_NG));
if (hasClvmSource) {
if (hasClvmSource && srcHost.getHypervisorType() == HypervisorType.KVM) {
logger.info("CLVM/CLVM_NG source pool detected for VM [{}], sending PreMigrationCommand to source host [{}] to convert volumes to shared mode.", vmTO.getName(), srcHost.getId());
PreMigrationCommand preMigCmd = new PreMigrationCommand(vmTO, vmTO.getName());
try {
@ -2248,6 +2247,8 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
} catch (Exception e) {
logger.warn("Failed to send PreMigrationCommand to source host [{}] for VM [{}]: {}. Migration will continue but may fail if volumes are exclusively locked.", srcHost.getId(), vmTO.getName(), e.getMessage());
}
} else if (hasClvmSource) {
logger.debug("Skipping PreMigrationCommand for non-KVM hypervisor type: {} on host [{}]", srcHost.getHypervisorType(), srcHost.getId());
}
}