]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/bectl/tests/bectl_test.sh
zfs: merge openzfs/zfs@10e36e176
[FreeBSD/FreeBSD.git] / sbin / bectl / tests / bectl_test.sh
1 #
2 # SPDX-License-Identifier: BSD-2-Clause
3 #
4 # Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 # SUCH DAMAGE.
26 #
27 # $FreeBSD$
28
29 ZPOOL_NAME_FILE=zpool_name
30 get_zpool_name()
31 {
32         cat $ZPOOL_NAME_FILE
33 }
34 make_zpool_name()
35 {
36         mktemp -u bectl_test_XXXXXX > $ZPOOL_NAME_FILE
37         get_zpool_name
38 }
39
40 # Establishes a bectl_create zpool that can be used for some light testing; contains
41 # a 'default' BE and not much else.
42 bectl_create_setup()
43 {
44         zpool=$1
45         disk=$2
46         mnt=$3
47
48         # Sanity check to make sure `make_zpool_name` succeeded
49         atf_check test -n "$zpool"
50
51         kldload -n -q zfs || atf_skip "ZFS module not loaded on the current system"
52         if ! getconf MIN_HOLE_SIZE "$(pwd)"; then
53                 echo "getconf MIN_HOLE_SIZE $(pwd) failed; sparse files " \
54                     "probably not supported by file system"
55                 mount
56                 atf_skip "Test's work directory does not support sparse files;" \
57                     "try with a different TMPDIR?"
58         fi
59         atf_check mkdir -p ${mnt}
60         atf_check truncate -s 1G ${disk}
61         atf_check zpool create -R ${mnt} ${zpool} ${disk}
62         atf_check zfs create -o mountpoint=none ${zpool}/ROOT
63         atf_check zfs create -o mountpoint=/ -o canmount=noauto \
64             ${zpool}/ROOT/default
65 }
66 bectl_create_deep_setup()
67 {
68         zpool=$1
69         disk=$2
70         mnt=$3
71
72         # Sanity check to make sure `make_zpool_name` succeeded
73         atf_check test -n "$zpool"
74
75         bectl_create_setup ${zpool} ${disk} ${mnt}
76         atf_check mkdir -p ${root}
77         atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
78         atf_check mkdir -p ${root}/usr
79         atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
80             ${zpool}/ROOT/default/usr
81         atf_check -o ignore bectl -r ${zpool}/ROOT umount default
82 }
83
84 bectl_cleanup()
85 {
86         zpool=$1
87         if [ -z "$zpool" ]; then
88                 echo "Skipping cleanup; zpool not set up"
89         elif zpool get health ${zpool} >/dev/null 2>&1; then
90                 zpool destroy -f ${zpool}
91         fi
92 }
93
94 atf_test_case bectl_create cleanup
95 bectl_create_head()
96 {
97
98         atf_set "descr" "Check the various forms of bectl create"
99         atf_set "require.user" root
100 }
101 bectl_create_body()
102 {
103         if [ "$(atf_config_get ci false)" = "true" ] && \
104                 [ "$(uname -p)" = "i386" ]; then
105                 atf_skip "https://bugs.freebsd.org/249055"
106         fi
107
108         if [ "$(atf_config_get ci false)" = "true" ] && \
109                 [ "$(uname -p)" = "armv7" ]; then
110                 atf_skip "https://bugs.freebsd.org/249229"
111         fi
112
113         cwd=$(realpath .)
114         zpool=$(make_zpool_name)
115         disk=${cwd}/disk.img
116         mount=${cwd}/mnt
117
118         bectl_create_setup ${zpool} ${disk} ${mount}
119
120         # Create a child dataset that will be used to test creation
121         # of recursive and non-recursive boot environments.
122         atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
123             ${zpool}/ROOT/default/usr
124
125         # BE datasets with spaces are not bootable, PR 254441.
126         atf_check -e not-empty -s not-exit:0 \
127                 bectl -r ${zpool}/ROOT create "foo bar"
128
129         # Test standard creation, creation of a snapshot, and creation from a
130         # snapshot.
131         atf_check bectl -r ${zpool}/ROOT create -e default default2
132         atf_check bectl -r ${zpool}/ROOT create default2@test_snap
133         atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3
134
135         # Test standard creation, creation of a snapshot, and creation from a
136         # snapshot for recursive boot environments.
137         atf_check bectl -r ${zpool}/ROOT create -r -e default recursive
138         atf_check bectl -r ${zpool}/ROOT create -r recursive@test_snap
139         atf_check bectl -r ${zpool}/ROOT create -r -e recursive@test_snap recursive-snap
140
141         # Test that non-recursive boot environments have no child datasets.
142         atf_check -e not-empty -s not-exit:0 \
143                 zfs list "${zpool}/ROOT/default2/usr"
144         atf_check -e not-empty -s not-exit:0 \
145                 zfs list "${zpool}/ROOT/default3/usr"
146
147         # Test that recursive boot environments have child datasets.
148         atf_check -o not-empty \
149                 zfs list "${zpool}/ROOT/recursive/usr"
150         atf_check -o not-empty \
151                 zfs list "${zpool}/ROOT/recursive-snap/usr"
152 }
153 bectl_create_cleanup()
154 {
155         bectl_cleanup $(get_zpool_name)
156 }
157
158 atf_test_case bectl_destroy cleanup
159 bectl_destroy_head()
160 {
161
162         atf_set "descr" "Check bectl destroy"
163         atf_set "require.user" root
164 }
165 bectl_destroy_body()
166 {
167         if [ "$(atf_config_get ci false)" = "true" ] && \
168                 [ "$(uname -p)" = "i386" ]; then
169                 atf_skip "https://bugs.freebsd.org/249055"
170         fi
171
172         if [ "$(atf_config_get ci false)" = "true" ] && \
173                 [ "$(uname -p)" = "armv7" ]; then
174                 atf_skip "https://bugs.freebsd.org/249229"
175         fi
176
177         cwd=$(realpath .)
178         zpool=$(make_zpool_name)
179         disk=${cwd}/disk.img
180         mount=${cwd}/mnt
181         root=${mount}/root
182
183         bectl_create_setup ${zpool} ${disk} ${mount}
184         atf_check bectl -r ${zpool}/ROOT create -e default default2
185         atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
186         atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
187         atf_check -e not-empty -s not-exit:0 zfs get mountpoint ${zpool}/ROOT/default2
188
189         # Test origin snapshot deletion when the snapshot to be destroyed
190         # belongs to a mounted dataset, see PR 236043.
191         atf_check mkdir -p ${root}
192         atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
193         atf_check bectl -r ${zpool}/ROOT create -e default default3
194         atf_check bectl -r ${zpool}/ROOT destroy -o default3
195         atf_check bectl -r ${zpool}/ROOT unmount default
196
197         # create two be from the same parent and destroy the parent
198         atf_check bectl -r ${zpool}/ROOT create -e default default2
199         atf_check bectl -r ${zpool}/ROOT create -e default default3
200         atf_check bectl -r ${zpool}/ROOT destroy default
201         atf_check bectl -r ${zpool}/ROOT destroy default2
202         atf_check bectl -r ${zpool}/ROOT rename default3 default
203
204         # Create a BE, have it be the parent for another and repeat, then start
205         # deleting environments.  Arbitrarily chose default3 as the first.
206         # Sleeps are required to prevent conflicting snapshots- libbe will
207         # use the time with a serial at the end as needed to prevent collisions,
208         # but as BEs get promoted the snapshot names will convert and conflict
209         # anyways.  libbe should perhaps consider adding something extra to the
210         # default name to prevent collisions like this, but the default name
211         # includes down to the second and creating BEs this rapidly is perhaps
212         # uncommon enough.
213         atf_check bectl -r ${zpool}/ROOT create -e default default2
214         sleep 1
215         atf_check bectl -r ${zpool}/ROOT create -e default2 default3
216         sleep 1
217         atf_check bectl -r ${zpool}/ROOT create -e default3 default4
218         atf_check bectl -r ${zpool}/ROOT destroy default3
219         atf_check bectl -r ${zpool}/ROOT destroy default2
220         atf_check bectl -r ${zpool}/ROOT destroy default4
221
222         # Create two BEs, then create an unrelated snapshot on the originating
223         # BE and destroy it.  We shouldn't have promoted the second BE, and it's
224         # only possible to tell if we promoted it by making sure we didn't
225         # demote the first BE at some point -- if we did, it's origin will no
226         # longer be empty.
227         atf_check bectl -r ${zpool}/ROOT create -e default default2
228         atf_check bectl -r ${zpool}/ROOT create default@test
229
230         atf_check bectl -r ${zpool}/ROOT destroy default@test
231         atf_check -o inline:"-\n" zfs get -Ho value origin ${zpool}/ROOT/default
232         atf_check bectl -r ${zpool}/ROOT destroy default2
233
234         # As observed by beadm, if we explicitly try to destroy a snapshot that
235         # leads to clones, we shouldn't have allowed it.
236         atf_check bectl -r ${zpool}/ROOT create default@test
237         atf_check bectl -r ${zpool}/ROOT create -e default@test default2
238
239         atf_check -e  not-empty -s not-exit:0 bectl -r ${zpool}/ROOT destroy \
240             default@test
241 }
242 bectl_destroy_cleanup()
243 {
244
245         bectl_cleanup $(get_zpool_name)
246 }
247
248 atf_test_case bectl_export_import cleanup
249 bectl_export_import_head()
250 {
251
252         atf_set "descr" "Check bectl export and import"
253         atf_set "require.user" root
254 }
255 bectl_export_import_body()
256 {
257         if [ "$(atf_config_get ci false)" = "true" ] && \
258                 [ "$(uname -p)" = "i386" ]; then
259                 atf_skip "https://bugs.freebsd.org/249055"
260         fi
261
262         if [ "$(atf_config_get ci false)" = "true" ] && \
263                 [ "$(uname -p)" = "armv7" ]; then
264                 atf_skip "https://bugs.freebsd.org/249229"
265         fi
266
267         cwd=$(realpath .)
268         zpool=$(make_zpool_name)
269         disk=${cwd}/disk.img
270         mount=${cwd}/mnt
271
272         bectl_create_setup ${zpool} ${disk} ${mount}
273         atf_check -o save:exported bectl -r ${zpool}/ROOT export default
274         atf_check -x "bectl -r ${zpool}/ROOT import default2 < exported"
275         atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
276         atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
277         atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
278             ${zpool}/ROOT/default2
279 }
280 bectl_export_import_cleanup()
281 {
282
283         bectl_cleanup $(get_zpool_name)
284 }
285
286 atf_test_case bectl_list cleanup
287 bectl_list_head()
288 {
289
290         atf_set "descr" "Check bectl list"
291         atf_set "require.user" root
292 }
293 bectl_list_body()
294 {
295         if [ "$(atf_config_get ci false)" = "true" ] && \
296                 [ "$(uname -p)" = "i386" ]; then
297                 atf_skip "https://bugs.freebsd.org/249055"
298         fi
299
300         if [ "$(atf_config_get ci false)" = "true" ] && \
301                 [ "$(uname -p)" = "armv7" ]; then
302                 atf_skip "https://bugs.freebsd.org/249229"
303         fi
304
305         cwd=$(realpath .)
306         zpool=$(make_zpool_name)
307         disk=${cwd}/disk.img
308         mount=${cwd}/mnt
309
310         bectl_create_setup ${zpool} ${disk} ${mount}
311         # Test the list functionality, including that BEs come and go away
312         # as they're created and destroyed.  Creation and destruction tests
313         # use the 'zfs' utility to verify that they're actually created, so
314         # these are just light tests that 'list' is picking them up.
315         atf_check -o save:list.out bectl -r ${zpool}/ROOT list
316         atf_check -o not-empty grep 'default' list.out
317         atf_check bectl -r ${zpool}/ROOT create -e default default2
318         atf_check -o save:list.out bectl -r ${zpool}/ROOT list
319         atf_check -o not-empty grep 'default2' list.out
320         atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
321         atf_check -o save:list.out bectl -r ${zpool}/ROOT list
322         atf_check -s not-exit:0 grep 'default2' list.out
323         # XXX TODO: Formatting checks
324 }
325 bectl_list_cleanup()
326 {
327
328         bectl_cleanup $(get_zpool_name)
329 }
330
331 atf_test_case bectl_mount cleanup
332 bectl_mount_head()
333 {
334
335         atf_set "descr" "Check bectl mount/unmount"
336         atf_set "require.user" root
337 }
338 bectl_mount_body()
339 {
340         if [ "$(atf_config_get ci false)" = "true" ] && \
341                 [ "$(uname -p)" = "i386" ]; then
342                 atf_skip "https://bugs.freebsd.org/249055"
343         fi
344
345         if [ "$(atf_config_get ci false)" = "true" ] && \
346                 [ "$(uname -p)" = "armv7" ]; then
347                 atf_skip "https://bugs.freebsd.org/249229"
348         fi
349
350         cwd=$(realpath .)
351         zpool=$(make_zpool_name)
352         disk=${cwd}/disk.img
353         mount=${cwd}/mnt
354         root=${mount}/root
355
356         bectl_create_deep_setup ${zpool} ${disk} ${mount}
357         atf_check mkdir -p ${root}
358         # Test unmount first...
359         atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
360         atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
361         atf_check bectl -r ${zpool}/ROOT unmount default
362         atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
363         # Then umount!
364         atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
365         atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
366         atf_check bectl -r ${zpool}/ROOT umount default
367         atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
368 }
369 bectl_mount_cleanup()
370 {
371
372         bectl_cleanup $(get_zpool_name)
373 }
374
375 atf_test_case bectl_rename cleanup
376 bectl_rename_head()
377 {
378
379         atf_set "descr" "Check bectl rename"
380         atf_set "require.user" root
381 }
382 bectl_rename_body()
383 {
384         if [ "$(atf_config_get ci false)" = "true" ] && \
385                 [ "$(uname -p)" = "i386" ]; then
386                 atf_skip "https://bugs.freebsd.org/249055"
387         fi
388
389         if [ "$(atf_config_get ci false)" = "true" ] && \
390                 [ "$(uname -p)" = "armv7" ]; then
391                 atf_skip "https://bugs.freebsd.org/249229"
392         fi
393
394         cwd=$(realpath .)
395         zpool=$(make_zpool_name)
396         disk=${cwd}/disk.img
397         mount=${cwd}/mnt
398
399         bectl_create_setup ${zpool} ${disk} ${mount}
400         atf_check bectl -r ${zpool}/ROOT rename default default2
401         atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
402         atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
403             ${zpool}/ROOT/default
404 }
405 bectl_rename_cleanup()
406 {
407
408         bectl_cleanup $(get_zpool_name)
409 }
410
411 atf_test_case bectl_jail cleanup
412 bectl_jail_head()
413 {
414
415         atf_set "descr" "Check bectl rename"
416         atf_set "require.user" root
417         atf_set "require.progs" jail
418 }
419 bectl_jail_body()
420 {
421         if [ "$(atf_config_get ci false)" = "true" ] && \
422                 [ "$(uname -p)" = "i386" ]; then
423                 atf_skip "https://bugs.freebsd.org/249055"
424         fi
425
426         if [ "$(atf_config_get ci false)" = "true" ] && \
427                 [ "$(uname -p)" = "armv7" ]; then
428                 atf_skip "https://bugs.freebsd.org/249229"
429         fi
430
431         cwd=$(realpath .)
432         zpool=$(make_zpool_name)
433         disk=${cwd}/disk.img
434         mount=${cwd}/mnt
435         root=${mount}/root
436
437         if [ ! -f /rescue/rescue ]; then
438                 atf_skip "This test requires a rescue binary"
439         fi
440         bectl_create_deep_setup ${zpool} ${disk} ${mount}
441         # Prepare our minimal BE... plop a rescue binary into it
442         atf_check mkdir -p ${root}
443         atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
444         atf_check mkdir -p ${root}/rescue
445         atf_check cp /rescue/rescue ${root}/rescue/rescue
446         atf_check bectl -r ${zpool}/ROOT umount default
447
448         # Prepare some more boot environments
449         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default target
450         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default 1234
451
452         # Attempt to unjail a BE with numeric name; jail_getid at one point
453         # did not validate that the input was a valid jid before returning the
454         # jid.
455         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b 1234
456         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail 1234
457
458         # When a jail name is not explicit, it should match the jail id.
459         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o jid=233637 default
460         atf_check -o inline:"233637\n" -s exit:0 -x "jls -j 233637 name"
461         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
462
463         # Basic command-mode tests, with and without jail cleanup
464         atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
465             jail default /rescue/rescue ls -1
466         atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
467             jail -Uo path=${root} default /rescue/rescue ls -1
468         atf_check [ -f ${root}/rescue/rescue ]
469         atf_check bectl -r ${zpool}/ROOT ujail default
470
471         # Batch mode tests
472         atf_check bectl -r ${zpool}/ROOT jail -bo path=${root} default
473         atf_check -o not-empty -x "jls | grep -F \"${root}\""
474         atf_check bectl -r ${zpool}/ROOT ujail default
475         atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
476         # 'unjail' naming
477         atf_check bectl -r ${zpool}/ROOT jail -b default
478         atf_check bectl -r ${zpool}/ROOT unjail default
479         atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
480         # 'unjail' by BE name. Force bectl to lookup jail id by the BE name.
481         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b default
482         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o name=bectl_test target
483         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail target
484         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
485         # cannot unjail an unjailed BE (by either command name)
486         atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT ujail default
487         atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT unjail default
488
489         # set+unset
490         atf_check bectl -r ${zpool}/ROOT jail -b -o path=${root} -u path default
491         # Ensure that it didn't mount at ${root}
492         atf_check -s not-exit:0 -x "mount | grep -F '${root}'"
493         atf_check bectl -r ${zpool}/ROOT ujail default
494 }
495
496 # If a test has failed, it's possible that the boot environment hasn't
497 # been 'unjail'ed. We want to remove the jail before 'bectl_cleanup'
498 # attempts to destroy the zpool.
499 bectl_jail_cleanup()
500 {
501         if [ "$(atf_config_get ci false)" = "true" ] && \
502                 [ "$(uname -p)" = "i386" ]; then
503                 atf_skip "https://bugs.freebsd.org/249055"
504         fi
505
506         if [ "$(atf_config_get ci false)" = "true" ] && \
507                 [ "$(uname -p)" = "armv7" ]; then
508                 atf_skip "https://bugs.freebsd.org/249229"
509         fi
510
511         zpool=$(get_zpool_name)
512         for bootenv in "default" "target" "1234"; do
513                 # mountpoint of the boot environment
514                 mountpoint="$(bectl -r ${zpool}/ROOT list -H | grep ${bootenv} | awk '{print $3}')"
515
516                 # see if any jail paths match the boot environment mountpoint
517                 jailid="$(jls | grep ${mountpoint} | awk '{print $1}')"
518
519                 if [ -z "$jailid" ]; then
520                        continue;
521                 fi
522                 jail -r ${jailid}
523         done;
524
525         bectl_cleanup ${zpool}
526 }
527
528 atf_init_test_cases()
529 {
530         atf_add_test_case bectl_create
531         atf_add_test_case bectl_destroy
532         atf_add_test_case bectl_export_import
533         atf_add_test_case bectl_list
534         atf_add_test_case bectl_mount
535         atf_add_test_case bectl_rename
536         atf_add_test_case bectl_jail
537 }