test: Use context system for guest commands

Extends the context system in the test scripts to allow executing commands
within a guest.  Do this without requiring an existing network in the guest
by using socat to run ssh via a vsock connection.

We do need some additional "sleep"s in the tests, because the new
faster dispatch means that sometimes we attempt to connect before
socat has managed to listen.

For now, only use this for the plain "passt" tests.  The "passt_in_ns" and
other tests have additional complications we still need to deal with.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
David Gibson 2022-09-12 20:56:22 +10:00 committed by Stefano Brivio
parent a8a437abd6
commit 56e755ba11
10 changed files with 90 additions and 16 deletions

2
test/.gitignore vendored
View file

@ -11,3 +11,5 @@ QEMU_EFI.fd
*.stop *.stop
*.js *.js
nsholder nsholder
guest-key
guest-key.pub

View file

@ -57,7 +57,7 @@ DOWNLOAD_ASSETS = mbuto \
LOCAL_ASSETS = mbuto.img QEMU_EFI.fd \ LOCAL_ASSETS = mbuto.img QEMU_EFI.fd \
$(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \ $(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \
$(UBUNTU_NEW_IMGS:%=prepared-%) \ $(UBUNTU_NEW_IMGS:%=prepared-%) \
nsholder nsholder guest-key guest-key.pub
ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS) ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS)
@ -68,7 +68,10 @@ assets: $(ASSETS)
mbuto: mbuto:
git clone git://mbuto.sh/mbuto git clone git://mbuto.sh/mbuto
mbuto.img: passt.mbuto mbuto guest-key guest-key.pub:
ssh-keygen -f guest-key -N ''
mbuto.img: passt.mbuto mbuto guest-key.pub
./mbuto/mbuto -p ./$< -c lz4 -f $@ ./mbuto/mbuto -p ./$< -c lz4 -f $@
nsholder: nsholder.c nsholder: nsholder.c

View file

@ -41,12 +41,38 @@ context_setup_nsenter() {
echo "nsenter $@ sh -c" > "${__prefix}.enter" echo "nsenter $@ sh -c" > "${__prefix}.enter"
} }
# context_setup_guest() - Create a new context for running commands in a guest
# $1: Context name
# $2: CID to use for vsock
context_setup_guest() {
__name="$1"
__cid="$2"
__prefix="${LOGDIR}/context_${__name}"
context_setup_common "${__name}"
cat > "${__prefix}.ssh" <<EOF
Host ${__name}
User root
UserKnownHostsFile ${__prefix}.hosts
StrictHostKeyChecking no
IdentityFile ${BASEPATH}/guest-key
IdentityAgent none
ProxyCommand socat - VSOCK-CONNECT:${__cid}:22
EOF
echo "ssh -F ${__prefix}.ssh ${__name}" > "${__prefix}.enter"
# Wait for the guest to be booted and accepting connections
while ! ssh -F "${__prefix}.ssh" "${__name}" :; do
sleep 0.1
done
}
# context_teardown() - Remove a context (leave log files intact) # context_teardown() - Remove a context (leave log files intact)
# $1: Context name # $1: Context name
context_teardown() { context_teardown() {
__name="$1" __name="$1"
__prefix="${LOGDIR}/context_${__name}" __prefix="${LOGDIR}/context_${__name}"
rm -f "${__prefix}.enter" rm -f "${__prefix}.enter" "${__prefix}.ssh" "${__prefix}.hosts"
} }
# context_exists() - Test if a context currently exists # context_exists() - Test if a context currently exists

View file

@ -92,15 +92,13 @@ layout_passt() {
get_info_cols get_info_cols
tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
tmux select-pane -t ${PANE_GUEST} -T "guest"
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done' tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log" tmux select-pane -t ${PANE_INFO} -T "test log"
pane_watch_contexts ${PANE_HOST} host host pane_watch_contexts ${PANE_HOST} host host
pane_watch_contexts ${PANE_PASST} passt passt pane_watch_contexts ${PANE_PASST} passt passt
pane_watch_contexts ${PANE_GUEST} guest qemu guest
info_layout "single passt instance with guest" info_layout "single passt instance with guest"

View file

@ -35,6 +35,7 @@ setup_distro() {
setup_passt() { setup_passt() {
context_setup_host host context_setup_host host
context_setup_host passt context_setup_host passt
context_setup_host qemu
layout_passt layout_passt
@ -55,7 +56,8 @@ setup_passt() {
context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid" context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
sleep 5 sleep 5
pane_run GUEST './qrap 5 qemu-system-$(uname -m)' \ GUEST_CID=94557
context_run_bg qemu './qrap 5 qemu-system-$(uname -m)' \
' -machine accel=kvm' \ ' -machine accel=kvm' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \ ' -m '${VMEM}' -cpu host -smp '${VCPUS} \
' -kernel ' "/boot/vmlinuz-$(uname -r)" \ ' -kernel ' "/boot/vmlinuz-$(uname -r)" \
@ -65,8 +67,10 @@ setup_passt() {
'virtio-net.napi_tx=1"' \ 'virtio-net.napi_tx=1"' \
" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384" \ " -device virtio-net-pci,netdev=hostnet0,x-txburst=16384" \
" -netdev socket,fd=5,id=hostnet0" \ " -netdev socket,fd=5,id=hostnet0" \
' -pidfile passt_qemu.pid' " -pidfile passt_qemu.pid" \
pane_status GUEST " -device vhost-vsock-pci,guest-cid=$GUEST_CID"
context_setup_guest guest $GUEST_CID
} }
# setup_pasta() - Create a network and user namespace, connect pasta to it # setup_pasta() - Create a network and user namespace, connect pasta to it
@ -307,11 +311,12 @@ teardown_distro() {
# teardown_passt() - Kill qemu, remove passt PID file # teardown_passt() - Kill qemu, remove passt PID file
teardown_passt() { teardown_passt() {
kill $(cat passt_qemu.pid) kill $(cat passt_qemu.pid)
pane_wait GUEST
rm passt.pid rm passt.pid
teardown_context_watch ${PANE_HOST} host teardown_context_watch ${PANE_HOST} host
teardown_context_watch ${PANE_PASST} passt teardown_context_watch ${PANE_PASST} passt
teardown_context_watch ${PANE_GUEST} qemu guest
} }
# teardown_passt() - Exit namespace, kill pasta process # teardown_passt() - Exit namespace, kill pasta process

View file

@ -266,7 +266,8 @@ pane_or_context_run() {
__name="${1}" __name="${1}"
shift shift
if context_exists "${__name}"; then if context_exists "${__name}"; then
context_run "${__name}" "$@" >/dev/null 2>&1 # Redirect stdin to stop ssh from eating the test instructions file we have on stdin
context_run "${__name}" "$@" >/dev/null 2>&1 < /dev/null
else else
__uc="$(echo "${__name}" | tr [a-z] [A-Z])" __uc="$(echo "${__name}" | tr [a-z] [A-Z])"
pane_run "${__uc}" "$@" pane_run "${__uc}" "$@"
@ -281,7 +282,8 @@ pane_or_context_run_bg() {
__name="${1}" __name="${1}"
shift shift
if context_exists "${__name}"; then if context_exists "${__name}"; then
context_run_bg "${__name}" "$@" >/dev/null 2>&1 # Redirect stdin to stop ssh from eating the test instructions file we have on stdin
context_run_bg "${__name}" "$@" >/dev/null 2>&1 < /dev/null
else else
__uc="$(echo "${__name}" | tr [a-z] [A-Z])" __uc="$(echo "${__name}" | tr [a-z] [A-Z])"
pane_run "${__uc}" "$@" pane_run "${__uc}" "$@"
@ -295,7 +297,8 @@ pane_or_context_output() {
__name="${1}" __name="${1}"
shift shift
if context_exists "${__name}"; then if context_exists "${__name}"; then
__output=$(context_run "${__name}" "$@" 2>/dev/null) # Redirect stdin to stop ssh from eating the test instructions file we have on stdin
__output=$(context_run "${__name}" "$@" 2>/dev/null </dev/null)
if [ -z "${__output}" ]; then if [ -z "${__output}" ]; then
echo "@EMPTY@" echo "@EMPTY@"
else else

View file

@ -13,15 +13,15 @@
PROGS="${PROGS:-ash,dash,bash ip mount ls insmod mkdir ln cat chmod lsmod PROGS="${PROGS:-ash,dash,bash ip mount ls insmod mkdir ln cat chmod lsmod
modprobe find grep mknod mv rm umount jq iperf3 dhclient hostname modprobe find grep mknod mv rm umount jq iperf3 dhclient hostname
sed tr chown sipcalc cut md5sum socat dd strace ping tail killall sleep sed tr chown sipcalc cut md5sum socat dd strace ping tail killall sleep
sysctl nproc tcp_rr tcp_crr udp_rr which tee seq bc}" sysctl nproc tcp_rr tcp_crr udp_rr which tee seq bc sshd ssh-keygen}"
KMODS="${KMODS:- virtio_net virtio_pci}" KMODS="${KMODS:- virtio_net virtio_pci vmw_vsock_virtio_transport}"
LINKS="${LINKS:- LINKS="${LINKS:-
ash,dash,bash /init ash,dash,bash /init
ash,dash,bash /bin/sh}" ash,dash,bash /bin/sh}"
DIRS="${DIRS} /tmp /sbin /var/log /var/run /var/lib" DIRS="${DIRS} /tmp /sbin /usr/share /var/log /var/lib /etc/ssh /run/sshd /root/.ssh"
FIXUP="${FIXUP}"' FIXUP="${FIXUP}"'
cat > /sbin/dhclient-script << EOF cat > /sbin/dhclient-script << EOF
@ -46,7 +46,33 @@ exit 0
EOF EOF
chmod 755 /sbin/dhclient-script chmod 755 /sbin/dhclient-script
ln -s /sbin /usr/sbin ln -s /sbin /usr/sbin
ln -s /bin /usr/bin
ln -s /run /var/run
:> /etc/fstab :> /etc/fstab
# sshd(dropbear) via vsock
cat > /etc/passwd << EOF
root:x:0:0:root:/root:/bin/sh
sshd:x:100:100:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
EOF
cat > /etc/shadow << EOF
root:::0:99999:7:::
EOF
chmod 000 /etc/shadow
:> /etc/ssh/sshd_config
ssh-keygen -A
chmod 700 /root/.ssh
chmod 700 /run/sshd
# Alternative location for the priv separation dir
ln -s /run/sshd /usr/share/empty.sshd
cat > /root/.ssh/authorized_keys <<EOF
'"$(cat guest-key.pub)"'
EOF
chmod 600 /root/.ssh/authorized_keys
chmod 700 /root
socat VSOCK-LISTEN:22,fork EXEC:"sshd -i -e" 2> /var/log/vsock-ssh.log &
sh +m sh +m
' '

View file

@ -17,6 +17,7 @@ htools dd socat ip jq md5sum cut
test TCP/IPv4: host to guest: big transfer test TCP/IPv4: host to guest: big transfer
temp TEMP_BIG temp TEMP_BIG
guestb socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_big.bin,create,trunc guestb socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_big.bin,create,trunc
sleep 1
host dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__ host dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__
host socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001 host socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001
guestw guestw
@ -35,6 +36,7 @@ check [ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
test TCP/IPv4: host to guest: small transfer test TCP/IPv4: host to guest: small transfer
temp TEMP_SMALL temp TEMP_SMALL
guestb socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_small.bin,create,trunc guestb socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_small.bin,create,trunc
sleep 1
host dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__ host dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__
host socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001 host socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001
guestw guestw

View file

@ -18,6 +18,7 @@ nstools socat ip jq md5sum cut
test TCP/IPv4: host to guest: big transfer test TCP/IPv4: host to guest: big transfer
temp TEMP_BIG temp TEMP_BIG
guestb socat -u TCP4-LISTEN:10001 OPEN:test_big.bin,create,trunc guestb socat -u TCP4-LISTEN:10001 OPEN:test_big.bin,create,trunc
sleep 1
host dd if=/dev/urandom bs=1M count=10 of=__TEMP_BIG__ host dd if=/dev/urandom bs=1M count=10 of=__TEMP_BIG__
host socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001 host socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001
guestw guestw
@ -82,6 +83,7 @@ check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: host to guest: small transfer test TCP/IPv4: host to guest: small transfer
temp TEMP_SMALL temp TEMP_SMALL
guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
sleep 1
host dd if=/dev/urandom bs=2k count=100 of=__TEMP_SMALL__ host dd if=/dev/urandom bs=2k count=100 of=__TEMP_SMALL__
host socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001 host socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001
guestw guestw
@ -129,6 +131,7 @@ check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to guest (using loopback address): small transfer test TCP/IPv4: ns to guest (using loopback address): small transfer
guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
sleep 1
ns socat -u OPEN:__TEMP_NS_SMALL__ TCP4:127.0.0.1:10001 ns socat -u OPEN:__TEMP_NS_SMALL__ TCP4:127.0.0.1:10001
guestw guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1 gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@ -136,6 +139,7 @@ check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to guest (using namespace address): small transfer test TCP/IPv4: ns to guest (using namespace address): small transfer
guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
sleep 1
ns socat -u OPEN:__TEMP_NS_SMALL__ TCP4:__ADDR__:10001 ns socat -u OPEN:__TEMP_NS_SMALL__ TCP4:__ADDR__:10001
guestw guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1 gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@ -143,6 +147,7 @@ check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: host to guest: big transfer test TCP/IPv6: host to guest: big transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc guestb socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc
sleep 1
host socat -u OPEN:__TEMP_BIG__ TCP6:[::1]:10001 host socat -u OPEN:__TEMP_BIG__ TCP6:[::1]:10001
guestw guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1 gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
@ -188,6 +193,7 @@ check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: ns to guest (using loopback address): big transfer test TCP/IPv6: ns to guest (using loopback address): big transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc guestb socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc
sleep 1
ns socat -u OPEN:__TEMP_NS_BIG__ TCP6:[::1]:10001 ns socat -u OPEN:__TEMP_NS_BIG__ TCP6:[::1]:10001
guestw guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1 gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
@ -203,6 +209,7 @@ check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: host to guest: small transfer test TCP/IPv6: host to guest: small transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc guestb socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc
sleep 1
host socat -u OPEN:__TEMP_SMALL__ TCP6:[::1]:10001 host socat -u OPEN:__TEMP_SMALL__ TCP6:[::1]:10001
guestw guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1 gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@ -248,6 +255,7 @@ check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to guest (using loopback address): small transfer test TCP/IPv6: ns to guest (using loopback address): small transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc guestb socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc
sleep 1
ns socat -u OPEN:__TEMP_NS_SMALL__ TCP6:[::1]:10001 ns socat -u OPEN:__TEMP_NS_SMALL__ TCP6:[::1]:10001
guestw guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1 gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1

View file

@ -18,6 +18,7 @@ test UDP/IPv4: host to guest
temp TEMP temp TEMP
temp SC_PID temp SC_PID
guestb (socat -u UDP4-LISTEN:10001 STDOUT & echo $! > __SC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__)) guestb (socat -u UDP4-LISTEN:10001 STDOUT & echo $! > __SC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
sleep 1
host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__ host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001 host socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
guestw guestw