From 785db6295e2c9b4516026358cc9490a1d98fb7af Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 20 Jun 2019 13:26:11 -0700 Subject: [PATCH] test: Add virtio-pmem integration tests Add 2 integration tests to validate virtio-pmem works as expected. One test takes care of checking the ability to read and write to this persistent memory from the guest, and validates that the data is carried over the virtualization boundary. The other test ensures the VM can be booted directly from an image that would be passed through virtio-pmem. Signed-off-by: Sebastien Boeuf --- Jenkinsfile | 2 +- scripts/run_integration_tests.sh | 8 ++ src/main.rs | 138 ++++++++++++++++++++++++++++++- 3 files changed, 144 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d4321470b..a60fcbb20 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,7 +5,7 @@ stage ("Builds") { } stage ('Install system packages') { sh "sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq build-essential mtools libssl-dev pkg-config" - sh "sudo apt-get install -yq flex bison libelf-dev" + sh "sudo apt-get install -yq flex bison libelf-dev qemu-utils" } stage ('Install Rust') { sh "nohup curl https://sh.rustup.rs -sSf | sh -s -- -y" diff --git a/scripts/run_integration_tests.sh b/scripts/run_integration_tests.sh index a575b14da..994831611 100755 --- a/scripts/run_integration_tests.sh +++ b/scripts/run_integration_tests.sh @@ -24,6 +24,14 @@ if [ ! -f "$OS_IMAGE" ]; then popd fi +OS_RAW_IMAGE_NAME="clear-29810-cloud-raw.img" +OS_RAW_IMAGE="$WORKLOADS_DIR/$OS_RAW_IMAGE_NAME" +if [ ! -f "$OS_RAW_IMAGE" ]; then + pushd $WORKLOADS_DIR + qemu-img convert -p -f qcow2 -O raw $OS_IMAGE_NAME $OS_RAW_IMAGE_NAME + popd +fi + # Build generic kernel VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux" BZIMAGE_IMAGE="$WORKLOADS_DIR/bzImage" diff --git a/src/main.rs b/src/main.rs index 8049aca88..f6f59d27c 100755 --- a/src/main.rs +++ b/src/main.rs @@ -155,10 +155,11 @@ extern crate credibility; #[cfg(feature = "integration_tests")] mod tests { use ssh2::Session; - use std::fs; - use std::io::Read; + use std::fs::{self, read, OpenOptions}; + use std::io::{Read, Write}; use std::net::TcpStream; use std::process::Command; + use std::string::String; use std::thread; fn ssh_command(command: &str) -> String { @@ -214,12 +215,18 @@ mod tests { let mut osdisk_base_path = workload_path.clone(); osdisk_base_path.push("clear-29810-cloud.img"); + let mut osdisk_raw_base_path = workload_path.clone(); + osdisk_raw_base_path.push("clear-29810-cloud-raw.img"); + let osdisk_path = "/tmp/osdisk.img"; + let osdisk_raw_path = "/tmp/osdisk_raw.img"; let cloudinit_path = "/tmp/cloudinit.img"; fs::copy(osdisk_base_path, osdisk_path).expect("copying of OS source disk image failed"); + fs::copy(osdisk_raw_base_path, osdisk_raw_path) + .expect("copying of OS source disk raw image failed"); - let disks = vec![osdisk_path, cloudinit_path]; + let disks = vec![osdisk_path, cloudinit_path, osdisk_raw_path]; (disks, String::from(fw_path.to_str().unwrap())) } @@ -569,4 +576,129 @@ mod tests { Ok(()) }); } + + #[test] + fn test_virtio_pmem() { + test_block!(tb, "", { + let (disks, _) = prepare_files(); + let mut workload_path = dirs::home_dir().unwrap(); + workload_path.push("workloads"); + + let mut kernel_path = workload_path.clone(); + kernel_path.push("vmlinux-custom"); + + let pmem_backend_path = "/tmp/pmem-file"; + let mut pmem_backend_file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(pmem_backend_path) + .unwrap(); + + let pmem_backend_content = "foo"; + pmem_backend_file + .write_all(pmem_backend_content.as_bytes()) + .unwrap(); + let pmem_backend_file_size = 0x1000; + pmem_backend_file.set_len(pmem_backend_file_size).unwrap(); + + let mut child = Command::new("target/debug/cloud-hypervisor") + .args(&["--cpus", "1"]) + .args(&["--memory", "size=512"]) + .args(&["--kernel", kernel_path.to_str().unwrap()]) + .args(&["--disk", disks[0], disks[1]]) + .args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"]) + .args(&[ + "--pmem", + format!( + "file={},size={}", + pmem_backend_path, + pmem_backend_file_size + ) + .as_str(), + ]) + .args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"]) + .spawn() + .unwrap(); + + thread::sleep(std::time::Duration::new(10, 0)); + + // Check for the presence of /dev/pmem0 + aver_eq!(tb, ssh_command("ls /dev/pmem0").trim(), "/dev/pmem0"); + // Check content + aver_eq!( + tb, + &ssh_command("sudo cat /dev/pmem0").trim()[..pmem_backend_content.len()], + pmem_backend_content + ); + // Modify content + let new_content = "bar"; + ssh_command( + format!( + "sudo bash -c 'echo {} > /dev/pmem0' && sudo sync /dev/pmem0", + new_content + ) + .as_str(), + ); + + // Check content from host + aver_eq!( + tb, + &String::from_utf8(read(pmem_backend_path).unwrap()) + .unwrap() + .as_str()[..new_content.len()], + new_content + ); + + ssh_command("sudo reboot"); + let _ = child.wait(); + + // Cleanup the file + fs::remove_file(pmem_backend_path).unwrap(); + + Ok(()) + }); + } + + #[test] + fn test_boot_from_virtio_pmem() { + test_block!(tb, "", { + let (disks, _) = prepare_files(); + let mut workload_path = dirs::home_dir().unwrap(); + workload_path.push("workloads"); + + let mut kernel_path = workload_path.clone(); + kernel_path.push("vmlinux-custom"); + + let mut child = Command::new("target/debug/cloud-hypervisor") + .args(&["--cpus", "1"]) + .args(&["--memory", "size=512"]) + .args(&["--kernel", kernel_path.to_str().unwrap()]) + .args(&["--disk", disks[1]]) + .args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"]) + .args(&[ + "--pmem", + format!( + "file={},size={}", + disks[2], + fs::metadata(disks[2]).unwrap().len() + ) + .as_str(), + ]) + .args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"]) + .spawn() + .unwrap(); + + thread::sleep(std::time::Duration::new(10, 0)); + + // Simple checks to validate the VM booted properly + aver_eq!(tb, get_cpu_count(), 1); + aver!(tb, get_total_memory() > 496_000); + + ssh_command("sudo reboot"); + let _ = child.wait(); + + Ok(()) + }); + } }