From 5c93bcf2d708b5dd5abbc19776bc1eab9e3b4b7d Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 9 Mar 2026 15:32:30 +0100 Subject: [PATCH] vmm: migration: only permit migration of running VMs Currently, it is not possible to migrate a paused VM. It fails with the following error: ``` [2026-03-09T14:43:42Z ERROR cloud_hypervisor] Fatal error: HttpApiClient(ServerResponse(InternalServerError, Some("[\"Error from API\",\"Error starting migration sender\",\"Failed to pause migratable component\",\"Invalid transition: InvalidStateTransition(Paused, Paused)\"]"))) Error: ch-remote exited with the following chain of errors: 0: http client error 1: Server responded with InternalServerError 2: Error from API 3: Error starting migration sender 4: Failed to pause migratable component 5: Invalid transition: InvalidStateTransition(Paused, Paused) ``` and even worse, after that, the VM is resumed on the source! Make the behavior explicit by only allowing migration of VMs in the Running state. This avoids unintended state transitions during migration and clarifies the current expected semantics. Future work could extend the migration protocol to work with paused VMs and preserve the VM runtime state, allowing paused VMs to be migrated without altering their state. Signed-off-by: Philipp Schuster On-behalf-of: SAP philipp.schuster@sap.com --- vmm/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index cea3d2fa4..96331fffa 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -2369,6 +2369,16 @@ impl RequestHandler for Vmm { .as_mut() .ok_or_else(|| MigratableError::MigrateSend(anyhow!("VM is not running")))?; + // Only running VMs can be migrated: Future work can fix this to allow + // also the migration of paused VMs while preserving the state in success + // and error case. See #7815. + if vm.get_state() != VmState::Running { + return Err(MigratableError::MigrateSend(anyhow!( + "VM is not in running state: {:?}", + vm.get_state() + ))); + } + Self::send_migration( vm, #[cfg(all(feature = "kvm", target_arch = "x86_64"))]