diff --git a/cloud-hypervisor/tests/integration.rs b/cloud-hypervisor/tests/integration.rs index 861044508..34379297f 100644 --- a/cloud-hypervisor/tests/integration.rs +++ b/cloud-hypervisor/tests/integration.rs @@ -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. diff --git a/test_infra/src/lib.rs b/test_infra/src/lib.rs index 19a76bb15..c58e6a9c8 100644 --- a/test_infra/src/lib.rs +++ b/test_infra/src/lib.rs @@ -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}\" ]");