From 0a00df2e7ef5afffffa3e15c7187588f1031f110 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 6 May 2021 15:18:05 +0200 Subject: [PATCH] tests: Dynamically assign IPs for Windows integration tests Relying on dnsmasq running on the host, the Windows guest are now getting allocated with the expected IP addresses. This allows for multiple VMs, therefore multiple tests to run in parallel. The end goal is to reduce the time spent running Windows integration tests. Fixes #1891 Signed-off-by: Sebastien Boeuf --- Jenkinsfile | 2 +- scripts/run_integration_tests_windows.sh | 2 +- tests/integration.rs | 90 ++++++++++++++++++++---- 3 files changed, 77 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8facceace..027d88865 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -170,7 +170,7 @@ pipeline{ } } stage ('Worker build - Windows guest') { - agent { node { label 'groovy-win' } } + agent { node { label 'groovy' } } stages { stage ('Checkout') { steps { diff --git a/scripts/run_integration_tests_windows.sh b/scripts/run_integration_tests_windows.sh index de4450fd0..cf4335af3 100755 --- a/scripts/run_integration_tests_windows.sh +++ b/scripts/run_integration_tests_windows.sh @@ -44,7 +44,7 @@ export RUST_BACKTRACE=1 # Only run with 1 thread to avoid tests interfering with one another because # Windows has a static IP configured -time cargo test $features_test "tests::windows::$test_filter" -- --test-threads=1 +time cargo test $features_test "tests::windows::$test_filter" RES=$? dmsetup remove_all -f diff --git a/tests/integration.rs b/tests/integration.rs index d552480eb..f4131a8ad 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -5260,7 +5260,7 @@ mod tests { return ssh_command_ip_with_auth( "powershell -Command \"(Get-CimInstance win32_computersystem).NumberOfLogicalProcessors\"", &self.auth, - "192.168.249.2", + &self.guest.network.guest_ip, DEFAULT_SSH_RETRIES, DEFAULT_SSH_TIMEOUT, ) @@ -5274,7 +5274,7 @@ mod tests { return ssh_command_ip_with_auth( "powershell -Command \"(Get-CimInstance win32_computersystem).TotalPhysicalMemory\"", &self.auth, - "192.168.249.2", + &self.guest.network.guest_ip, DEFAULT_SSH_RETRIES, DEFAULT_SSH_TIMEOUT, ) @@ -5288,7 +5288,7 @@ mod tests { return ssh_command_ip_with_auth( "powershell -Command \"netsh int ipv4 show interfaces | Select-String ethernet | Measure-Object -Line | Format-Table -HideTableHeaders\"", &self.auth, - "192.168.249.2", + &self.guest.network.guest_ip, DEFAULT_SSH_RETRIES, DEFAULT_SSH_TIMEOUT, ) @@ -5302,7 +5302,7 @@ mod tests { ssh_command_ip_with_auth( "shutdown /r /t 0", &self.auth, - "192.168.249.2", + &self.guest.network.guest_ip, DEFAULT_SSH_RETRIES, DEFAULT_SSH_TIMEOUT, ) @@ -5313,12 +5313,36 @@ mod tests { ssh_command_ip_with_auth( "shutdown /s", &self.auth, - "192.168.249.2", + &self.guest.network.guest_ip, DEFAULT_SSH_RETRIES, DEFAULT_SSH_TIMEOUT, ) .unwrap(); } + + fn run_dnsmasq(&self) -> std::process::Child { + let listen_address = format!("--listen-address={}", self.guest.network.host_ip); + let dhcp_host = format!( + "--dhcp-host={},{}", + self.guest.network.guest_mac, self.guest.network.guest_ip + ); + let dhcp_range = format!( + "--dhcp-range=eth,{},{}", + self.guest.network.guest_ip, self.guest.network.guest_ip + ); + + Command::new("dnsmasq") + .arg("--no-daemon") + .arg("--log-queries") + .arg(listen_address.as_str()) + .arg("--except-interface=lo") + .arg("--bind-interfaces") + .arg("--conf-file=/dev/null") + .arg(dhcp_host.as_str()) + .arg(dhcp_range.as_str()) + .spawn() + .unwrap() + } } fn vcpu_threads_count(pid: u32) -> u8 { @@ -5362,10 +5386,10 @@ mod tests { .args(&["--cpus", "boot=2,kvm_hyperv=on"]) .args(&["--memory", "size=4G"]) .args(&["--kernel", ovmf_path.to_str().unwrap()]) - .default_disks() .args(&["--serial", "tty"]) .args(&["--console", "off"]) - .args(&["--net", "tap="]) + .default_disks() + .default_net() .capture_output() .spawn() .unwrap(); @@ -5378,6 +5402,12 @@ mod tests { assert!(pipesize >= PIPE_SIZE && pipesize1 >= PIPE_SIZE); thread::sleep(std::time::Duration::new(60, 0)); + + let mut child_dnsmasq = windows_guest.run_dnsmasq(); + // Give some time for the guest to reach dnsmasq and get + // assigned the right IP address. + thread::sleep(std::time::Duration::new(30, 0)); + let r = std::panic::catch_unwind(|| { windows_guest.shutdown(); }); @@ -5386,6 +5416,8 @@ mod tests { let _ = child.kill(); let output = child.wait_with_output().unwrap(); + let _ = child_dnsmasq.kill(); + handle_child_output(r, &output); } @@ -5411,10 +5443,10 @@ mod tests { .args(&["--cpus", "boot=2,kvm_hyperv=on"]) .args(&["--memory", "size=4G"]) .args(&["--kernel", ovmf_path.to_str().unwrap()]) - .default_disks() .args(&["--serial", "tty"]) .args(&["--console", "off"]) - .args(&["--net", "tap="]) + .default_disks() + .default_net() .capture_output() .spawn() .unwrap(); @@ -5429,6 +5461,11 @@ mod tests { // Wait to make sure Windows boots up thread::sleep(std::time::Duration::new(60, 0)); + let mut child_dnsmasq = windows_guest.run_dnsmasq(); + // Give some time for the guest to reach dnsmasq and get + // assigned the right IP address. + thread::sleep(std::time::Duration::new(30, 0)); + let snapshot_dir = temp_snapshot_dir_path(&tmp_dir); // Pause the VM @@ -5472,6 +5509,8 @@ mod tests { let _ = child.kill(); let output = child.wait_with_output().unwrap(); + let _ = child_dnsmasq.kill(); + handle_child_output(r, &output); } @@ -5497,10 +5536,10 @@ mod tests { .args(&["--cpus", "boot=2,max=8,kvm_hyperv=on"]) .args(&["--memory", "size=4G"]) .args(&["--kernel", ovmf_path.to_str().unwrap()]) - .default_disks() .args(&["--serial", "tty"]) .args(&["--console", "off"]) - .args(&["--net", "tap="]) + .default_disks() + .default_net() .capture_output() .spawn() .unwrap(); @@ -5508,6 +5547,11 @@ mod tests { // Wait to make sure Windows boots up thread::sleep(std::time::Duration::new(60, 0)); + let mut child_dnsmasq = windows_guest.run_dnsmasq(); + // Give some time for the guest to reach dnsmasq and get + // assigned the right IP address. + thread::sleep(std::time::Duration::new(30, 0)); + let r = std::panic::catch_unwind(|| { let vcpu_num = 2; // Check the initial number of CPUs the guest sees @@ -5546,6 +5590,8 @@ mod tests { let _ = child.kill(); let output = child.wait_with_output().unwrap(); + let _ = child_dnsmasq.kill(); + handle_child_output(r, &output); } @@ -5571,10 +5617,10 @@ mod tests { .args(&["--cpus", "boot=2,kvm_hyperv=on"]) .args(&["--memory", "size=2G,hotplug_size=5G"]) .args(&["--kernel", ovmf_path.to_str().unwrap()]) - .default_disks() .args(&["--serial", "tty"]) .args(&["--console", "off"]) - .args(&["--net", "tap="]) + .default_disks() + .default_net() .capture_output() .spawn() .unwrap(); @@ -5582,6 +5628,11 @@ mod tests { // Wait to make sure Windows boots up thread::sleep(std::time::Duration::new(60, 0)); + let mut child_dnsmasq = windows_guest.run_dnsmasq(); + // Give some time for the guest to reach dnsmasq and get + // assigned the right IP address. + thread::sleep(std::time::Duration::new(30, 0)); + let r = std::panic::catch_unwind(|| { let ram_size = 2 * 1024 * 1024 * 1024; // Check the initial number of RAM the guest sees @@ -5620,6 +5671,8 @@ mod tests { let _ = child.kill(); let output = child.wait_with_output().unwrap(); + let _ = child_dnsmasq.kill(); + handle_child_output(r, &output); } @@ -5645,10 +5698,10 @@ mod tests { .args(&["--cpus", "boot=2,kvm_hyperv=on"]) .args(&["--memory", "size=2G,hotplug_size=5G"]) .args(&["--kernel", ovmf_path.to_str().unwrap()]) - .default_disks() .args(&["--serial", "tty"]) .args(&["--console", "off"]) - .args(&["--net", "tap="]) + .default_disks() + .default_net() .capture_output() .spawn() .unwrap(); @@ -5656,6 +5709,11 @@ mod tests { // Wait to make sure Windows boots up thread::sleep(std::time::Duration::new(60, 0)); + let mut child_dnsmasq = windows_guest.run_dnsmasq(); + // Give some time for the guest to reach dnsmasq and get + // assigned the right IP address. + thread::sleep(std::time::Duration::new(30, 0)); + let r = std::panic::catch_unwind(|| { // Initially present network device let netdev_num = 1; @@ -5692,6 +5750,8 @@ mod tests { let _ = child.kill(); let output = child.wait_with_output().unwrap(); + let _ = child_dnsmasq.kill(); + handle_child_output(r, &output); } }