]> git.ipfire.org Git - thirdparty/dracut.git/blob - test/TEST-40-NBD/test.sh
ci: run the integration tests on more distributions
[thirdparty/dracut.git] / test / TEST-40-NBD / test.sh
1 #!/bin/bash
2
3 if [[ $NM ]]; then
4 USE_NETWORK="network-manager"
5 OMIT_NETWORK="network-legacy"
6 else
7 USE_NETWORK="network-legacy"
8 OMIT_NETWORK="network-manager"
9 fi
10
11 # shellcheck disable=SC2034
12 TEST_DESCRIPTION="root filesystem on NBD with $USE_NETWORK"
13
14 KVERSION=${KVERSION-$(uname -r)}
15
16 # Uncomment this to debug failures
17 # DEBUGFAIL="rd.debug systemd.log_target=console loglevel=7"
18 #DEBUGFAIL="rd.shell rd.break rd.debug systemd.log_target=console loglevel=7 systemd.log_level=debug"
19 #SERIAL="tcp:127.0.0.1:9999"
20
21 test_check() {
22 if ! type -p nbd-server &> /dev/null; then
23 echo "Test needs nbd-server... Skipping"
24 return 1
25 fi
26
27 if ! modinfo -k "$KVERSION" nbd &> /dev/null; then
28 echo "Kernel module nbd does not exist"
29 return 1
30 fi
31
32 return 0
33 }
34
35 run_server() {
36 # Start server first
37 echo "NBD TEST SETUP: Starting DHCP/NBD server"
38
39 declare -a disk_args=()
40 # shellcheck disable=SC2034
41 declare -i disk_index=0
42 qemu_add_drive_args disk_index disk_args "$TESTDIR"/unencrypted.img unencrypted
43 qemu_add_drive_args disk_index disk_args "$TESTDIR"/encrypted.img encrypted
44 qemu_add_drive_args disk_index disk_args "$TESTDIR"/server.img serverroot
45
46 "$testdir"/run-qemu \
47 "${disk_args[@]}" \
48 -serial "${SERIAL:-"file:$TESTDIR/server.log"}" \
49 -net nic,macaddr=52:54:00:12:34:56,model=e1000 \
50 -net socket,listen=127.0.0.1:12340 \
51 -append "panic=1 oops=panic softlockup_panic=1 rd.luks=0 systemd.crash_reboot quiet root=/dev/disk/by-id/ata-disk_serverroot rootfstype=ext3 rw console=ttyS0,115200n81 selinux=0 $SERVER_DEBUG" \
52 -initrd "$TESTDIR"/initramfs.server \
53 -pidfile "$TESTDIR"/server.pid -daemonize || return 1
54 chmod 644 "$TESTDIR"/server.pid || return 1
55
56 # Cleanup the terminal if we have one
57 tty -s && stty sane
58
59 if ! [[ $SERIAL ]]; then
60 echo "Waiting for the server to startup"
61 while :; do
62 grep Serving "$TESTDIR"/server.log && break
63 tail "$TESTDIR"/server.log
64 sleep 1
65 done
66 else
67 echo Sleeping 10 seconds to give the server a head start
68 sleep 10
69 fi
70 }
71
72 client_test() {
73 local test_name="$1"
74 local mac=$2
75 local cmdline="$3"
76 local fstype=$4
77 local fsopt=$5
78 local found opts nbdinfo
79
80 [[ $fstype ]] || fstype=ext3
81 [[ $fsopt ]] || fsopt="ro"
82
83 echo "CLIENT TEST START: $test_name"
84
85 dd if=/dev/zero of="$TESTDIR"/marker.img bs=1MiB count=1
86 declare -a disk_args=()
87 declare -i disk_index=0
88 qemu_add_drive_args disk_index disk_args "$TESTDIR"/marker.img marker
89
90 "$testdir"/run-qemu \
91 "${disk_args[@]}" \
92 -net nic,macaddr="$mac",model=e1000 \
93 -net socket,connect=127.0.0.1:12340 \
94 -append "panic=1 oops=panic softlockup_panic=1 systemd.crash_reboot rd.shell=0 $cmdline $DEBUGFAIL rd.auto rd.info rd.retry=10 ro console=ttyS0,115200n81 selinux=0 " \
95 -initrd "$TESTDIR"/initramfs.testing
96
97 # shellcheck disable=SC2181
98 if [[ $? -ne 0 ]] || ! grep -U --binary-files=binary -F -m 1 -q nbd-OK "$TESTDIR"/marker.img; then
99 echo "CLIENT TEST END: $test_name [FAILED - BAD EXIT]"
100 return 1
101 fi
102
103 # nbdinfo=( fstype fsoptions )
104 read -r -a nbdinfo < <(awk '{print $2, $3; exit}' "$TESTDIR"/marker.img)
105
106 if [[ ${nbdinfo[0]} != "$fstype" ]]; then
107 echo "CLIENT TEST END: $test_name [FAILED - WRONG FS TYPE] \"${nbdinfo[0]}\" != \"$fstype\""
108 return 1
109 fi
110
111 opts=${nbdinfo[1]},
112 while [[ $opts ]]; do
113 if [[ ${opts%%,*} == "$fsopt" ]]; then
114 found=1
115 break
116 fi
117 opts=${opts#*,}
118 done
119
120 if [[ ! $found ]]; then
121 echo "CLIENT TEST END: $test_name [FAILED - BAD FS OPTS] \"${nbdinfo[1]}\" != \"$fsopt\""
122 return 1
123 fi
124
125 echo "CLIENT TEST END: $test_name [OK]"
126 }
127
128 test_run() {
129 if ! run_server; then
130 echo "Failed to start server" 1>&2
131 return 1
132 fi
133 client_run
134 kill_server
135 }
136
137 client_run() {
138 # The default is ext3,errors=continue so use that to determine
139 # if our options were parsed and used
140 client_test "NBD root=nbd:IP:port" 52:54:00:12:34:00 \
141 "root=nbd:192.168.50.1:raw rd.luks=0" || return 1
142
143 client_test "NBD root=nbd:IP:port::fsopts" 52:54:00:12:34:00 \
144 "root=nbd:192.168.50.1:raw::errors=panic rd.luks=0" \
145 ext3 errors=panic || return 1
146
147 client_test "NBD root=nbd:IP:port:fstype" 52:54:00:12:34:00 \
148 "root=nbd:192.168.50.1:raw:ext3 rd.luks=0" ext3 || return 1
149
150 client_test "NBD root=nbd:IP:port:fstype:fsopts" 52:54:00:12:34:00 \
151 "root=nbd:192.168.50.1:raw:ext3:errors=panic rd.luks=0" \
152 ext3 errors=panic || return 1
153
154 # DHCP root-path parsing
155
156 client_test "NBD root=/dev/root netroot=dhcp DHCP root-path nbd:srv:port" 52:54:00:12:34:01 \
157 "root=/dev/root netroot=dhcp ip=dhcp rd.luks=0" || return 1
158
159 client_test "NBD root=/dev/root netroot=dhcp DHCP root-path nbd:srv:port:fstype" \
160 52:54:00:12:34:02 "root=/dev/root netroot=dhcp ip=dhcp rd.luks=0" ext2 || return 1
161
162 client_test "NBD root=/dev/root netroot=dhcp DHCP root-path nbd:srv:port::fsopts" \
163 52:54:00:12:34:03 "root=/dev/root netroot=dhcp ip=dhcp rd.luks=0" ext3 errors=panic || return 1
164
165 client_test "NBD root=/dev/root netroot=dhcp DHCP root-path nbd:srv:port:fstype:fsopts" \
166 52:54:00:12:34:04 "root=/dev/root netroot=dhcp ip=dhcp rd.luks=0" ext2 errors=panic || return 1
167
168 # netroot handling
169
170 client_test "NBD netroot=nbd:IP:port" 52:54:00:12:34:00 \
171 "root=LABEL=dracut netroot=nbd:192.168.50.1:raw ip=dhcp rd.luks=0" || return 1
172
173 client_test "NBD root=/dev/root netroot=dhcp DHCP root-path nbd:srv:port:fstype:fsopts" \
174 52:54:00:12:34:04 "root=/dev/root netroot=dhcp ip=dhcp rd.luks=0" ext2 errors=panic || return 1
175
176 # Encrypted root handling via LVM/LUKS over NBD
177
178 # shellcheck disable=SC1090
179 . "$TESTDIR"/luks.uuid
180
181 client_test "NBD root=LABEL=dracut netroot=nbd:IP:port" \
182 52:54:00:12:34:00 \
183 "root=LABEL=dracut rd.luks.uuid=$ID_FS_UUID rd.lv.vg=dracut ip=dhcp netroot=nbd:192.168.50.1:encrypted" || return 1
184
185 # XXX This should be ext3,errors=panic but that doesn't currently
186 # XXX work when you have a real root= line in addition to netroot=
187 # XXX How we should work here needs clarification
188 # client_test "NBD root=LABEL=dracut netroot=dhcp (w/ fstype and opts)" \
189 # 52:54:00:12:34:05 \
190 # "root=LABEL=dracut rd.luks.uuid=$ID_FS_UUID rd.lv.vg=dracut netroot=dhcp" || return 1
191
192 if [[ -s server.pid ]]; then
193 kill -TERM "$(cat "$TESTDIR"/server.pid)"
194 rm -f -- "$TESTDIR"/server.pid
195 fi
196
197 }
198
199 make_encrypted_root() {
200 rm -fr "$TESTDIR"/overlay
201 kernel=$KVERSION
202 # Create what will eventually be our root filesystem onto an overlay
203 (
204 # shellcheck disable=SC2030
205 export initdir=$TESTDIR/overlay/source
206 # shellcheck disable=SC1090
207 . "$basedir"/dracut-init.sh
208 mkdir -p "$initdir"
209 (
210 cd "$initdir" || exit
211 mkdir -p dev sys proc etc run var/run tmp
212 )
213
214 inst_multiple sh df free ls shutdown poweroff stty cat ps ln ip \
215 mount dmesg mkdir cp ping dd sync
216 for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
217 [ -f ${_terminfodir}/l/linux ] && break
218 done
219 inst_multiple -o ${_terminfodir}/l/linux
220
221 inst_simple "${basedir}/modules.d/99base/dracut-lib.sh" "/lib/dracut-lib.sh"
222 inst_binary "${basedir}/dracut-util" "/usr/bin/dracut-util"
223 ln -s dracut-util "${initdir}/usr/bin/dracut-getarg"
224 ln -s dracut-util "${initdir}/usr/bin/dracut-getargs"
225
226 inst ./client-init.sh /sbin/init
227 inst_simple /etc/os-release
228 find_binary plymouth > /dev/null && inst_multiple plymouth
229 cp -a /etc/ld.so.conf* "$initdir"/etc
230 ldconfig -r "$initdir"
231 )
232
233 # second, install the files needed to make the root filesystem
234 (
235 # shellcheck disable=SC2030
236 # shellcheck disable=SC2031
237 export initdir=$TESTDIR/overlay
238 # shellcheck disable=SC1090
239 . "$basedir"/dracut-init.sh
240 (
241 cd "$initdir" || exit
242 mkdir -p dev sys proc etc tmp var run root
243 ln -s ../run var/run
244 )
245 inst_multiple mkfs.ext3 poweroff cp umount dd sync
246 inst_hook shutdown-emergency 000 ./hard-off.sh
247 inst_hook emergency 000 ./hard-off.sh
248 inst_hook initqueue 01 ./create-encrypted-root.sh
249 inst_hook initqueue/finished 01 ./finished-false.sh
250 )
251
252 # create an initramfs that will create the target root filesystem.
253 # We do it this way so that we do not risk trashing the host mdraid
254 # devices, volume groups, encrypted partitions, etc.
255 "$basedir"/dracut.sh -l -i "$TESTDIR"/overlay / \
256 -m "dash crypt lvm mdraid udev-rules base rootfs-block fs-lib kernel-modules qemu" \
257 -d "piix ide-gd_mod ata_piix ext3 ext3 sd_mod" \
258 --no-hostonly-cmdline -N \
259 -f "$TESTDIR"/initramfs.makeroot "$KVERSION" || return 1
260 rm -rf -- "$TESTDIR"/overlay
261
262 dd if=/dev/zero of="$TESTDIR"/encrypted.img bs=1MiB count=120
263 dd if=/dev/zero of="$TESTDIR"/marker.img bs=1MiB count=1
264 declare -a disk_args=()
265 # shellcheck disable=SC2034
266 declare -i disk_index=0
267 qemu_add_drive_args disk_index disk_args "$TESTDIR"/marker.img marker
268 qemu_add_drive_args disk_index disk_args "$TESTDIR"/encrypted.img root
269
270 # Invoke KVM and/or QEMU to actually create the target filesystem.
271 "$testdir"/run-qemu \
272 "${disk_args[@]}" \
273 -append "root=/dev/fakeroot rw quiet console=ttyS0,115200n81 selinux=0" \
274 -initrd "$TESTDIR"/initramfs.makeroot || return 1
275 grep -U --binary-files=binary -F -m 1 -q dracut-root-block-created "$TESTDIR"/marker.img || return 1
276 grep -F -a -m 1 ID_FS_UUID "$TESTDIR"/marker.img > "$TESTDIR"/luks.uuid
277 }
278
279 make_client_root() {
280 rm -fr "$TESTDIR"/overlay
281 kernel=$KVERSION
282 (
283 mkdir -p "$TESTDIR"/overlay/source
284 # shellcheck disable=SC2030
285 # shellcheck disable=SC2031
286 export initdir=$TESTDIR/overlay/source
287 # shellcheck disable=SC1090
288 . "$basedir"/dracut-init.sh
289 mkdir -p "$initdir"
290 (
291 cd "$initdir" || exit
292 mkdir -p dev sys proc etc run var/run tmp
293 )
294 inst_multiple sh ls shutdown poweroff stty cat ps ln ip \
295 dmesg mkdir cp ping dd mount sync
296 for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
297 [ -f ${_terminfodir}/l/linux ] && break
298 done
299 inst_multiple -o ${_terminfodir}/l/linux
300
301 inst_simple "${basedir}/modules.d/99base/dracut-lib.sh" "/lib/dracut-lib.sh"
302 inst_binary "${basedir}/dracut-util" "/usr/bin/dracut-util"
303 ln -s dracut-util "${initdir}/usr/bin/dracut-getarg"
304 ln -s dracut-util "${initdir}/usr/bin/dracut-getargs"
305
306 inst ./client-init.sh /sbin/init
307 inst_simple /etc/os-release
308 inst_multiple -o {,/usr}/etc/nsswitch.conf
309 inst /etc/passwd /etc/passwd
310 inst /etc/group /etc/group
311 for i in /usr/lib*/libnss_files* /lib*/libnss_files*; do
312 [ -e "$i" ] || continue
313 inst "$i"
314 done
315 cp -a /etc/ld.so.conf* "$initdir"/etc
316 ldconfig -r "$initdir"
317 )
318
319 # second, install the files needed to make the root filesystem
320 (
321 # shellcheck disable=SC2030
322 # shellcheck disable=SC2031
323 export initdir=$TESTDIR/overlay
324 # shellcheck disable=SC1090
325 . "$basedir"/dracut-init.sh
326 inst_multiple sfdisk mkfs.ext3 poweroff cp umount sync dd
327 inst_hook initqueue 01 ./create-client-root.sh
328 inst_hook initqueue/finished 01 ./finished-false.sh
329 )
330
331 # create an initramfs that will create the target root filesystem.
332 # We do it this way so that we do not risk trashing the host mdraid
333 # devices, volume groups, encrypted partitions, etc.
334 "$basedir"/dracut.sh -l -i "$TESTDIR"/overlay / \
335 -m "dash udev-rules base rootfs-block fs-lib kernel-modules fs-lib qemu" \
336 -d "piix ide-gd_mod ata_piix ext3 sd_mod" \
337 --nomdadmconf \
338 --no-hostonly-cmdline -N \
339 -f "$TESTDIR"/initramfs.makeroot "$KVERSION" || return 1
340
341 dd if=/dev/zero of="$TESTDIR"/unencrypted.img bs=1MiB count=120
342 dd if=/dev/zero of="$TESTDIR"/marker.img bs=1MiB count=1
343 declare -a disk_args=()
344 # shellcheck disable=SC2034
345 declare -i disk_index=0
346 qemu_add_drive_args disk_index disk_args "$TESTDIR"/marker.img marker
347 qemu_add_drive_args disk_index disk_args "$TESTDIR"/unencrypted.img root
348
349 # Invoke KVM and/or QEMU to actually create the target filesystem.
350 "$testdir"/run-qemu \
351 "${disk_args[@]}" \
352 -append "root=/dev/dracut/root rw rootfstype=ext3 quiet console=ttyS0,115200n81 selinux=0" \
353 -initrd "$TESTDIR"/initramfs.makeroot || return 1
354 grep -U --binary-files=binary -F -m 1 -q dracut-root-block-created "$TESTDIR"/marker.img || return 1
355 rm -fr "$TESTDIR"/overlay
356 }
357
358 make_server_root() {
359 rm -fr "$TESTDIR"/overlay
360 # shellcheck disable=SC2031
361 export kernel=$KVERSION
362 (
363 mkdir -p "$TESTDIR"/overlay/source
364 # shellcheck disable=SC2030
365 # shellcheck disable=SC2031
366 export initdir=$TESTDIR/overlay/source
367 # shellcheck disable=SC1090
368 . "$basedir"/dracut-init.sh
369 mkdir -p "$initdir"
370 (
371 cd "$initdir" || exit
372 mkdir -p run dev sys proc etc var var/lib/dhcpd tmp etc/nbd-server
373 ln -s ../run var/run
374 )
375 cat > "$initdir/etc/nbd-server/config" << EOF
376 [generic]
377 [raw]
378 exportname = /dev/disk/by-id/ata-disk_unencrypted
379 port = 2000
380 bs = 4096
381 [encrypted]
382 exportname = /dev/disk/by-id/ata-disk_encrypted
383 port = 2001
384 bs = 4096
385 EOF
386 inst_multiple sh ls shutdown poweroff stty cat ps ln ip \
387 dmesg mkdir cp ping grep \
388 sleep nbd-server chmod modprobe vi pidof
389 for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
390 [ -f ${_terminfodir}/l/linux ] && break
391 done
392 inst_multiple -o ${_terminfodir}/l/linux
393 instmods nfsd sunrpc ipv6 lockd af_packet 8021q ipvlan macvlan
394 type -P dhcpd > /dev/null && inst_multiple dhcpd
395 [ -x /usr/sbin/dhcpd3 ] && inst /usr/sbin/dhcpd3 /usr/sbin/dhcpd
396 inst ./server-init.sh /sbin/init
397 inst_simple /etc/os-release
398 inst ./hosts /etc/hosts
399 inst ./dhcpd.conf /etc/dhcpd.conf
400 inst_multiple -o {,/usr}/etc/nsswitch.conf
401 inst /etc/passwd /etc/passwd
402 inst /etc/group /etc/group
403 _nsslibs=$(
404 cat "$dracutsysrootdir"/{,usr/}etc/nsswitch.conf 2> /dev/null \
405 | sed -e '/^#/d' -e 's/^.*://' -e 's/\[NOTFOUND=return\]//' \
406 | tr -s '[:space:]' '\n' | sort -u | tr -s '[:space:]' '|'
407 )
408 _nsslibs=${_nsslibs#|}
409 _nsslibs=${_nsslibs%|}
410
411 inst_libdir_file -n "$_nsslibs" 'libnss_*.so*'
412
413 cp -a /etc/ld.so.conf* "$initdir"/etc
414 ldconfig -r "$initdir"
415 dracut_kernel_post
416 )
417
418 # second, install the files needed to make the root filesystem
419 (
420 # shellcheck disable=SC2030
421 # shellcheck disable=SC2031
422 export initdir=$TESTDIR/overlay
423 # shellcheck disable=SC1090
424 . "$basedir"/dracut-init.sh
425 inst_multiple sfdisk mkfs.ext3 poweroff cp umount sync dd sync
426 inst_hook initqueue 01 ./create-server-root.sh
427 inst_hook initqueue/finished 01 ./finished-false.sh
428 )
429
430 # create an initramfs that will create the target root filesystem.
431 # We do it this way so that we do not risk trashing the host mdraid
432 # devices, volume groups, encrypted partitions, etc.
433 "$basedir"/dracut.sh -l -i "$TESTDIR"/overlay / \
434 -m "dash udev-rules base rootfs-block fs-lib kernel-modules fs-lib qemu" \
435 -d "piix ide-gd_mod ata_piix ext3 sd_mod" \
436 --nomdadmconf \
437 --no-hostonly-cmdline -N \
438 -f "$TESTDIR"/initramfs.makeroot "$KVERSION" || return 1
439
440 dd if=/dev/zero of="$TESTDIR"/server.img bs=1MiB count=120
441 dd if=/dev/zero of="$TESTDIR"/marker.img bs=1MiB count=1
442 declare -a disk_args=()
443 # shellcheck disable=SC2034
444 declare -i disk_index=0
445 qemu_add_drive_args disk_index disk_args "$TESTDIR"/marker.img marker
446 qemu_add_drive_args disk_index disk_args "$TESTDIR"/server.img root
447
448 # Invoke KVM and/or QEMU to actually create the target filesystem.
449 "$testdir"/run-qemu \
450 "${disk_args[@]}" \
451 -append "root=/dev/dracut/root rw rootfstype=ext3 quiet console=ttyS0,115200n81 selinux=0" \
452 -initrd "$TESTDIR"/initramfs.makeroot || return 1
453 grep -U --binary-files=binary -F -m 1 -q dracut-root-block-created "$TESTDIR"/marker.img || return 1
454 rm -fr "$TESTDIR"/overlay
455 }
456
457 test_setup() {
458 make_encrypted_root || return 1
459 make_client_root || return 1
460 make_server_root || return 1
461
462 rm -fr "$TESTDIR"/overlay
463 # Make the test image
464 (
465 # shellcheck disable=SC2031
466 # shellcheck disable=SC2030
467 export initdir=$TESTDIR/overlay
468 # shellcheck disable=SC1090
469 . "$basedir"/dracut-init.sh
470 inst_multiple poweroff shutdown dd
471 inst_hook shutdown-emergency 000 ./hard-off.sh
472 inst ./cryptroot-ask.sh /sbin/cryptroot-ask
473
474 # inst ./debug-shell.service /lib/systemd/system/debug-shell.service
475 # mkdir -p "${initdir}/lib/systemd/system/sysinit.target.wants"
476 # ln -fs ../debug-shell.service "${initdir}/lib/systemd/system/sysinit.target.wants/debug-shell.service"
477
478 # shellcheck disable=SC1090
479 . "$TESTDIR"/luks.uuid
480 mkdir -p "$initdir"/etc
481 echo "luks-$ID_FS_UUID /dev/nbd0 /etc/key" > "$initdir"/etc/crypttab
482 echo -n test > "$initdir"/etc/key
483 inst_simple ./client.link /etc/systemd/network/01-client.link
484 )
485
486 "$basedir"/dracut.sh -l -i "$TESTDIR"/overlay / \
487 -o "plymouth dash iscsi nfs ${OMIT_NETWORK}" \
488 -a "debug watchdog ${USE_NETWORK}" \
489 --no-hostonly-cmdline -N \
490 -f "$TESTDIR"/initramfs.testing "$KVERSION" || return 1
491
492 (
493 # shellcheck disable=SC2031
494 export initdir="$TESTDIR"/overlay
495 # shellcheck disable=SC1090
496 . "$basedir"/dracut-init.sh
497 rm "$initdir"/etc/systemd/network/01-client.link
498 inst_simple ./server.link /etc/systemd/network/01-server.link
499 inst_hook pre-mount 99 ./wait-if-server.sh
500 )
501 "$basedir"/dracut.sh -l -i "$TESTDIR"/overlay / \
502 -a "udev-rules base rootfs-block fs-lib debug kernel-modules network network-legacy" \
503 -d "af_packet piix ide-gd_mod ata_piix ext3 sd_mod e1000 drbg" \
504 --no-hostonly-cmdline -N \
505 -f "$TESTDIR"/initramfs.server "$KVERSION" || return 1
506
507 rm -rf -- "$TESTDIR"/overlay
508 }
509
510 kill_server() {
511 if [[ -s $TESTDIR/server.pid ]]; then
512 kill -TERM "$(cat "$TESTDIR"/server.pid)"
513 rm -f -- "$TESTDIR"/server.pid
514 fi
515 }
516
517 test_cleanup() {
518 kill_server
519 }
520
521 # shellcheck disable=SC1090
522 . "$testdir"/test-functions