]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/bash | |
2 | ||
3 | TEST_DESCRIPTION="root filesystem on NBD" | |
4 | ||
5 | KVERSION=${KVERSION-$(uname -r)} | |
6 | ||
7 | # Uncomment this to debug failures | |
8 | #DEBUGFAIL="rd.shell rd.break rd.debug systemd.log_target=console loglevel=7 systemd.log_level=debug" | |
9 | #SERIAL="tcp:127.0.0.1:9999" | |
10 | ||
11 | test_check() { | |
12 | if ! type -p nbd-server 2>/dev/null; then | |
13 | echo "Test needs nbd-server... Skipping" | |
14 | return 1 | |
15 | fi | |
16 | ||
17 | if ! modinfo -k $KVERSION nbd &>/dev/null; then | |
18 | echo "Kernel module nbd does not exist" | |
19 | return 1 | |
20 | fi | |
21 | ||
22 | return 0 | |
23 | } | |
24 | ||
25 | run_server() { | |
26 | # Start server first | |
27 | echo "NBD TEST SETUP: Starting DHCP/NBD server" | |
28 | ||
29 | $testdir/run-qemu \ | |
30 | -drive format=raw,index=0,media=disk,file=$TESTDIR/server.ext2 \ | |
31 | -drive format=raw,index=1,media=disk,file=$TESTDIR/nbd.ext2 \ | |
32 | -drive format=raw,index=2,media=disk,file=$TESTDIR/encrypted.ext2 \ | |
33 | -m 512M -smp 2 \ | |
34 | -display none \ | |
35 | -net nic,macaddr=52:54:00:12:34:56,model=e1000 \ | |
36 | -net socket,listen=127.0.0.1:12340 \ | |
37 | ${SERIAL:+-serial "$SERIAL"} \ | |
38 | ${SERIAL:--serial file:"$TESTDIR"/server.log} \ | |
39 | -no-reboot \ | |
40 | -append "panic=1 systemd.crash_reboot root=/dev/sda rootfstype=ext2 rw quiet console=ttyS0,115200n81 selinux=0" \ | |
41 | -initrd $TESTDIR/initramfs.server -pidfile $TESTDIR/server.pid -daemonize || return 1 | |
42 | sudo chmod 644 $TESTDIR/server.pid || return 1 | |
43 | ||
44 | # Cleanup the terminal if we have one | |
45 | tty -s && stty sane | |
46 | ||
47 | if ! [[ $SERIAL ]]; then | |
48 | echo "Waiting for the server to startup" | |
49 | while : ; do | |
50 | grep Serving "$TESTDIR"/server.log && break | |
51 | sleep 1 | |
52 | done | |
53 | else | |
54 | echo Sleeping 10 seconds to give the server a head start | |
55 | sleep 10 | |
56 | fi | |
57 | } | |
58 | ||
59 | client_test() { | |
60 | local test_name="$1" | |
61 | local mac=$2 | |
62 | local cmdline="$3" | |
63 | local fstype=$4 | |
64 | local fsopt=$5 | |
65 | local found opts nbdinfo | |
66 | ||
67 | [[ $fstype ]] || fstype=ext3 | |
68 | [[ $fsopt ]] || fsopt="ro" | |
69 | ||
70 | echo "CLIENT TEST START: $test_name" | |
71 | ||
72 | # Clear out the flags for each test | |
73 | if ! dd if=/dev/zero of=$TESTDIR/flag.img bs=1M count=1; then | |
74 | echo "Unable to make client sda image" 1>&2 | |
75 | return 1 | |
76 | fi | |
77 | ||
78 | $testdir/run-qemu \ | |
79 | -drive format=raw,index=0,media=disk,file=$TESTDIR/flag.img \ | |
80 | -m 512M -smp 2 \ | |
81 | -nographic \ | |
82 | -net nic,macaddr=$mac,model=e1000 \ | |
83 | -net socket,connect=127.0.0.1:12340 \ | |
84 | -no-reboot \ | |
85 | -append "panic=1 systemd.crash_reboot rd.shell=0 $cmdline $DEBUGFAIL rd.auto rd.info rd.retry=10 ro console=ttyS0,115200n81 selinux=0 " \ | |
86 | -initrd $TESTDIR/initramfs.testing | |
87 | ||
88 | if [[ $? -ne 0 ]] || ! grep -F -m 1 -q nbd-OK $TESTDIR/flag.img; then | |
89 | echo "CLIENT TEST END: $test_name [FAILED - BAD EXIT]" | |
90 | return 1 | |
91 | fi | |
92 | ||
93 | # nbdinfo=( fstype fsoptions ) | |
94 | nbdinfo=($(awk '{print $2, $3; exit}' $TESTDIR/flag.img)) | |
95 | ||
96 | if [[ "${nbdinfo[0]}" != "$fstype" ]]; then | |
97 | echo "CLIENT TEST END: $test_name [FAILED - WRONG FS TYPE] \"${nbdinfo[0]}\" != \"$fstype\"" | |
98 | return 1 | |
99 | fi | |
100 | ||
101 | opts=${nbdinfo[1]}, | |
102 | while [[ $opts ]]; do | |
103 | if [[ ${opts%%,*} = $fsopt ]]; then | |
104 | found=1 | |
105 | break | |
106 | fi | |
107 | opts=${opts#*,} | |
108 | done | |
109 | ||
110 | if [[ ! $found ]]; then | |
111 | echo "CLIENT TEST END: $test_name [FAILED - BAD FS OPTS] \"${nbdinfo[1]}\" != \"$fsopt\"" | |
112 | return 1 | |
113 | fi | |
114 | ||
115 | echo "CLIENT TEST END: $test_name [OK]" | |
116 | } | |
117 | ||
118 | test_run() { | |
119 | if ! run_server; then | |
120 | echo "Failed to start server" 1>&2 | |
121 | return 1 | |
122 | fi | |
123 | client_run | |
124 | kill_server | |
125 | } | |
126 | ||
127 | client_run() { | |
128 | # The default is ext3,errors=continue so use that to determine | |
129 | # if our options were parsed and used | |
130 | client_test "NBD root=nbd:IP:port" 52:54:00:12:34:00 \ | |
131 | "root=nbd:192.168.50.1:raw rd.luks=0" || return 1 | |
132 | ||
133 | client_test "NBD root=nbd:IP:port::fsopts" 52:54:00:12:34:00 \ | |
134 | "root=nbd:192.168.50.1:raw::errors=panic rd.luks=0" \ | |
135 | ext3 errors=panic || return 1 | |
136 | ||
137 | client_test "NBD root=nbd:IP:port:fstype" 52:54:00:12:34:00 \ | |
138 | "root=nbd:192.168.50.1:raw:ext2 rd.luks=0" ext2 || return 1 | |
139 | ||
140 | client_test "NBD root=nbd:IP:port:fstype:fsopts" 52:54:00:12:34:00 \ | |
141 | "root=nbd:192.168.50.1:raw:ext2:errors=panic rd.luks=0" \ | |
142 | ext2 errors=panic || return 1 | |
143 | ||
144 | client_test "NBD Bridge root=nbd:IP:port:fstype:fsopts" 52:54:00:12:34:00 \ | |
145 | "root=nbd:192.168.50.1:raw:ext2:errors=panic bridge rd.luks=0" \ | |
146 | ext2 errors=panic || return 1 | |
147 | ||
148 | # | |
149 | # FIXME! These fail, but probably shouldn't | |
150 | # | |
151 | ||
152 | # There doesn't seem to be a good way to validate the NBD options, so | |
153 | # just check that we don't screw up the other options | |
154 | # | |
155 | # client_test "NBD root=nbd:IP:port:::NBD opts" 52:54:00:12:34:00 \ | |
156 | # "root=nbd:192.168.50.1:raw:::bs=2048 rd.luks=0" || return 1 | |
157 | # | |
158 | # client_test "NBD root=nbd:IP:port:fstype::NBD opts" 52:54:00:12:34:00 \ | |
159 | # "root=nbd:192.168.50.1:raw:ext2::bs=2048 rd.luks=0" ext2 || return 1 | |
160 | # | |
161 | # client_test "NBD root=nbd:IP:port:fstype:fsopts:NBD opts" \ | |
162 | # 52:54:00:12:34:00 \ | |
163 | # "root=nbd:192.168.50.1:raw:ext2:errors=panic:bs=2048 rd.luks=0" \ | |
164 | # ext2 errors=panic || return 1 | |
165 | ||
166 | # DHCP root-path parsing | |
167 | ||
168 | # client_test "NBD root=dhcp DHCP root-path nbd:srv:port" 52:54:00:12:34:01 \ | |
169 | # "root=dhcp rd.luks=0" || return 1 | |
170 | ||
171 | # client_test "NBD Bridge root=dhcp DHCP root-path nbd:srv:port" 52:54:00:12:34:01 \ | |
172 | # "root=dhcp bridge rd.luks=0" || return 1 | |
173 | ||
174 | # client_test "NBD root=dhcp DHCP root-path nbd:srv:port:fstype" \ | |
175 | # 52:54:00:12:34:02 "root=dhcp rd.luks=0" ext2 || return 1 | |
176 | ||
177 | # client_test "NBD root=dhcp DHCP root-path nbd:srv:port::fsopts" \ | |
178 | # 52:54:00:12:34:03 "root=dhcp rd.luks=0" ext3 errors=panic || return 1 | |
179 | ||
180 | # client_test "NBD root=dhcp DHCP root-path nbd:srv:port:fstype:fsopts" \ | |
181 | # 52:54:00:12:34:04 "root=dhcp rd.luks=0" ext2 errors=panic || return 1 | |
182 | ||
183 | # netroot handling | |
184 | ||
185 | # client_test "NBD netroot=nbd:IP:port" 52:54:00:12:34:00 \ | |
186 | # "netroot=nbd:192.168.50.1:raw rd.luks=0" || return 1 | |
187 | # | |
188 | # client_test "NBD netroot=dhcp DHCP root-path nbd:srv:port:fstype:fsopts" \ | |
189 | # 52:54:00:12:34:04 "netroot=dhcp rd.luks=0" ext2 errors=panic || return 1 | |
190 | ||
191 | # Encrypted root handling via LVM/LUKS over NBD | |
192 | ||
193 | # . $TESTDIR/luks.uuid | |
194 | # | |
195 | # client_test "NBD root=LABEL=dracut netroot=nbd:IP:port" \ | |
196 | # 52:54:00:12:34:00 \ | |
197 | # "root=LABEL=dracut rd.luks.uuid=$ID_FS_UUID rd.lv.vg=dracut netroot=nbd:192.168.50.1:encrypted" || return 1 | |
198 | ||
199 | # XXX This should be ext2,errors=panic but that doesn't currently | |
200 | # XXX work when you have a real root= line in addition to netroot= | |
201 | # XXX How we should work here needs clarification | |
202 | # client_test "NBD root=LABEL=dracut netroot=dhcp (w/ fstype and opts)" \ | |
203 | # 52:54:00:12:34:05 \ | |
204 | # "root=LABEL=dracut rd.luks.uuid=$ID_FS_UUID rd.lv.vg=dracut netroot=dhcp" || return 1 | |
205 | ||
206 | if [[ -s server.pid ]]; then | |
207 | sudo kill -TERM $(cat $TESTDIR/server.pid) | |
208 | rm -f -- $TESTDIR/server.pid | |
209 | fi | |
210 | ||
211 | } | |
212 | ||
213 | make_encrypted_root() { | |
214 | # Create the blank file to use as a root filesystem | |
215 | dd if=/dev/null of=$TESTDIR/encrypted.ext2 bs=1M seek=80 | |
216 | dd if=/dev/null of=$TESTDIR/flag.img bs=1M seek=1 | |
217 | ||
218 | kernel=$KVERSION | |
219 | # Create what will eventually be our root filesystem onto an overlay | |
220 | ( | |
221 | export initdir=$TESTDIR/overlay/source | |
222 | . $basedir/dracut-init.sh | |
223 | mkdir -p "$initdir" | |
224 | ( | |
225 | cd "$initdir" | |
226 | mkdir -p dev sys proc etc var tmp run root usr/bin usr/lib usr/lib64 usr/sbin | |
227 | for i in bin sbin lib lib64; do | |
228 | ln -sfnr usr/$i $i | |
229 | done | |
230 | ln -s ../run var/run | |
231 | ) | |
232 | inst_multiple sh df free ls shutdown poweroff stty cat ps ln ip \ | |
233 | mount dmesg mkdir cp ping | |
234 | for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do | |
235 | [ -f ${_terminfodir}/l/linux ] && break | |
236 | done | |
237 | inst_multiple -o ${_terminfodir}/l/linux | |
238 | inst ./client-init.sh /sbin/init | |
239 | inst_simple /etc/os-release | |
240 | find_binary plymouth >/dev/null && inst_multiple plymouth | |
241 | cp -a /etc/ld.so.conf* $initdir/etc | |
242 | sudo ldconfig -r "$initdir" | |
243 | ) | |
244 | ||
245 | # second, install the files needed to make the root filesystem | |
246 | ( | |
247 | export initdir=$TESTDIR/overlay | |
248 | . $basedir/dracut-init.sh | |
249 | ( | |
250 | cd "$initdir" | |
251 | mkdir -p dev sys proc etc tmp var run root usr/bin usr/lib usr/lib64 usr/sbin | |
252 | for i in bin sbin lib lib64; do | |
253 | ln -sfnr usr/$i $i | |
254 | done | |
255 | ln -s ../run var/run | |
256 | ) | |
257 | inst_multiple mke2fs poweroff cp umount tune2fs | |
258 | inst_hook shutdown-emergency 000 ./hard-off.sh | |
259 | inst_hook emergency 000 ./hard-off.sh | |
260 | inst_hook initqueue 01 ./create-root.sh | |
261 | inst_hook initqueue/finished 01 ./finished-false.sh | |
262 | inst_simple ./99-idesymlinks.rules /etc/udev/rules.d/99-idesymlinks.rules | |
263 | ) | |
264 | ||
265 | # create an initramfs that will create the target root filesystem. | |
266 | # We do it this way so that we do not risk trashing the host mdraid | |
267 | # devices, volume groups, encrypted partitions, etc. | |
268 | $basedir/dracut.sh -l -i $TESTDIR/overlay / \ | |
269 | -m "dash crypt lvm mdraid udev-rules base rootfs-block fs-lib kernel-modules qemu" \ | |
270 | -d "piix ide-gd_mod ata_piix ext2 ext3 sd_mod" \ | |
271 | --no-hostonly-cmdline -N \ | |
272 | -f $TESTDIR/initramfs.makeroot $KVERSION || return 1 | |
273 | rm -rf -- $TESTDIR/overlay | |
274 | ||
275 | # Invoke KVM and/or QEMU to actually create the target filesystem. | |
276 | $testdir/run-qemu \ | |
277 | -drive format=raw,index=0,media=disk,file=$TESTDIR/flag.img \ | |
278 | -drive format=raw,index=1,media=disk,file=$TESTDIR/encrypted.ext2 \ | |
279 | -m 512M -smp 2\ | |
280 | -nographic -net none \ | |
281 | -append "root=/dev/fakeroot rw quiet console=ttyS0,115200n81 selinux=0" \ | |
282 | -initrd $TESTDIR/initramfs.makeroot || return 1 | |
283 | grep -F -m 1 -q dracut-root-block-created $TESTDIR/flag.img || return 1 | |
284 | grep -F -a -m 1 ID_FS_UUID $TESTDIR/flag.img > $TESTDIR/luks.uuid | |
285 | } | |
286 | ||
287 | make_client_root() { | |
288 | dd if=/dev/null of=$TESTDIR/nbd.ext2 bs=1M seek=120 | |
289 | mke2fs -F -j $TESTDIR/nbd.ext2 | |
290 | mkdir $TESTDIR/mnt | |
291 | sudo mount -o loop $TESTDIR/nbd.ext2 $TESTDIR/mnt | |
292 | ||
293 | kernel=$KVERSION | |
294 | ( | |
295 | export initdir=$TESTDIR/mnt | |
296 | . $basedir/dracut-init.sh | |
297 | mkdir -p "$initdir" | |
298 | ( | |
299 | cd "$initdir" | |
300 | mkdir -p dev sys proc etc var tmp run root usr/bin usr/lib usr/lib64 usr/sbin | |
301 | for i in bin sbin lib lib64; do | |
302 | ln -sfnr usr/$i $i | |
303 | done | |
304 | ln -s ../run var/run | |
305 | ) | |
306 | inst_multiple sh ls shutdown poweroff stty cat ps ln ip \ | |
307 | dmesg mkdir cp ping | |
308 | for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do | |
309 | [ -f ${_terminfodir}/l/linux ] && break | |
310 | done | |
311 | inst_multiple -o ${_terminfodir}/l/linux | |
312 | inst ./client-init.sh /sbin/init | |
313 | inst_simple /etc/os-release | |
314 | inst /etc/nsswitch.conf /etc/nsswitch.conf | |
315 | inst /etc/passwd /etc/passwd | |
316 | inst /etc/group /etc/group | |
317 | for i in /usr/lib*/libnss_files* /lib*/libnss_files*;do | |
318 | [ -e "$i" ] || continue | |
319 | inst $i | |
320 | done | |
321 | cp -a /etc/ld.so.conf* $initdir/etc | |
322 | sudo ldconfig -r "$initdir" | |
323 | ) | |
324 | ||
325 | sudo umount $TESTDIR/mnt | |
326 | rm -fr -- $TESTDIR/mnt | |
327 | } | |
328 | ||
329 | make_server_root() { | |
330 | dd if=/dev/null of=$TESTDIR/server.ext2 bs=1M seek=120 | |
331 | mke2fs -F $TESTDIR/server.ext2 | |
332 | mkdir $TESTDIR/mnt | |
333 | sudo mount -o loop $TESTDIR/server.ext2 $TESTDIR/mnt | |
334 | ||
335 | kernel=$KVERSION | |
336 | ( | |
337 | export initdir=$TESTDIR/mnt | |
338 | . $basedir/dracut-init.sh | |
339 | mkdir -p "$initdir" | |
340 | ( | |
341 | cd "$initdir"; | |
342 | mkdir -p run dev sys proc etc var var/lib/dhcpd tmp etc/nbd-server | |
343 | ln -s ../run var/run | |
344 | ) | |
345 | cat > "$initdir/etc/nbd-server/config" <<EOF | |
346 | [generic] | |
347 | [raw] | |
348 | exportname = /dev/sdb | |
349 | port = 2000 | |
350 | bs = 4096 | |
351 | [encrypted] | |
352 | exportname = /dev/sdc | |
353 | port = 2001 | |
354 | bs = 4096 | |
355 | EOF | |
356 | inst_multiple sh ls shutdown poweroff stty cat ps ln ip \ | |
357 | dmesg mkdir cp ping grep \ | |
358 | sleep nbd-server chmod modprobe vi | |
359 | for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do | |
360 | [ -f ${_terminfodir}/l/linux ] && break | |
361 | done | |
362 | inst_multiple -o ${_terminfodir}/l/linux | |
363 | instmods af_packet | |
364 | type -P dhcpd >/dev/null && inst_multiple dhcpd | |
365 | [ -x /usr/sbin/dhcpd3 ] && inst /usr/sbin/dhcpd3 /usr/sbin/dhcpd | |
366 | inst ./server-init.sh /sbin/init | |
367 | inst_simple /etc/os-release | |
368 | inst ./hosts /etc/hosts | |
369 | inst ./dhcpd.conf /etc/dhcpd.conf | |
370 | inst /etc/nsswitch.conf /etc/nsswitch.conf | |
371 | inst /etc/passwd /etc/passwd | |
372 | inst /etc/group /etc/group | |
373 | for i in /usr/lib*/libnss_files* /lib*/libnss_files*;do | |
374 | [ -e "$i" ] || continue | |
375 | inst $i | |
376 | done | |
377 | ||
378 | cp -a /etc/ld.so.conf* $initdir/etc | |
379 | sudo ldconfig -r "$initdir" | |
380 | ) | |
381 | ||
382 | sudo umount $TESTDIR/mnt | |
383 | rm -fr -- $TESTDIR/mnt | |
384 | } | |
385 | ||
386 | test_setup() { | |
387 | make_encrypted_root || return 1 | |
388 | make_client_root || return 1 | |
389 | make_server_root || return 1 | |
390 | ||
391 | # Make the test image | |
392 | ( | |
393 | export initdir=$TESTDIR/overlay | |
394 | . $basedir/dracut-init.sh | |
395 | inst_multiple poweroff shutdown | |
396 | inst_hook shutdown-emergency 000 ./hard-off.sh | |
397 | inst_simple ./99-idesymlinks.rules /etc/udev/rules.d/99-idesymlinks.rules | |
398 | inst ./cryptroot-ask.sh /sbin/cryptroot-ask | |
399 | ||
400 | # inst ./debug-shell.service /lib/systemd/system/debug-shell.service | |
401 | # mkdir -p "${initdir}/lib/systemd/system/sysinit.target.wants" | |
402 | # ln -fs ../debug-shell.service "${initdir}/lib/systemd/system/sysinit.target.wants/debug-shell.service" | |
403 | ||
404 | . $TESTDIR/luks.uuid | |
405 | mkdir -p $initdir/etc | |
406 | echo "luks-$ID_FS_UUID /dev/nbd0 /etc/key" > $initdir/etc/crypttab | |
407 | echo -n test > $initdir/etc/key | |
408 | ) | |
409 | ||
410 | sudo $basedir/dracut.sh -l -i $TESTDIR/overlay / \ | |
411 | -m "dash udev-rules rootfs-block fs-lib base debug kernel-modules" \ | |
412 | -d "af_packet piix ide-gd_mod ata_piix ext2 ext3 sd_mod e1000" \ | |
413 | --no-hostonly-cmdline -N \ | |
414 | -f $TESTDIR/initramfs.server $KVERSION || return 1 | |
415 | ||
416 | sudo $basedir/dracut.sh -l -i $TESTDIR/overlay / \ | |
417 | -o "plymouth" \ | |
418 | -a "debug watchdog" \ | |
419 | -d "af_packet piix ide-gd_mod ata_piix ext2 ext3 sd_mod e1000 i6300esb ib700wdt" \ | |
420 | --no-hostonly-cmdline -N \ | |
421 | -f $TESTDIR/initramfs.testing $KVERSION || return 1 | |
422 | } | |
423 | ||
424 | kill_server() { | |
425 | if [[ -s $TESTDIR/server.pid ]]; then | |
426 | sudo kill -TERM $(cat $TESTDIR/server.pid) | |
427 | rm -f -- $TESTDIR/server.pid | |
428 | fi | |
429 | } | |
430 | ||
431 | test_cleanup() { | |
432 | kill_server | |
433 | } | |
434 | ||
435 | . $testdir/test-functions |