From c3df42d42f80bb1555bee7e2942430fb8f1b68d5 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Tue, 12 Jan 2021 11:01:20 +0100 Subject: [PATCH] ci: Copy Windows image for each integration test By relying on the Guest object, Windows dedicated tests copy the Windows guest image before booting from it. The point being to avoid corruption between multiple tests. This is already how the rest of the integration tests work, Windows tests were the only ones missing this feature. Signed-off-by: Sebastien Boeuf --- tests/integration.rs | 115 +++++++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 27 deletions(-) diff --git a/tests/integration.rs b/tests/integration.rs index f516e21da..7a95a0a85 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -96,6 +96,8 @@ mod tests { const FOCAL_IMAGE_NAME_QCOW2: &str = "focal-server-cloudimg-arm64-custom.qcow2"; #[cfg(target_arch = "x86_64")] const FOCAL_IMAGE_NAME_QCOW2: &str = "focal-server-cloudimg-amd64-custom-20210106-1.qcow2"; + #[cfg(target_arch = "x86_64")] + const WINDOWS_IMAGE_NAME: &str = "windows-server-2019.raw"; const DIRECT_KERNEL_BOOT_CMDLINE: &str = "root=/dev/vda1 console=hvc0 rw systemd.journald.forward_to_console=1"; @@ -112,6 +114,20 @@ mod tests { } } + struct WindowsDiskConfig { + image_name: String, + osdisk_path: String, + } + + impl WindowsDiskConfig { + fn new(image_name: String) -> Self { + WindowsDiskConfig { + image_name, + osdisk_path: String::new(), + } + } + } + fn handle_child_output( r: Result<(), std::boxed::Box>, output: &std::process::Output, @@ -311,6 +327,34 @@ mod tests { } } + impl DiskConfig for WindowsDiskConfig { + fn prepare_cloudinit(&self, _tmp_dir: &TempDir, _network: &GuestNetworkConfig) -> String { + String::new() + } + + fn prepare_files(&mut self, tmp_dir: &TempDir, _network: &GuestNetworkConfig) { + let mut workload_path = dirs::home_dir().unwrap(); + workload_path.push("workloads"); + + let mut osdisk_base_path = workload_path; + osdisk_base_path.push(&self.image_name); + + let osdisk_path = String::from(tmp_dir.path().join("osdisk.img").to_str().unwrap()); + + rate_limited_copy(osdisk_base_path, &osdisk_path) + .expect("copying of OS source disk image failed"); + + self.osdisk_path = osdisk_path; + } + + fn disk(&self, disk_type: DiskType) -> Option { + match disk_type { + DiskType::OperatingSystem => Some(self.osdisk_path.clone()), + DiskType::CloudInit => None, + } + } + } + fn prepare_virtiofsd( tmp_dir: &TempDir, shared_dir: &str, @@ -1171,22 +1215,36 @@ mod tests { } fn default_disks(&mut self) -> &mut Self { - self.args(&[ - "--disk", - format!( - "path={}", - self.guest - .disk_config - .disk(DiskType::OperatingSystem) - .unwrap() - ) - .as_str(), - format!( - "path={}", - self.guest.disk_config.disk(DiskType::CloudInit).unwrap() - ) - .as_str(), - ]) + if self.guest.disk_config.disk(DiskType::CloudInit).is_some() { + self.args(&[ + "--disk", + format!( + "path={}", + self.guest + .disk_config + .disk(DiskType::OperatingSystem) + .unwrap() + ) + .as_str(), + format!( + "path={}", + self.guest.disk_config.disk(DiskType::CloudInit).unwrap() + ) + .as_str(), + ]) + } else { + self.args(&[ + "--disk", + format!( + "path={}", + self.guest + .disk_config + .disk(DiskType::OperatingSystem) + .unwrap() + ) + .as_str(), + ]) + } } fn default_net(&mut self) -> &mut Self { @@ -5567,6 +5625,9 @@ mod tests { #[test] fn test_windows_guest() { + let mut windows = WindowsDiskConfig::new(WINDOWS_IMAGE_NAME.to_string()); + let guest = Guest::new(&mut windows); + let mut workload_path = dirs::home_dir().unwrap(); workload_path.push("workloads"); @@ -5576,16 +5637,15 @@ mod tests { let mut osdisk_path = workload_path; osdisk_path.push("windows-server-2019.raw"); - let mut child = Command::new(clh_command("cloud-hypervisor")) + let mut child = GuestCommand::new(&guest) .args(&["--cpus", "boot=2,kvm_hyperv=on"]) .args(&["--memory", "size=4G"]) .args(&["--kernel", ovmf_path.to_str().unwrap()]) - .args(&["--disk", &format!("path={}", osdisk_path.to_str().unwrap())]) + .default_disks() .args(&["--serial", "tty"]) .args(&["--console", "off"]) .args(&["--net", "tap="]) - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .capture_output() .spawn() .unwrap(); @@ -5618,6 +5678,9 @@ mod tests { #[test] fn test_windows_guest_snapshot_restore() { + let mut windows = WindowsDiskConfig::new(WINDOWS_IMAGE_NAME.to_string()); + let guest = Guest::new(&mut windows); + let tmp_dir = TempDir::new("ch").unwrap(); let mut workload_path = dirs::home_dir().unwrap(); workload_path.push("workloads"); @@ -5630,17 +5693,16 @@ mod tests { let api_socket = temp_api_path(&tmp_dir); - let mut child = Command::new(clh_command("cloud-hypervisor")) + let mut child = GuestCommand::new(&guest) .args(&["--api-socket", &api_socket]) .args(&["--cpus", "boot=2,kvm_hyperv=on"]) .args(&["--memory", "size=4G"]) .args(&["--kernel", ovmf_path.to_str().unwrap()]) - .args(&["--disk", &format!("path={}", osdisk_path.to_str().unwrap())]) + .default_disks() .args(&["--serial", "tty"]) .args(&["--console", "off"]) .args(&["--net", "tap="]) - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .capture_output() .spawn() .unwrap(); @@ -5673,14 +5735,13 @@ mod tests { child.wait().unwrap(); // Restore the VM from the snapshot - let mut child = Command::new(clh_command("cloud-hypervisor")) + let mut child = GuestCommand::new(&guest) .args(&["--api-socket", &api_socket]) .args(&[ "--restore", format!("source_url=file://{}", snapshot_dir).as_str(), ]) - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .capture_output() .spawn() .unwrap();