From 700f63fad8f55ef0b931f53acd28c49d5a7ca1b7 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Fri, 25 Sep 2020 10:46:50 +0100 Subject: [PATCH] tests: Add integration test for virtio-watchdog Signed-off-by: Rob Bradford --- tests/integration.rs | 111 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/tests/integration.rs b/tests/integration.rs index c4d6e01ed..5dd3771ea 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -5323,6 +5323,117 @@ mod tests { handle_child_output(r, &output); } + + #[test] + #[cfg(target_arch = "x86_64")] + fn test_watchdog() { + let mut focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string()); + let guest = Guest::new(&mut focal); + let api_socket = temp_api_path(&guest.tmp_dir); + + let kernel_path = direct_kernel_boot_path().unwrap(); + + let mut cmd = GuestCommand::new(&guest); + cmd.args(&["--cpus", "boot=1"]) + .args(&["--memory", "size=512M"]) + .args(&["--kernel", kernel_path.to_str().unwrap()]) + .args(&["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE]) + .default_disks() + .args(&["--net", guest.default_net_string().as_str()]) + .args(&["--watchdog"]) + .args(&["--api-socket", &api_socket]) + .capture_output(); + + let mut child = cmd.spawn().unwrap(); + + thread::sleep(std::time::Duration::new(20, 0)); + let r = std::panic::catch_unwind(|| { + // Check for PCI device + assert!(guest + .does_device_vendor_pair_match("0x1063", "0x1af4") + .unwrap_or_default()); + + // Enable systemd watchdog + guest + .ssh_command( + "echo RuntimeWatchdogSec=15s | sudo tee -a /etc/systemd/system.conf", + ) + .unwrap(); + + guest.ssh_command("sudo reboot").unwrap(); + thread::sleep(std::time::Duration::new(20, 0)); + + // Check that systemd has activated the watchdog + assert_eq!( + guest + .ssh_command("sudo journalctl | grep -c -- \"Watchdog started\"") + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default(), + 2 + ); + + // Ensure that the current boot journal is written so reboot counts are valid + guest.ssh_command("sudo journalctl --sync").unwrap(); + + let boot_count = guest + .ssh_command("sudo journalctl --list-boots | wc -l") + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default(); + assert_eq!(boot_count, 2); + // Allow some normal time to elapse to check we don't get spurious reboots + thread::sleep(std::time::Duration::new(40, 0)); + + // Check no reboot + let boot_count = guest + .ssh_command("sudo journalctl --list-boots | wc -l") + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default(); + assert_eq!(boot_count, 2); + + // Ensure that the current boot journal is written so reboot counts are valid + guest.ssh_command("sudo journalctl --sync").unwrap(); + + // Trigger a panic (sync first). We need to do this inside a screen with a delay so the SSH command returns. + guest.ssh_command("screen -dmS reboot sh -c \"sleep 5; echo s | tee /proc/sysrq-trigger; echo c | sudo tee /proc/sysrq-trigger\"").unwrap(); + + // Allow some time for the watchdog to trigger (max 30s) and reboot to happen + thread::sleep(std::time::Duration::new(50, 0)); + + // Check that watchdog triggered reboot + let boot_count = guest + .ssh_command("sudo journalctl --list-boots | wc -l") + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default(); + assert_eq!(boot_count, 3); + + // Now pause the VM and remain offline for 30s + assert!(remote_command(&api_socket, "pause", None)); + thread::sleep(std::time::Duration::new(30, 0)); + assert!(remote_command(&api_socket, "resume", None)); + + // Check no reboot + let boot_count = guest + .ssh_command("sudo journalctl --list-boots | wc -l") + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default(); + assert_eq!(boot_count, 3); + }); + + let _ = child.kill(); + let output = child.wait_with_output().unwrap(); + + handle_child_output(r, &output); + } } mod sequential {