]> git.ipfire.org Git - thirdparty/dracut.git/blob - test/TEST-50-MULTINIC/test.sh
56a12a5d6a93313f36e74c697c9c91136e8c40e4
[thirdparty/dracut.git] / test / TEST-50-MULTINIC / 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 NFS with multiple nics with $USE_NETWORK"
13
14 KVERSION=${KVERSION-$(uname -r)}
15
16 # Uncomment this to debug failures
17 #DEBUGFAIL="rd.shell rd.break"
18 #SERIAL="tcp:127.0.0.1:9999"
19
20 run_server() {
21 # Start server first
22 echo "MULTINIC TEST SETUP: Starting DHCP/NFS server"
23
24 declare -a disk_args=()
25 # shellcheck disable=SC2034
26 declare -i disk_index=0
27 qemu_add_drive_args disk_index disk_args "$TESTDIR"/server.img root
28
29 "$testdir"/run-qemu \
30 "${disk_args[@]}" \
31 -net socket,listen=127.0.0.1:12350 \
32 -net nic,macaddr=52:54:01:12:34:56,model=e1000 \
33 -serial "${SERIAL:-"file:$TESTDIR/server.log"}" \
34 -watchdog i6300esb -watchdog-action poweroff \
35 -append "panic=1 systemd.crash_reboot loglevel=7 root=LABEL=dracut rootfstype=ext3 rw console=ttyS0,115200n81 selinux=0" \
36 -initrd "$TESTDIR"/initramfs.server \
37 -pidfile "$TESTDIR"/server.pid -daemonize || return 1
38
39 chmod 644 -- "$TESTDIR"/server.pid || return 1
40
41 # Cleanup the terminal if we have one
42 tty -s && stty sane
43
44 if ! [[ $SERIAL ]]; then
45 while :; do
46 grep Serving "$TESTDIR"/server.log && break
47 echo "Waiting for the server to startup"
48 tail "$TESTDIR"/server.log
49 sleep 1
50 done
51 else
52 echo Sleeping 10 seconds to give the server a head start
53 sleep 10
54 fi
55 }
56
57 client_test() {
58 local test_name="$1"
59 local mac1="$2"
60 local mac2="$3"
61 local mac3="$4"
62 local cmdline="$5"
63 local check="$6"
64
65 echo "CLIENT TEST START: $test_name"
66
67 dd if=/dev/zero of="$TESTDIR"/marker.img bs=1MiB count=1
68 declare -a disk_args=()
69 # shellcheck disable=SC2034
70 declare -i disk_index=0
71 qemu_add_drive_args disk_index disk_args "$TESTDIR"/marker.img marker
72
73 # Invoke KVM and/or QEMU to actually create the target filesystem.
74 "$testdir"/run-qemu \
75 "${disk_args[@]}" \
76 -net socket,connect=127.0.0.1:12350 \
77 -net nic,macaddr=52:54:00:12:34:"$mac1",model=e1000 \
78 -net nic,macaddr=52:54:00:12:34:"$mac2",model=e1000 \
79 -net nic,macaddr=52:54:00:12:34:"$mac3",model=e1000 \
80 -netdev hubport,id=n1,hubid=1 \
81 -netdev hubport,id=n2,hubid=2 \
82 -device e1000,netdev=n1,mac=52:54:00:12:34:98 \
83 -device e1000,netdev=n2,mac=52:54:00:12:34:99 \
84 -watchdog i6300esb -watchdog-action poweroff \
85 -append "quiet rd.net.timeout.dhcp=3 panic=1 systemd.crash_reboot rd.shell=0 $cmdline $DEBUGFAIL rd.retry=5 ro console=ttyS0,115200n81 selinux=0 init=/sbin/init rd.debug systemd.log_target=console" \
86 -initrd "$TESTDIR"/initramfs.testing || return 1
87
88 {
89 read -r OK
90 read -r IFACES
91 } < "$TESTDIR"/marker.img
92
93 if [[ $OK != "OK" ]]; then
94 echo "CLIENT TEST END: $test_name [FAILED - BAD EXIT]"
95 return 1
96 fi
97
98 for i in $check; do
99 if [[ " $IFACES " != *\ $i\ * ]]; then
100 echo "$i not in '$IFACES'"
101 echo "CLIENT TEST END: $test_name [FAILED - BAD IF]"
102 return 1
103 fi
104 done
105
106 for i in $IFACES; do
107 if [[ " $check " != *\ $i\ * ]]; then
108 echo "$i in '$IFACES', but should not be"
109 echo "CLIENT TEST END: $test_name [FAILED - BAD IF]"
110 return 1
111 fi
112 done
113
114 echo "CLIENT TEST END: $test_name [OK]"
115 return 0
116 }
117
118 test_run() {
119 if ! run_server; then
120 echo "Failed to start server" 1>&2
121 return 1
122 fi
123 test_client
124 ret=$?
125 kill_server
126 return $ret
127 }
128
129 test_client() {
130 # Mac Numbering Scheme
131 # ...:00-02 receive IP adresses all others don't
132 # ...:02 receives a dhcp root-path
133
134 # PXE Style BOOTIF=
135 client_test "MULTINIC root=nfs BOOTIF=" \
136 00 01 02 \
137 "root=nfs:192.168.50.1:/nfs/client BOOTIF=52-54-00-12-34-00" \
138 "enp0s1" || return 1
139
140 client_test "MULTINIC root=nfs BOOTIF= ip=enp0s3:dhcp" \
141 00 01 02 \
142 "root=nfs:192.168.50.1:/nfs/client BOOTIF=52-54-00-12-34-00 ip=enp0s2:dhcp" \
143 "enp0s1 enp0s2" || return 1
144
145 # PXE Style BOOTIF= with dhcp root-path
146 client_test "MULTINIC root=dhcp BOOTIF=" \
147 00 01 02 \
148 "root=dhcp BOOTIF=52-54-00-12-34-02" \
149 "enp0s3" || return 1
150
151 # Multinic case, where only one nic works
152 client_test "MULTINIC root=nfs ip=dhcp" \
153 FF 00 FE \
154 "root=nfs:192.168.50.1:/nfs/client ip=dhcp" \
155 "enp0s2" || return 1
156
157 # Require two interfaces
158 client_test "MULTINIC root=nfs ip=enp0s2:dhcp ip=enp0s3:dhcp bootdev=enp0s2" \
159 00 01 02 \
160 "root=nfs:192.168.50.1:/nfs/client ip=enp0s2:dhcp ip=enp0s3:dhcp bootdev=enp0s2" \
161 "enp0s2 enp0s3" || return 1
162
163 # Require three interfaces with dhcp root-path
164 client_test "MULTINIC root=dhcp ip=enp0s1:dhcp ip=enp0s2:dhcp ip=enp0s3:dhcp bootdev=enp0s3" \
165 00 01 02 \
166 "root=dhcp ip=enp0s1:dhcp ip=enp0s2:dhcp ip=enp0s3:dhcp bootdev=enp0s3" \
167 "enp0s1 enp0s2 enp0s3" || return 1
168
169 client_test "MULTINIC bonding" \
170 00 01 02 \
171 "root=nfs:192.168.50.1:/nfs/client ip=bond0:dhcp bond=bond0:enp0s1,enp0s2,enp0s3:mode=balance-rr" \
172 "bond0" || return 1
173
174 # bridge, where only one interface is actually connected
175 client_test "MULTINIC bridging" \
176 00 01 02 \
177 "root=nfs:192.168.50.1:/nfs/client ip=bridge0:dhcp bridge=bridge0:enp0s1,enp0s5,enp0s6" \
178 "bridge0" || return 1
179 return 0
180 }
181
182 test_setup() {
183 kernel=$KVERSION
184 (
185 mkdir -p "$TESTDIR"/overlay/source
186 # shellcheck disable=SC2030
187 export initdir=$TESTDIR/overlay/source
188 # shellcheck disable=SC1090
189 . "$basedir"/dracut-init.sh
190
191 (
192 cd "$initdir" || exit
193 mkdir -p -- dev sys proc run var/run etc tmp var/lib/{dhcpd,rpcbind}
194 mkdir -p -- var/lib/nfs/{v4recovery,rpc_pipefs}
195 chmod 777 -- var/lib/rpcbind var/lib/nfs
196 )
197
198 for _f in modules.builtin.bin modules.builtin; do
199 [[ -f $srcmods/$_f ]] && break
200 done || {
201 dfatal "No modules.builtin.bin and modules.builtin found!"
202 return 1
203 }
204
205 for _f in modules.builtin.bin modules.builtin modules.order; do
206 [[ -f $srcmods/$_f ]] && inst_simple "$srcmods/$_f" "/lib/modules/$kernel/$_f"
207 done
208
209 inst_multiple sh ls shutdown poweroff stty cat ps ln ip \
210 dmesg mkdir cp ping exportfs \
211 modprobe rpc.nfsd rpc.mountd showmount tcpdump \
212 /etc/services sleep mount chmod
213 for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
214 [ -f "${_terminfodir}"/l/linux ] && break
215 done
216 inst_multiple -o "${_terminfodir}"/l/linux
217 type -P portmap > /dev/null && inst_multiple portmap
218 type -P rpcbind > /dev/null && inst_multiple rpcbind
219 [ -f /etc/netconfig ] && inst_multiple /etc/netconfig
220 type -P dhcpd > /dev/null && inst_multiple dhcpd
221 [ -x /usr/sbin/dhcpd3 ] && inst /usr/sbin/dhcpd3 /usr/sbin/dhcpd
222 instmods nfsd sunrpc ipv6 lockd af_packet
223 inst_simple /etc/os-release
224 inst ./server-init.sh /sbin/init
225 inst ./hosts /etc/hosts
226 inst ./exports /etc/exports
227 inst ./dhcpd.conf /etc/dhcpd.conf
228 inst_multiple /etc/nsswitch.conf /etc/rpc /etc/protocols
229
230 inst_multiple rpc.idmapd /etc/idmapd.conf
231
232 inst_libdir_file 'libnfsidmap_nsswitch.so*'
233 inst_libdir_file 'libnfsidmap/*.so*'
234 inst_libdir_file 'libnfsidmap*.so*'
235
236 _nsslibs=$(sed -e '/^#/d' -e 's/^.*://' -e 's/\[NOTFOUND=return\]//' /etc/nsswitch.conf \
237 | tr -s '[:space:]' '\n' | sort -u | tr -s '[:space:]' '|')
238 _nsslibs=${_nsslibs#|}
239 _nsslibs=${_nsslibs%|}
240
241 inst_libdir_file -n "$_nsslibs" 'libnss_*.so*'
242
243 inst /etc/nsswitch.conf /etc/nsswitch.conf
244 inst /etc/passwd /etc/passwd
245 inst /etc/group /etc/group
246
247 cp -a -- /etc/ld.so.conf* "$initdir"/etc
248 ldconfig -r "$initdir"
249 dracut_kernel_post
250 )
251
252 # Make client root inside server root
253 (
254 # shellcheck disable=SC2030
255 # shellcheck disable=SC2031
256 export initdir=$TESTDIR/overlay/source/nfs/client
257 # shellcheck disable=SC1090
258 . "$basedir"/dracut-init.sh
259 (
260 cd "$initdir" || exit
261 mkdir -p dev sys proc etc run
262 mkdir -p var/lib/nfs/rpc_pipefs
263 mkdir -p root usr/bin usr/lib usr/lib64 usr/sbin
264 for i in bin sbin lib lib64; do
265 ln -sfnr usr/$i $i
266 done
267 )
268 inst_multiple sh shutdown poweroff stty cat ps ln ip \
269 mount dmesg mkdir cp ping grep ls dd sync
270 for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
271 [[ -f ${_terminfodir}/l/linux ]] && break
272 done
273 inst_multiple -o "${_terminfodir}"/l/linux
274 inst_simple /etc/os-release
275
276 inst_simple "${basedir}/modules.d/99base/dracut-lib.sh" "/lib/dracut-lib.sh"
277 inst_binary "${basedir}/dracut-util" "/usr/bin/dracut-util"
278 ln -s dracut-util "${initdir}/usr/bin/dracut-getarg"
279 ln -s dracut-util "${initdir}/usr/bin/dracut-getargs"
280
281 inst ./client-init.sh /sbin/init
282 inst /etc/nsswitch.conf /etc/nsswitch.conf
283 inst /etc/passwd /etc/passwd
284 inst /etc/group /etc/group
285
286 inst_multiple rpc.idmapd /etc/idmapd.conf
287 inst_libdir_file 'libnfsidmap_nsswitch.so*'
288 inst_libdir_file 'libnfsidmap/*.so*'
289 inst_libdir_file 'libnfsidmap*.so*'
290
291 _nsslibs=$(sed -e '/^#/d' -e 's/^.*://' -e 's/\[NOTFOUND=return\]//' -- /etc/nsswitch.conf \
292 | tr -s '[:space:]' '\n' | sort -u | tr -s '[:space:]' '|')
293 _nsslibs=${_nsslibs#|}
294 _nsslibs=${_nsslibs%|}
295
296 inst_libdir_file -n "$_nsslibs" 'libnss_*.so*'
297
298 cp -a -- /etc/ld.so.conf* "$initdir"/etc
299 ldconfig -r "$initdir"
300 )
301
302 # second, install the files needed to make the root filesystem
303 (
304 # shellcheck disable=SC2030
305 # shellcheck disable=SC2031
306 export initdir=$TESTDIR/overlay
307 # shellcheck disable=SC1090
308 . "$basedir"/dracut-init.sh
309 inst_multiple sfdisk mkfs.ext3 poweroff cp umount sync dd
310 inst_hook initqueue 01 ./create-root.sh
311 inst_hook initqueue/finished 01 ./finished-false.sh
312 )
313
314 # create an initramfs that will create the target root filesystem.
315 # We do it this way so that we do not risk trashing the host mdraid
316 # devices, volume groups, encrypted partitions, etc.
317 "$basedir"/dracut.sh -l -i "$TESTDIR"/overlay / \
318 -m "bash udev-rules base rootfs-block fs-lib kernel-modules fs-lib qemu" \
319 -d "piix ide-gd_mod ata_piix ext3 sd_mod" \
320 --nomdadmconf \
321 --no-hostonly-cmdline -N \
322 -f "$TESTDIR"/initramfs.makeroot "$KVERSION" || return 1
323 rm -fr "$TESTDIR"/overlay
324
325 dd if=/dev/zero of="$TESTDIR"/server.img bs=1MiB count=120
326 dd if=/dev/zero of="$TESTDIR"/marker.img bs=1MiB count=1
327 declare -a disk_args=()
328 # shellcheck disable=SC2034
329 declare -i disk_index=0
330 qemu_add_drive_args disk_index disk_args "$TESTDIR"/marker.img marker
331 qemu_add_drive_args disk_index disk_args "$TESTDIR"/server.img root
332
333 # Invoke KVM and/or QEMU to actually create the target filesystem.
334 "$testdir"/run-qemu \
335 "${disk_args[@]}" \
336 -append "root=/dev/dracut/root rw rootfstype=ext3 quiet console=ttyS0,115200n81 selinux=0" \
337 -initrd "$TESTDIR"/initramfs.makeroot || return 1
338 grep -U --binary-files=binary -F -m 1 -q dracut-root-block-created "$TESTDIR"/marker.img || return 1
339
340 # Make an overlay with needed tools for the test harness
341 (
342 # shellcheck disable=SC2031
343 export initdir="$TESTDIR"/overlay
344 # shellcheck disable=SC1090
345 . "$basedir"/dracut-init.sh
346 inst_multiple poweroff shutdown
347 inst_hook shutdown-emergency 000 ./hard-off.sh
348 inst_hook emergency 000 ./hard-off.sh
349 inst_simple ./99-default.link /etc/systemd/network/99-default.link
350 )
351
352 # Make server's dracut image
353 "$basedir"/dracut.sh \
354 -l -i "$TESTDIR"/overlay / \
355 -m "dash udev-rules base rootfs-block fs-lib debug kernel-modules watchdog qemu" \
356 -d "af_packet piix ide-gd_mod ata_piix ext3 sd_mod nfsv2 nfsv3 nfsv4 nfs_acl nfs_layout_nfsv41_files nfsd e1000 i6300esb ib700wdt" \
357 --no-hostonly-cmdline -N \
358 -f "$TESTDIR"/initramfs.server "$KVERSION" || return 1
359
360 # Make client's dracut image
361 "$basedir"/dracut.sh \
362 -l -i "$TESTDIR"/overlay / \
363 -o "plymouth ${OMIT_NETWORK}" \
364 -a "debug ${USE_NETWORK}" \
365 -d "af_packet piix sd_mod sr_mod ata_piix ide-gd_mod e1000 nfsv2 nfsv3 nfsv4 nfs_acl nfs_layout_nfsv41_files sunrpc i6300esb ib700wdt" \
366 --no-hostonly-cmdline -N \
367 -f "$TESTDIR"/initramfs.testing "$KVERSION" || return 1
368 }
369
370 kill_server() {
371 if [[ -s "$TESTDIR"/server.pid ]]; then
372 kill -TERM -- "$(cat "$TESTDIR"/server.pid)"
373 rm -f -- "$TESTDIR"/server.pid
374 fi
375 }
376
377 test_cleanup() {
378 kill_server
379 }
380
381 # shellcheck disable=SC1090
382 . "$testdir"/test-functions