tests: add live disk resize test

This test verifies that we can grow and shrink
disk images during runtime.

On-behalf-of: SAP thomas.prescher@sap.com
Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
This commit is contained in:
Thomas Prescher 2025-12-08 20:38:34 +01:00 committed by Rob Bradford
parent b15459106c
commit 736813f90c

View file

@ -717,6 +717,18 @@ fn resize_zone_command(api_socket: &str, id: &str, desired_size: &str) -> bool {
cmd.status().expect("Failed to launch ch-remote").success()
}
fn resize_disk_command(api_socket: &str, id: &str, desired_size: &str) -> bool {
let mut cmd = Command::new(clh_command("ch-remote"));
cmd.args([
&format!("--api-socket={api_socket}"),
"resize-disk",
&format!("--disk={id}"),
&format!("--size={desired_size}"),
]);
cmd.status().expect("Failed to launch ch-remote").success()
}
// setup OVS-DPDK bridge and ports
fn setup_ovs_dpdk() {
// setup OVS-DPDK
@ -5645,6 +5657,118 @@ mod common_parallel {
_test_disk_hotplug(true);
}
#[test]
fn test_disk_resize() {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config));
#[cfg(target_arch = "x86_64")]
let kernel_path = direct_kernel_boot_path();
#[cfg(target_arch = "aarch64")]
let kernel_path = edk2_path();
let api_socket = temp_api_path(&guest.tmp_dir);
// Create a disk image that we can write to
assert!(
exec_host_command_output(&format!(
"sudo dd if=/dev/zero of=/tmp/resize.img bs=1M count=16"
))
.status
.success()
);
let mut cmd = GuestCommand::new(&guest);
cmd.args(["--api-socket", &api_socket])
.args(["--cpus", "boot=1"])
.args(["--memory", "size=512M"])
.args(["--kernel", kernel_path.to_str().unwrap()])
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
.default_disks()
.default_net()
.capture_output();
let mut child = cmd.spawn().unwrap();
let r = std::panic::catch_unwind(|| {
guest.wait_vm_boot(None).unwrap();
// Add the disk to the VM
let (cmd_success, cmd_output) = remote_command_w_output(
&api_socket,
"add-disk",
Some("path=/tmp/resize.img,id=test0"),
);
assert!(cmd_success);
assert!(
String::from_utf8_lossy(&cmd_output)
.contains("{\"id\":\"test0\",\"bdf\":\"0000:00:06.0\"}")
);
// Check that /dev/vdc exists and the block size is 16M.
assert_eq!(
guest
.ssh_command("lsblk | grep vdc | grep -c 16M")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1
);
// And check the block device can be written to.
guest
.ssh_command("sudo dd if=/dev/zero of=/dev/vdc bs=1M count=16")
.unwrap();
// Resize disk to 32M
let resize_up_success =
resize_disk_command(&api_socket, "test0", "33554432" /* 32M */);
assert!(resize_up_success);
assert_eq!(
guest
.ssh_command("lsblk | grep vdc | grep -c 32M")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1
);
// And check all blocks can be written to
guest
.ssh_command("sudo dd if=/dev/zero of=/dev/vdc bs=1M count=32")
.unwrap();
// Resize down to original size
let resize_down_success =
resize_disk_command(&api_socket, "test0", "16777216" /* 16M */);
assert!(resize_down_success);
assert_eq!(
guest
.ssh_command("lsblk | grep vdc | grep -c 16M")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1
);
// And check all blocks can be written to, again
guest
.ssh_command("sudo dd if=/dev/zero of=/dev/vdc bs=1M count=16")
.unwrap();
});
kill_child(&mut child);
let output = child.wait_with_output().unwrap();
handle_child_output(r, &output);
}
fn create_loop_device(backing_file_path: &str, block_size: u32, num_retries: usize) -> String {
const LOOP_CONFIGURE: u64 = 0x4c0a;
const LOOP_CTL_GET_FREE: u64 = 0x4c82;