File: run_bisect_qemu.sh

package info (click to toggle)
devscripts 2.25.15
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 8,528 kB
  • sloc: perl: 26,530; sh: 11,698; python: 4,428; makefile: 363
file content (205 lines) | stat: -rwxr-xr-x 6,949 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/bin/sh
#
# Copyright 2020 Johannes Schauer Marin Rodrigues <josch@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# this script is part of debbisect and usually called by debbisect itself
#
# it accepts eight or ten arguments:
#    1. dependencies
#    2. script name or shell snippet
#    3. mirror URL
#    4. architecture
#    5. suite
#    6. components
#    7. memsize
#    8. disksize
#    9. (optional) second mirror URL
#   10. (optional) package to upgrade
#
# It will create an ephemeral qemu virtual machine using mmdebstrap and
# guestfish using (3.) as mirror, (4.) as architecture, (5.) as suite and
# (6.) as components, install the dependencies given in (1.) and execute the
# script given in (2.).
# Its output is the exit code of the script as well as a file ./pkglist
# containing the output of "dpkg-query -W" inside the chroot.
#
# If not only six but eight arguments are given, then the second mirror URL
# (9.) will be added to the apt sources and the single package (10.) will be
# upgraded to its version from (9.).
#
# shellcheck disable=SC2016

set -exu

if [ $# -ne 8 ] && [ $# -ne 10 ]; then
	echo "usage: $0 depends script mirror1 architecture suite components memsize disksize [mirror2 toupgrade]"
	exit 1
fi

depends=$1
script=$2
mirror1=$3
architecture=$4
suite=$5
components=$6
memsize=$7
disksize=$8

if [ $# -eq 10 ]; then
	mirror2=$9
	toupgrade=${10}
fi

TMPDIR=$(mktemp --tmpdir --directory debbisect_qemu.XXXXXXXXXX)
cleantmp() {
	for f in customize.sh id_rsa id_rsa.pub qemu.log config; do
		rm -f "$TMPDIR/$f"
	done
	rmdir "$TMPDIR"
}

trap cleantmp EXIT
# the temporary directory must be world readable (for example in unshare mode)
chmod a+xr "$TMPDIR"

ssh-keygen -q -t rsa -f "$TMPDIR/id_rsa" -N ""

# The following hacks are needed to go back as far as 2006-08-10:
#
#  - Acquire::Check-Valid-Until "false" allows Release files with an expired
#    Valid-Until dates
#  - Apt::Key::gpgvcommand allows expired GPG keys
#  - Apt::Hashes::SHA1::Weak "yes" allows GPG keys with weak SHA1 signature
#  - /usr/share/keyrings lets apt use debian-archive-removed-keys.gpg
#  - /usr/share/mmdebstrap/hooks/jessie-or-older performs some setup that is
#    only required for Debian Jessie or older
#
debvm-create --skip=usrmerge --size="$disksize" \
	--sshkey="$TMPDIR/id_rsa.pub" --release="$suite" \
	--output="debian-rootfs.img" -- \
	--architecture="$architecture" \
	--components="$components" \
	--aptopt='Acquire::Check-Valid-Until "false"' \
	--aptopt='Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"' \
	--aptopt='Apt::Hashes::SHA1::Weak "yes"' \
	--keyring=/usr/share/keyrings \
	--hook-dir=/usr/share/mmdebstrap/hooks/maybe-jessie-or-older \
	--hook-dir=/usr/share/mmdebstrap/hooks/maybe-merged-usr \
	--skip=check/signed-by \
	"$mirror1"

timeout --kill-after=60s 60m \
	debvm-run --image="debian-rootfs.img" \
	--sshport=10022 -- \
	-m "$memsize" \
	-serial mon:stdio \
	> "$TMPDIR/qemu.log" </dev/null 2>&1 &

# store the pid
QEMUPID=$!

# use a function here, so that we can properly quote the path to qemu.log
showqemulog() {
	cat --show-nonprinting "$TMPDIR/qemu.log"
}

# show the log and kill qemu in case the script exits first
trap 'showqemulog; cleantmp; kill $QEMUPID' EXIT

# the default ssh command does not store known hosts and even ignores host keys
# it identifies itself with the rsa key generated above
# pseudo terminal allocation is disabled or otherwise, programs executed via
# ssh might wait for input on stdin of the ssh process

cat << END > "$TMPDIR/config"
Host qemu
	Hostname 127.0.0.1
	User root
	Port 10022
	UserKnownHostsFile /dev/null
	StrictHostKeyChecking no
	IdentityFile $TMPDIR/id_rsa
	RequestTTY no
END

debvm-waitssh 10022

# we install dependencies now and not with mmdebstrap --include in case some
# dependencies require a full system present
if [ -n "$depends" ]; then
	ssh -F "$TMPDIR/config" qemu apt-get update
	# shellcheck disable=SC2046,SC2086
	ssh -F "$TMPDIR/config" qemu env DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true apt-get --yes install --no-install-recommends $(echo $depends | tr ',' ' ')
fi

# in its ten-argument form, a single package has to be upgraded to its
# version from the first bad timestamp
if [ $# -eq 10 ]; then
	# replace content of sources.list with first bad timestamp
	mirror2=$(echo "$mirror2" | sed 's/http:\/\/127.0.0.1:/http:\/\/10.0.2.2:/')
	echo "deb $mirror2 $suite $(echo "$components" | tr ',' ' ')" | ssh -F "$TMPDIR/config" qemu "cat > /etc/apt/sources.list"
	ssh -F "$TMPDIR/config" qemu apt-get update
	# upgrade a single package (and whatever else apt deems necessary)
	before=$(ssh -F "$TMPDIR/config" qemu dpkg-query -W)
	ssh -F "$TMPDIR/config" qemu env DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true apt-get --yes install --no-install-recommends "$toupgrade"
	after=$(ssh -F "$TMPDIR/config" qemu dpkg-query -W)
	# make sure that something was upgraded
	if [ "$before" = "$after" ]; then
		echo "nothing got upgraded -- this should never happen" >&2
		exit 1
	fi
	ssh -F "$TMPDIR/config" qemu dpkg-query -W > "./debbisect.$DEBIAN_BISECT_TIMESTAMP.$toupgrade.pkglist"
else
	ssh -F "$TMPDIR/config" qemu dpkg-query -W > "./debbisect.$DEBIAN_BISECT_TIMESTAMP.pkglist"
fi

ssh -F "$TMPDIR/config" qemu dpkg-query --list | cat

# explicitly export all necessary variables
# because we use set -u this also makes sure that this script has these
# variables set in the first place
export DEBIAN_BISECT_EPOCH="$DEBIAN_BISECT_EPOCH"
export DEBIAN_BISECT_TIMESTAMP="$DEBIAN_BISECT_TIMESTAMP"
if [ -z ${DEBIAN_BISECT_MIRROR+x} ]; then
	# DEBIAN_BISECT_MIRROR was unset (caching is disabled)
	true
else
	# replace the localhost IP by the IP of the host as seen by qemu
	DEBIAN_BISECT_MIRROR=$(echo "$DEBIAN_BISECT_MIRROR" | sed 's/http:\/\/127.0.0.1:/http:\/\/10.0.2.2:/')
	export DEBIAN_BISECT_MIRROR="$DEBIAN_BISECT_MIRROR"
fi


# either execute $script as a script from $PATH or as a shell snippet
ret=0
if [ -x "$script" ] || echo "$script" | grep --invert-match --silent --perl-regexp '[^\w@\%+=:,.\/-]'; then
	"$script" "$TMPDIR/config" || ret=$?
else
	sh -c "$script" exec "$TMPDIR/config" || ret=$?
fi

# since we installed systemd-sysv, systemctl is available
ssh -F "$TMPDIR/config" qemu systemctl poweroff

wait $QEMUPID

trap - EXIT

showqemulog
cleantmp

if [ "$ret" -eq 0 ]; then
	exit 0
else
	exit 1
fi