tests: Wait for boot notification from test_vfio_user L2 guest

Reuse the boot notification method we have for the L1 guests for the L2
guest. This removes the need to use SSH based boot tracking for
connecfting to the L2 guest and should make the test more reliable.

This requires making the L2 guest use a different cloud-init
configuration to the L1.

Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
Rob Bradford
2026-05-06 11:06:15 +01:00
parent 9703971ae7
commit 12f48700a2
2 changed files with 35 additions and 25 deletions

View File

@@ -2359,13 +2359,11 @@ mod common_parallel {
let mut cloud_init_vfio_base_path = vfio_path.clone();
cloud_init_vfio_base_path.push("cloudinit.img");
// We copy our cloudinit into the vfio mount point, for the nested
// cloud-hypervisor guest to use.
rate_limited_copy(
guest.disk_config.disk(DiskType::CloudInit).unwrap(),
&cloud_init_vfio_base_path,
)
.expect("copying of cloud-init disk failed");
// Prepare a separate cloud-init for the L2 guest with its own
// boot notification port.
let (_l2_ci_dir, l2_ci_path) = guest.prepare_l2_cloudinit();
rate_limited_copy(l2_ci_path, &cloud_init_vfio_base_path)
.expect("copying of L2 cloud-init disk failed");
let mut vfio_disk_path = workload_path.clone();
vfio_disk_path.push("vfio.img");
@@ -2444,24 +2442,17 @@ mod common_parallel {
let r = std::panic::catch_unwind(|| {
guest.ssh_command_l1("sudo systemctl start vfio").unwrap();
GuestNetworkConfig::wait_vm_boot_from(
guest.network.l2_tcp_listener_port,
&guest.network.l2_guest_ip2,
DEFAULT_TCP_LISTENER_TIMEOUT,
)
.unwrap();
let auth = PasswordAuth {
username: String::from("cloud"),
password: String::from("cloud123"),
};
wait_for_ssh(
"true",
&auth,
&guest.network.l2_guest_ip1,
Duration::from_secs(120),
)
.unwrap();
wait_for_ssh(
"true",
&auth,
&guest.network.l2_guest_ip2,
Duration::from_secs(120),
)
.unwrap();
// We booted our cloud hypervisor L2 guest with a "VFIOTAG" tag
// added to its kernel command line.

View File

@@ -193,6 +193,7 @@ where
}
}
#[derive(Clone)]
pub struct GuestNetworkConfig {
pub guest_ip0: String,
pub host_ip0: String,
@@ -207,6 +208,7 @@ pub struct GuestNetworkConfig {
pub l2_guest_mac2: String,
pub l2_guest_mac3: String,
pub tcp_listener_port: u16,
pub l2_tcp_listener_port: u16,
pub notify_ip: String,
}
@@ -230,11 +232,13 @@ pub enum WaitForBootError {
}
impl GuestNetworkConfig {
pub fn wait_vm_boot(&self, custom_timeout: u32) -> Result<(), WaitForBootError> {
pub fn wait_vm_boot_from(
port: u16,
expected_guest_addr: &str,
custom_timeout: u32,
) -> Result<(), WaitForBootError> {
let start = std::time::Instant::now();
// The 'port' is unique per 'GUEST' and listening to wild-card ip avoids retrying on 'TcpListener::bind()'
let listen_addr = format!("0.0.0.0:{}", self.tcp_listener_port);
let expected_guest_addr = self.guest_ip0.as_str();
let listen_addr = format!("0.0.0.0:{port}");
let mut s = String::new();
let mut closure = || -> Result<(), WaitForBootError> {
@@ -314,6 +318,10 @@ impl GuestNetworkConfig {
Ok(_) => Ok(()),
}
}
pub fn wait_vm_boot(&self, custom_timeout: u32) -> Result<(), WaitForBootError> {
Self::wait_vm_boot_from(self.tcp_listener_port, &self.guest_ip0, custom_timeout)
}
}
pub enum DiskType {
@@ -1203,6 +1211,7 @@ impl Guest {
l2_guest_mac2: format!("de:ad:be:ef:34:{id:02x}"),
l2_guest_mac3: format!("de:ad:be:ef:56:{id:02x}"),
tcp_listener_port: DEFAULT_TCP_LISTENER_PORT + id as u16,
l2_tcp_listener_port: DEFAULT_TCP_LISTENER_PORT + 1024 + id as u16,
notify_ip: format!("{class}.{id}.1"),
};
@@ -1463,6 +1472,16 @@ impl Guest {
.map_err(Error::WaitForBoot)
}
pub fn prepare_l2_cloudinit(&self) -> (TempDir, String) {
let l2_dir = TempDir::new_with_prefix("/tmp/ch-l2").unwrap();
let l2_network = GuestNetworkConfig {
tcp_listener_port: self.network.l2_tcp_listener_port,
..self.network.clone()
};
let path = self.disk_config.prepare_cloudinit(&l2_dir, &l2_network);
(l2_dir, path)
}
pub fn check_numa_node_cpus(&self, node_id: usize, cpus: &[usize]) -> Result<(), Error> {
for cpu in cpus.iter() {
let cmd = format!("[ -d \"/sys/devices/system/node/node{node_id}/cpu{cpu}\" ]");