nixos-test-driver: include a timeout for the recv call, do not assume sh == bash

This commit is contained in:
r-vdp 2023-04-26 00:44:23 +02:00
parent 113045a443
commit 4147b878bc
No known key found for this signature in database
2 changed files with 31 additions and 7 deletions

View File

@ -7,6 +7,7 @@ import io
import os import os
import queue import queue
import re import re
import select
import shlex import shlex
import shutil import shutil
import socket import socket
@ -99,7 +100,7 @@ def _perform_ocr_on_screenshot(
+ "-blur 1x65535" + "-blur 1x65535"
) )
tess_args = f"-c debug_file=/dev/null --psm 11" tess_args = "-c debug_file=/dev/null --psm 11"
cmd = f"convert {magick_args} '{screenshot_path}' 'tiff:{screenshot_path}.tiff'" cmd = f"convert {magick_args} '{screenshot_path}' 'tiff:{screenshot_path}.tiff'"
ret = subprocess.run(cmd, shell=True, capture_output=True) ret = subprocess.run(cmd, shell=True, capture_output=True)
@ -154,6 +155,7 @@ class StartCommand:
# qemu options # qemu options
qemu_opts = ( qemu_opts = (
" -device virtio-serial" " -device virtio-serial"
# Note: virtconsole will map to /dev/hvc0 in Linux guests
" -device virtconsole,chardev=shell" " -device virtconsole,chardev=shell"
" -device virtio-rng-pci" " -device virtio-rng-pci"
" -serial stdio" " -serial stdio"
@ -524,8 +526,10 @@ class Machine:
if timeout is not None: if timeout is not None:
timeout_str = f"timeout {timeout}" timeout_str = f"timeout {timeout}"
# While sh is bash on NixOS, this is not the case for every distro.
# We explicitely call bash here to allow for the driver to boot other distros as well.
out_command = ( out_command = (
f"{timeout_str} sh -c {shlex.quote(command)} | (base64 --wrap 0; echo)\n" f"{timeout_str} bash -c {shlex.quote(command)} | (base64 --wrap 0; echo)\n"
) )
assert self.shell assert self.shell
@ -719,6 +723,15 @@ class Machine:
self.wait_for_unit(jobname) self.wait_for_unit(jobname)
def connect(self) -> None: def connect(self) -> None:
def shell_ready(timeout_secs: int) -> bool:
"""We sent some data from the backdoor service running on the guest
to indicate that the backdoor shell is ready.
As soon as we read some data from the socket here, we assume that
our root shell is operational.
"""
(ready, _, _) = select.select([self.shell], [], [], timeout_secs)
return bool(ready)
if self.connected: if self.connected:
return return
@ -728,8 +741,11 @@ class Machine:
assert self.shell assert self.shell
tic = time.time() tic = time.time()
self.shell.recv(1024) # TODO: do we want to bail after a set number of attempts?
# TODO: Timeout while not shell_ready(timeout_secs=30):
self.log("Guest root shell did not produce any data yet...")
self.log(self.shell.recv(1024).decode())
toc = time.time() toc = time.time()
self.log("connected to guest root shell") self.log("connected to guest root shell")
@ -950,7 +966,7 @@ class Machine:
Prepares the machine to be reconnected which is useful if the Prepares the machine to be reconnected which is useful if the
machine was started with `allow_reboot = True` machine was started with `allow_reboot = True`
""" """
self.send_key(f"ctrl-alt-delete") self.send_key("ctrl-alt-delete")
self.connected = False self.connected = False
def wait_for_x(self) -> None: def wait_for_x(self) -> None:

View File

@ -36,8 +36,16 @@ in
while ! exec 2> /dev/${qemu-common.qemuSerialDevice}; do sleep 0.1; done while ! exec 2> /dev/${qemu-common.qemuSerialDevice}; do sleep 0.1; done
echo "connecting to host..." >&2 echo "connecting to host..." >&2
stty -F /dev/hvc0 raw -echo # prevent nl -> cr/nl conversion stty -F /dev/hvc0 raw -echo # prevent nl -> cr/nl conversion
echo # The following line is essential since it signals to
PS1= exec /bin/sh # the test driver that the shell is ready.
# See: the connect method in the Machine class.
echo "Spawning backdoor root shell..."
# Passing the terminal device makes bash run non-interactively.
# Otherwise we get errors on the terminal because bash tries to
# setup things like job control.
# Note: calling bash explicitely here instead of sh makes sure that
# we can also run non-NixOS guests during tests.
PS1= exec /usr/bin/env bash --norc /dev/hvc0
''; '';
serviceConfig.KillSignal = "SIGHUP"; serviceConfig.KillSignal = "SIGHUP";
}; };