diff options
author | Helmut Grohne <helmut@subdivi.de> | 2023-01-11 19:58:23 +0100 |
---|---|---|
committer | Helmut Grohne <helmut@subdivi.de> | 2023-01-11 19:58:23 +0100 |
commit | dc3527288d6f82ab60cfbe24efeb0961130901b7 (patch) | |
tree | 4df30b822078140cec3646421c71208a4646bc4a | |
parent | fe999e3cdb244bef2bd425918bc874b0018e94aa (diff) | |
parent | e7c2288400ee78c3ef8c7a92128287c1eff67811 (diff) | |
download | debvm-dc3527288d6f82ab60cfbe24efeb0961130901b7.tar.gz |
Merge branch main into skip
Resolve conflicts in the documentation of debvm-create.
-rw-r--r-- | .gitlab-ci.yml | 4 | ||||
-rwxr-xr-x | debvm-create | 15 | ||||
-rwxr-xr-x | debvm-run | 38 | ||||
-rwxr-xr-x | debvm-waitssh | 178 | ||||
-rwxr-xr-x | tests/create-and-run.sh | 2 | ||||
-rwxr-xr-x | tests/dist-upgrades.sh | 4 | ||||
-rw-r--r-- | tests/test_common.sh | 11 |
7 files changed, 225 insertions, 27 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d2a1bbf..456e8d9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,7 +27,7 @@ release_test: script: - apt-get update - apt-get dist-upgrade --yes - - apt-get --no-install-recommends --yes install e2fsprogs genext2fs mmdebstrap openssh-client sleepenh qemu-kvm + - apt-get --no-install-recommends --yes install e2fsprogs genext2fs mmdebstrap openssh-client qemu-kvm - PATH=.:$PATH ./tests/create-and-run.sh $(dpkg --print-architecture) "$RELEASE" arch_test: @@ -45,5 +45,5 @@ arch_test: - test -e /proc/sys/fs/binfmt_misc/status || mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc - apt-get update - apt-get dist-upgrade --yes - - apt-get --no-install-recommends --yes install e2fsprogs genext2fs mmdebstrap openssh-client sleepenh qemu-system binfmt-support arch-test qemu-user-static + - apt-get --no-install-recommends --yes install e2fsprogs genext2fs mmdebstrap openssh-client qemu-system binfmt-support arch-test qemu-user-static - PATH=.:$PATH ./tests/create-and-run.sh "$ARCHITECTURE" sid diff --git a/debvm-create b/debvm-create index 5ddbd2f..541519b 100755 --- a/debvm-create +++ b/debvm-create @@ -11,7 +11,7 @@ debvm-create - Create a VM image for various Debian releases and architectures =head1 SYNOPSIS -B<debvm-create> [B<-a> I<architecture>] [B<-h> I<hostname>] [B<-k> I<sshkey>] [B<-m> I<mirror>] [B<-o> I<output>] [B<-p> I<package>] [B<-r> I<release>] [B<-s> <task>] [B<-z> I<size_in_GB>] [B<--> I<mmdebstrap options>] +B<debvm-create> [B<-a> I<architecture>] [B<-h> I<hostname>] [B<-k> F<sshkey>] [B<-m> I<mirror>] [B<-o> F<output>] [B<-p> I<package>] [B<-r> I<release>] [B<-s> <task>] [B<-z> I<size_in_GB>] [B<--> I<mmdebstrap options>] =head1 DESCRIPTION @@ -37,7 +37,7 @@ A suitable kernel image is automatically selected and installed into the image. Set the hostname of the virtual machine. By default, the hostname is B<testvm>. -=item B<-k> I<sshkey>, B<--sshkey>=I<sshkey> +=item B<-k> F<sshkey>, B<--sshkey>=F<sshkey> Install the given ssh public key file into the virtual machine image for the root user. This option also causes the ssh server to be installed. @@ -47,12 +47,12 @@ To connect to the vm, pass a port number to B<debvm-run> with the B<-s> option. =item B<-m> I<mirror>, B<--mirror>=I<mirror> Specify the Debian mirror to be used for downloading packages and to be configured inside the virtual machine image. -By default, B<http://deb.debian.org/debian> is being used. +By default, L<http://deb.debian.org/debian> is being used. -=item B<-o> I<output>, B<--output>=I<output> +=item B<-o> F<output>, B<--output>=F<output> Specify the file name of the resulting virtual machine image. -By default, it is written to B<rootfs.ext4>. +By default, it is written to F<rootfs.ext4>. =item B<-p> I<package>, B<--package>=I<package> @@ -365,6 +365,11 @@ if test "$DEBVER" -ge 12 && ! check_skip usrmerge; then set -- --hook-dir=/usr/share/mmdebstrap/hooks/merged-usr "$@" fi +set -- \ + '--customize-hook=mkdir "$1/etc/systemd/system/serial-getty@.service.d"' \ + "--customize-hook=sed -n -e '1i[Service]' -e '1iExecStart=' -e 's,^ExecStart=-/sbin/agetty ,&-a root ,p'"' "$1/lib/systemd/system/serial-getty@.service" > "$1/etc/systemd/system/serial-getty@.service.d/autologin.conf"' \ + "$@" + # suite target mirror set -- "$@" "$SUITE" "$IMAGE" "deb $MIRROR $SUITE main" @@ -9,14 +9,14 @@ debvm-run - Run a VM image created by debvm-create =head1 SYNOPSIS -B<debvm-run> [B<-g>] [B<-i> I<image>] [B<-s> I<sshport>] [B<--> I<qemu options>] +B<debvm-run> [B<-g>] [B<-i> F<image>] [B<-s> I<sshport>] [B<--> I<qemu options>] =head1 DESCRIPTION B<debvm-run> is essentially a thin wrapper around B<qemu> for running a virtual machine image created by B<debvm-create> or something compatible. The virtual machine image is expected to be a raw ext4 image with file system label B<debvm>. -The architecture of the machine is detected from the contained B</bin/true>. -It must contain a symbolic link pointing to a kernel image at B</vmlinuz> or B</vmlinux> depending on the architecture and a symbolic link pointing to an initrd image at B</initrd.img>. +The architecture of the machine is detected from the contained F</bin/true>. +It must contain a symbolic link pointing to a kernel image at F</vmlinuz> or F</vmlinux> depending on the architecture and a symbolic link pointing to an initrd image at F</initrd.img>. Both are extracted and passed to B<qemu>. A net interface configured for user mode is added automatically. @@ -29,10 +29,10 @@ A net interface configured for user mode is added automatically. By default, the option B<-nographic> is passed to B<qemu> and one interacts with the serial console of the machine. This configuration is skipped in the presence of this option. -=item B<-i> I<image>, B<--image>=I<image> +=item B<-i> F<image>, B<--image>=F<image> This option specifies the location of the virtual machine image file. -By default B<rootfs.ext4> in the working directory is used. +By default F<rootfs.ext4> in the working directory is used. =item B<-s> I<sshport>, B<--sshport>=I<sshport> @@ -49,6 +49,32 @@ One possible use of this method is passing B<-snapshot> to avoid modifying the v =back +=head1 EXAMPLES + +Run a virtual machine stored in the image F<rootfs.ext4> (the default) with +local port 8022 routed to port 22 of the virtual machine. The B<-snapshot> +argument is passed to QEMU and prevents any permanent changes to +F<rootfs.ext4>, resulting in an ephemeral run. + + debvm-run -s 8022 -i rootfs.ext4 -- -snapshot + +=head1 FAQ + +=over 8 + +=item The debvm-run console renders wrong. + +Get C<echo $LINES $COLUMNS> from an other terminal and run C<stty rows $LINES cols $COLUMNS> in the console or use ssh. +Another option is to run C<eval $(resize)>, which is available from the B<xterm> package. +Also set C<$TERM> to the outside value. + +=item How can I kill debvm-run? + +The wrapped B<qemu> can be terminated by pressing Ctrl-a x. +Refer to the B<qemu> manual page for more escape sequences. + +=back + =head1 LIMITATIONS Due to the way kernel and bootloader are being extracted before running B<qemu>, one cannot upgrade a kernel and then just reboot. @@ -123,7 +149,7 @@ while getopts :gi:s:-: OPTCHAR; do usage_error "missing argument for -$OPTARG" ;; '?') - usage_erro "unrecognized option -$OPTARG" + usage_error "unrecognized option -$OPTARG" ;; *) die "internal error while parsing command options, please report a bug" diff --git a/debvm-waitssh b/debvm-waitssh new file mode 100755 index 0000000..82eb14d --- /dev/null +++ b/debvm-waitssh @@ -0,0 +1,178 @@ +#!/bin/sh +# Copyright 2023 Helmut Grohne <helmut@subdivi.de> +# SPDX-License-Identifier: MIT + +: <<'POD2MAN' +=head1 NAME + +debvm-waitssh - Wait for a ssh server to be reachable + +=head1 SYNOPSIS + +B<debvm-waitssh> [B<-q>] [B<-t> I<timeout>] [I<hostname>:]I<port> + +=head1 DESCRIPTION + +B<debvm-waitssh> can be used to wait for a virtual machine with exposed ssh port to be reachable on that port. +If no hostname is given, B<127.0.0.1> is assumed. No authentication is attempted by B<debvm-waitssh>, so neither +a username nor a key have to be supplied. + +=head1 OPTIONS + +=over 8 + +=item B<-t> I<timeout>, B<--timeout>=I<timeout> + +Set the maximum duration for waiting in seconds. +Defaults to one minute. + +=item B<-q>, B<--quiet> + +Be quiet. +Do not output a message when the timeout has been reached without success. + +=back + +=head1 EXIT VALUES + +=over 8 + +=item B<0> + +The server is reachable. + +=item B<1> + +A timeout was reached before the server answered. + +=item B<2> + +Usage error. + +=back + +=head1 SEE ALSO + + debvm-run(1) + +=cut +POD2MAN + +set -u + +TOTALTIMEOUT=60 +SCANTIMEOUT=10 +SCANDELAY=1 +VERBOSITY=1 + +nth_arg() { + shift "$1" + printf "%s" "$1" +} + +die() { + echo "$*" >&2 + exit 2 +} +usage() { + die "usage: $0 [-q] [-t <timeout>] [<host>:]<port>" +} +usage_error() { + echo "error: $*" >&2 + usage +} + +opt_help() { + # shellcheck disable=SC2317 # not dead, called as "opt_$OPTARG" + usage +} +opt_quiet() { + VERBOSITY=0 +} +opt_timeout() { + TOTALTIMEOUT=$1 +} + +while getopts :qt:-: OPTCHAR; do + case "$OPTCHAR" in + q) opt_quiet ;; + t) opt_timeout "$OPTARG" ;; + -) + case "$OPTARG" in + help|quiet) + "opt_$OPTARG" + ;; + timeout) + test "$OPTIND" -gt "$#" && usage_error "missing argument for --$OPTARG" + "opt_$OPTARG" "$(nth_arg "$OPTIND" "$@")" + OPTIND=$((OPTIND+1)) + ;; + timeout=) + "opt_${OPTARG%%=*}" "${OPTARG#*=}" + ;; + *) + usage_error "unrecognized option --$OPTARG" + ;; + esac + ;; + :) + usage_error "missing argument for -$OPTARG" + ;; + '?') + usage_error "unrecognized option -$OPTARG" + ;; + *) + die "internal error while parsing command options, please report a bug" + ;; + esac +done +shift "$((OPTIND - 1))" + +test "$#" = 1 || usage + +case "$1" in + "") + usage + ;; + *:*) + HOST=${1%:*} + PORT=${1##*:} + ;; + *) + HOST=127.0.0.1 + PORT=$1 + ;; +esac + +case "$HOST" in *@*) + die "$0: hostname '$HOST' must not contain the '@' character. No username is required." +;; esac + +# Guard against strings containing anything but digits, strings starting with +# zero and empty strings as the port number. +# +# We cannot use [!0-9] because that matches on any character (or possibly +# multi-character collation element) that sorts in between 0 and 9. +case "$PORT" in *[!0123456789]*|0?*|""|??????*) + die "$0: port '$PORT' is not an integer between 1 and 65535" +;; esac +if test "$PORT" -lt 1 -o "$PORT" -gt 65535; then + die "$0: port '$PORT' is not an integer between 1 and 65535" +fi + +now=$(date +%s) +deadline=$((now + TOTALTIMEOUT)) +while test "$now" -lt "$deadline"; do + start=$now + ssh-keyscan -t rsa -T "$SCANTIMEOUT" -p "$PORT" "$HOST" >/dev/null 2>&1 && exit 0 + now=$(date +%s) + if test "$((now - start))" -lt "$SCANTIMEOUT"; then + sleep "$SCANDELAY" + now=$(date +%s) + fi +done +if [ "$VERBOSITY" -ge 1 ]; then + echo "$0: timeout reached trying to contact $HOST:$PORT after waiting $TOTALTIMEOUT seconds." >&2 +fi +exit 1 + diff --git a/tests/create-and-run.sh b/tests/create-and-run.sh index 540e6c4..f978052 100755 --- a/tests/create-and-run.sh +++ b/tests/create-and-run.sh @@ -26,6 +26,6 @@ SSH_PORT=2222 timeout 240s debvm-run -s "$SSH_PORT" -i "$IMAGE" & set -- localhost test "$RELEASE" = jessie && set -- -o PubkeyAcceptedKeyTypes=+ssh-rsa "$@" -wait_ssh "$@" +debvm-waitssh -t 150 "$SSH_PORT" run_ssh "$@" poweroff wait diff --git a/tests/dist-upgrades.sh b/tests/dist-upgrades.sh index 85c9f4a..177712b 100755 --- a/tests/dist-upgrades.sh +++ b/tests/dist-upgrades.sh @@ -44,12 +44,12 @@ for RELEASE in stretch buster bullseye bookworm sid; do timeout 15m debvm-run -s "$SSH_PORT" & set -- localhost test "$RELEASE" = stretch && set -- -o PubkeyAcceptedKeyTypes=+ssh-rsa "$@" - wait_ssh "$@" + debvm-waitssh -t 150 "$SSH_PORT" run_ssh "$@" "upgrade $RELEASE" wait done timeout 5m debvm-run -s "$SSH_PORT" & -wait_ssh localhost +debvm-waitssh -t 150 "$SSH_PORT" run_ssh localhost poweroff wait diff --git a/tests/test_common.sh b/tests/test_common.sh index f42a26a..cba9693 100644 --- a/tests/test_common.sh +++ b/tests/test_common.sh @@ -5,14 +5,3 @@ run_ssh() { test -n "${SSH_PORT:-}" && set -- -p "$SSH_PORT" "$@" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l root "$@" } - -wait_ssh() { - wait_ssh_timeout=5 - wait_ssh_ts=$(sleepenh 0 || [ $? -eq 1 ]) - for _ in $(seq 30); do - run_ssh -o ConnectTimeout="$wait_ssh_timeout" "$@" echo success && return 0 - wait_ssh_ts=$(sleepenh "$wait_ssh_ts" "$wait_ssh_timeout" || [ $? -eq 1 ]) - done - echo "timeout reached" >&2 - return 1 -} |