diff --git a/cloud-hypervisor/tests/common/utils.rs b/cloud-hypervisor/tests/common/utils.rs index 45a803dce..a76878f7a 100644 --- a/cloud-hypervisor/tests/common/utils.rs +++ b/cloud-hypervisor/tests/common/utils.rs @@ -1070,6 +1070,7 @@ pub(crate) fn start_live_migration( src_api_socket: &str, dest_api_socket: &str, local: bool, + paused: bool, ) -> bool { // Start to receive migration from the destination VM let mut receive_migration = Command::new(clh_command("ch-remote")) @@ -1084,8 +1085,17 @@ pub(crate) fn start_live_migration( .unwrap(); // Give it '1s' to make sure the 'migration_socket' file is properly created thread::sleep(std::time::Duration::new(1, 0)); - // Start to send migration from the source VM + if paused { + // Test the migration of a paused VM. + let cmd_success = remote_command(src_api_socket, "pause", None); + if !cmd_success { + let _ = receive_migration.kill(); + eprintln!("Failed to pause the source VM before live migration"); + } + } + + // Start to send migration from the source VM let args = [ format!("--api-socket={}", &src_api_socket), "send-migration".to_string(), @@ -1145,6 +1155,28 @@ pub(crate) fn start_live_migration( String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr) ); + } else if paused { + // for a paused VM, we should make sure the destinations VM state is still 'Paused' after + // migration. + let dest_state = vm_state(dest_api_socket); + if dest_state != "Paused" { + eprintln!( + "\n\n==== Start 'destination VM state' output ==== \ + \n\nExpected destination VM state: Paused\nActual destination VM state: {dest_state} \ + \n\n==== End 'destination VM state' output ====\n\n" + ); + return false; + } + // Resume the paused VM to make sure it still works after migration + let cmd_success = remote_command(dest_api_socket, "resume", None); + if !cmd_success { + eprintln!( + "\n\n==== Start 'destination VM state' output ==== \ + \n\nFailed to resume the destination VM after live migration \ + \n\n==== End 'destination VM state' output ====\n\n" + ); + return false; + } } send_success && receive_success diff --git a/cloud-hypervisor/tests/integration.rs b/cloud-hypervisor/tests/integration.rs index 3a7d4cd71..429a00d8e 100644 --- a/cloud-hypervisor/tests/integration.rs +++ b/cloud-hypervisor/tests/integration.rs @@ -6119,7 +6119,7 @@ mod common_parallel { // live migration; // Note: This test does not use vsock as we can't create two identical vsock on the same host. #[cfg(not(feature = "mshv"))] - fn _test_live_migration(upgrade_test: bool, local: bool) { + fn _test_live_migration(upgrade_test: bool, local: bool, paused: bool) { let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string()); let guest = Guest::new(Box::new(disk_config)); let kernel_path = direct_kernel_boot_path(); @@ -6228,7 +6228,13 @@ mod common_parallel { ); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, local), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + local, + paused + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); }); @@ -6403,7 +6409,13 @@ mod common_parallel { ); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, local), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + local, + false + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); }); @@ -6563,7 +6575,13 @@ mod common_parallel { ); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, true), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + true, + false + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); }); @@ -6995,13 +7013,25 @@ mod common_parallel { #[test] #[cfg(not(feature = "mshv"))] fn test_live_migration_basic() { - _test_live_migration(false, false); + _test_live_migration(false, false, false); } #[test] #[cfg(not(feature = "mshv"))] fn test_live_migration_local() { - _test_live_migration(false, true); + _test_live_migration(false, true, false); + } + + #[test] + #[cfg(not(feature = "mshv"))] + fn test_live_migration_basic_paused() { + _test_live_migration(false, false, true); + } + + #[test] + #[cfg(not(feature = "mshv"))] + fn test_live_migration_local_paused() { + _test_live_migration(false, true, true); } #[test] @@ -7040,16 +7070,18 @@ mod common_parallel { _test_live_migration_watchdog(false, true); } + // TODO: Add test of live upgrade paused vm after cloud-hypervisor-static + // version is updated. #[test] #[cfg(not(feature = "mshv"))] fn test_live_upgrade_basic() { - _test_live_migration(true, false); + _test_live_migration(true, false, false); } #[test] #[cfg(not(feature = "mshv"))] fn test_live_upgrade_local() { - _test_live_migration(true, true); + _test_live_migration(true, true, false); } #[test] @@ -7177,7 +7209,13 @@ mod common_parallel { let _ = std::fs::remove_file(&virtiofsd_socket_path); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, local), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + local, + false + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); }); @@ -7511,7 +7549,13 @@ mod ivshmem { ); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, local), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + local, + false + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); }); @@ -8987,7 +9031,13 @@ mod common_sequential { ); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, local), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + local, + false + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); }); @@ -9208,7 +9258,13 @@ mod common_sequential { ); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, local), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + local, + false + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); }); @@ -9336,7 +9392,13 @@ mod common_sequential { ); assert!( - start_live_migration(&migration_socket, &src_api_socket, &dest_api_socket, local), + start_live_migration( + &migration_socket, + &src_api_socket, + &dest_api_socket, + local, + false + ), "Unsuccessful command: 'send-migration' or 'receive-migration'." ); });