]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/bectl/tests/bectl_test.sh
Call atf_skip function in cleanup procedure as it also triggers zfs.ko loading
[FreeBSD/FreeBSD.git] / sbin / bectl / tests / bectl_test.sh
1 #
2 # SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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         atf_check mkdir -p ${mnt}
53         atf_check truncate -s 1G ${disk}
54         atf_check zpool create -o altroot=${mnt} ${zpool} ${disk}
55         atf_check zfs create -o mountpoint=none ${zpool}/ROOT
56         atf_check zfs create -o mountpoint=/ -o canmount=noauto \
57             ${zpool}/ROOT/default
58 }
59 bectl_create_deep_setup()
60 {
61         zpool=$1
62         disk=$2
63         mnt=$3
64
65         # Sanity check to make sure `make_zpool_name` succeeded
66         atf_check test -n "$zpool"
67
68         bectl_create_setup ${zpool} ${disk} ${mnt}
69         atf_check mkdir -p ${root}
70         atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
71         atf_check mkdir -p ${root}/usr
72         atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
73             ${zpool}/ROOT/default/usr
74         atf_check -o ignore bectl -r ${zpool}/ROOT umount default
75 }
76
77 bectl_cleanup()
78 {
79         zpool=$1
80         if [ -z "$zpool" ]; then
81                 echo "Skipping cleanup; zpool not set up"
82         elif zpool get health ${zpool} >/dev/null 2>&1; then
83                 zpool destroy -f ${zpool}
84         fi
85 }
86
87 atf_test_case bectl_create cleanup
88 bectl_create_head()
89 {
90
91         atf_set "descr" "Check the various forms of bectl create"
92         atf_set "require.user" root
93 }
94 bectl_create_body()
95 {
96         if [ "$(atf_config_get ci false)" = "true" ] && \
97                 [ "$(uname -p)" = "i386" ]; then
98                 atf_skip "https://bugs.freebsd.org/249055"
99         fi
100
101         cwd=$(realpath .)
102         zpool=$(make_zpool_name)
103         disk=${cwd}/disk.img
104         mount=${cwd}/mnt
105
106         bectl_create_setup ${zpool} ${disk} ${mount}
107
108         # Create a child dataset that will be used to test creation
109         # of recursive and non-recursive boot environments.
110         atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
111             ${zpool}/ROOT/default/usr
112
113         # Test standard creation, creation of a snapshot, and creation from a
114         # snapshot.
115         atf_check bectl -r ${zpool}/ROOT create -e default default2
116         atf_check bectl -r ${zpool}/ROOT create default2@test_snap
117         atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3
118
119         # Test standard creation, creation of a snapshot, and creation from a
120         # snapshot for recursive boot environments.
121         atf_check bectl -r ${zpool}/ROOT create -r -e default recursive
122         atf_check bectl -r ${zpool}/ROOT create -r recursive@test_snap
123         atf_check bectl -r ${zpool}/ROOT create -r -e recursive@test_snap recursive-snap
124
125         # Test that non-recursive boot environments have no child datasets.
126         atf_check -e not-empty -s not-exit:0 \
127                 zfs list "${zpool}/ROOT/default2/usr"
128         atf_check -e not-empty -s not-exit:0 \
129                 zfs list "${zpool}/ROOT/default3/usr"
130
131         # Test that recursive boot environments have child datasets.
132         atf_check -o not-empty \
133                 zfs list "${zpool}/ROOT/recursive/usr"
134         atf_check -o not-empty \
135                 zfs list "${zpool}/ROOT/recursive-snap/usr"
136 }
137 bectl_create_cleanup()
138 {
139         bectl_cleanup $(get_zpool_name)
140 }
141
142 atf_test_case bectl_destroy cleanup
143 bectl_destroy_head()
144 {
145
146         atf_set "descr" "Check bectl destroy"
147         atf_set "require.user" root
148 }
149 bectl_destroy_body()
150 {
151         if [ "$(atf_config_get ci false)" = "true" ] && \
152                 [ "$(uname -p)" = "i386" ]; then
153                 atf_skip "https://bugs.freebsd.org/249055"
154         fi
155
156         cwd=$(realpath .)
157         zpool=$(make_zpool_name)
158         disk=${cwd}/disk.img
159         mount=${cwd}/mnt
160         root=${mount}/root
161
162         bectl_create_setup ${zpool} ${disk} ${mount}
163         atf_check bectl -r ${zpool}/ROOT create -e default default2
164         atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
165         atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
166         atf_check -e not-empty -s not-exit:0 zfs get mountpoint ${zpool}/ROOT/default2
167
168         # Test origin snapshot deletion when the snapshot to be destroyed
169         # belongs to a mounted dataset, see PR 236043.
170         atf_check mkdir -p ${root}
171         atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
172         atf_check bectl -r ${zpool}/ROOT create -e default default3
173         atf_check bectl -r ${zpool}/ROOT destroy -o default3
174         atf_check bectl -r ${zpool}/ROOT unmount default
175
176         # create two be from the same parent and destroy the parent
177         atf_check bectl -r ${zpool}/ROOT create -e default default2
178         atf_check bectl -r ${zpool}/ROOT create -e default default3
179         atf_check bectl -r ${zpool}/ROOT destroy default
180         atf_check bectl -r ${zpool}/ROOT destroy default2
181         atf_check bectl -r ${zpool}/ROOT rename default3 default
182
183         # Create a BE, have it be the parent for another and repeat, then start
184         # deleting environments.  Arbitrarily chose default3 as the first.
185         # Sleeps are required to prevent conflicting snapshots- libbe will
186         # use the time with a serial at the end as needed to prevent collisions,
187         # but as BEs get promoted the snapshot names will convert and conflict
188         # anyways.  libbe should perhaps consider adding something extra to the
189         # default name to prevent collisions like this, but the default name
190         # includes down to the second and creating BEs this rapidly is perhaps
191         # uncommon enough.
192         atf_check bectl -r ${zpool}/ROOT create -e default default2
193         sleep 1
194         atf_check bectl -r ${zpool}/ROOT create -e default2 default3
195         sleep 1
196         atf_check bectl -r ${zpool}/ROOT create -e default3 default4
197         atf_check bectl -r ${zpool}/ROOT destroy default3
198         atf_check bectl -r ${zpool}/ROOT destroy default2
199         atf_check bectl -r ${zpool}/ROOT destroy default4
200
201         # Create two BEs, then create an unrelated snapshot on the originating
202         # BE and destroy it.  We shouldn't have promoted the second BE, and it's
203         # only possible to tell if we promoted it by making sure we didn't
204         # demote the first BE at some point -- if we did, it's origin will no
205         # longer be empty.
206         atf_check bectl -r ${zpool}/ROOT create -e default default2
207         atf_check bectl -r ${zpool}/ROOT create default@test
208
209         atf_check bectl -r ${zpool}/ROOT destroy default@test
210         atf_check -o inline:"-\n" zfs get -Ho value origin ${zpool}/ROOT/default
211         atf_check bectl -r ${zpool}/ROOT destroy default2
212
213         # As observed by beadm, if we explicitly try to destroy a snapshot that
214         # leads to clones, we shouldn't have allowed it.
215         atf_check bectl -r ${zpool}/ROOT create default@test
216         atf_check bectl -r ${zpool}/ROOT create -e default@test default2
217
218         atf_check -e  not-empty -s not-exit:0 bectl -r ${zpool}/ROOT destroy \
219             default@test
220 }
221 bectl_destroy_cleanup()
222 {
223
224         bectl_cleanup $(get_zpool_name)
225 }
226
227 atf_test_case bectl_export_import cleanup
228 bectl_export_import_head()
229 {
230
231         atf_set "descr" "Check bectl export and import"
232         atf_set "require.user" root
233 }
234 bectl_export_import_body()
235 {
236         if [ "$(atf_config_get ci false)" = "true" ] && \
237                 [ "$(uname -p)" = "i386" ]; then
238                 atf_skip "https://bugs.freebsd.org/249055"
239         fi
240
241         cwd=$(realpath .)
242         zpool=$(make_zpool_name)
243         disk=${cwd}/disk.img
244         mount=${cwd}/mnt
245
246         bectl_create_setup ${zpool} ${disk} ${mount}
247         atf_check -o save:exported bectl -r ${zpool}/ROOT export default
248         atf_check -x "bectl -r ${zpool}/ROOT import default2 < exported"
249         atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
250         atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
251         atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
252             ${zpool}/ROOT/default2
253 }
254 bectl_export_import_cleanup()
255 {
256
257         bectl_cleanup $(get_zpool_name)
258 }
259
260 atf_test_case bectl_list cleanup
261 bectl_list_head()
262 {
263
264         atf_set "descr" "Check bectl list"
265         atf_set "require.user" root
266 }
267 bectl_list_body()
268 {
269         if [ "$(atf_config_get ci false)" = "true" ] && \
270                 [ "$(uname -p)" = "i386" ]; then
271                 atf_skip "https://bugs.freebsd.org/249055"
272         fi
273
274         cwd=$(realpath .)
275         zpool=$(make_zpool_name)
276         disk=${cwd}/disk.img
277         mount=${cwd}/mnt
278
279         bectl_create_setup ${zpool} ${disk} ${mount}
280         # Test the list functionality, including that BEs come and go away
281         # as they're created and destroyed.  Creation and destruction tests
282         # use the 'zfs' utility to verify that they're actually created, so
283         # these are just light tests that 'list' is picking them up.
284         atf_check -o save:list.out bectl -r ${zpool}/ROOT list
285         atf_check -o not-empty grep 'default' list.out
286         atf_check bectl -r ${zpool}/ROOT create -e default default2
287         atf_check -o save:list.out bectl -r ${zpool}/ROOT list
288         atf_check -o not-empty grep 'default2' list.out
289         atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
290         atf_check -o save:list.out bectl -r ${zpool}/ROOT list
291         atf_check -s not-exit:0 grep 'default2' list.out
292         # XXX TODO: Formatting checks
293 }
294 bectl_list_cleanup()
295 {
296
297         bectl_cleanup $(get_zpool_name)
298 }
299
300 atf_test_case bectl_mount cleanup
301 bectl_mount_head()
302 {
303
304         atf_set "descr" "Check bectl mount/unmount"
305         atf_set "require.user" root
306 }
307 bectl_mount_body()
308 {
309         if [ "$(atf_config_get ci false)" = "true" ] && \
310                 [ "$(uname -p)" = "i386" ]; then
311                 atf_skip "https://bugs.freebsd.org/249055"
312         fi
313
314         cwd=$(realpath .)
315         zpool=$(make_zpool_name)
316         disk=${cwd}/disk.img
317         mount=${cwd}/mnt
318         root=${mount}/root
319
320         bectl_create_deep_setup ${zpool} ${disk} ${mount}
321         atf_check mkdir -p ${root}
322         # Test unmount first...
323         atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
324         atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
325         atf_check bectl -r ${zpool}/ROOT unmount default
326         atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
327         # Then umount!
328         atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
329         atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
330         atf_check bectl -r ${zpool}/ROOT umount default
331         atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
332 }
333 bectl_mount_cleanup()
334 {
335
336         bectl_cleanup $(get_zpool_name)
337 }
338
339 atf_test_case bectl_rename cleanup
340 bectl_rename_head()
341 {
342
343         atf_set "descr" "Check bectl rename"
344         atf_set "require.user" root
345 }
346 bectl_rename_body()
347 {
348         if [ "$(atf_config_get ci false)" = "true" ] && \
349                 [ "$(uname -p)" = "i386" ]; then
350                 atf_skip "https://bugs.freebsd.org/249055"
351         fi
352
353         cwd=$(realpath .)
354         zpool=$(make_zpool_name)
355         disk=${cwd}/disk.img
356         mount=${cwd}/mnt
357
358         bectl_create_setup ${zpool} ${disk} ${mount}
359         atf_check bectl -r ${zpool}/ROOT rename default default2
360         atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
361         atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
362             ${zpool}/ROOT/default
363 }
364 bectl_rename_cleanup()
365 {
366
367         bectl_cleanup $(get_zpool_name)
368 }
369
370 atf_test_case bectl_jail cleanup
371 bectl_jail_head()
372 {
373
374         atf_set "descr" "Check bectl rename"
375         atf_set "require.user" root
376         atf_set "require.progs" jail
377 }
378 bectl_jail_body()
379 {
380         if [ "$(atf_config_get ci false)" = "true" ] && \
381                 [ "$(uname -p)" = "i386" ]; then
382                 atf_skip "https://bugs.freebsd.org/249055"
383         fi
384
385         cwd=$(realpath .)
386         zpool=$(make_zpool_name)
387         disk=${cwd}/disk.img
388         mount=${cwd}/mnt
389         root=${mount}/root
390
391         if [ ! -f /rescue/rescue ]; then
392                 atf_skip "This test requires a rescue binary"
393         fi
394         bectl_create_deep_setup ${zpool} ${disk} ${mount}
395         # Prepare our minimal BE... plop a rescue binary into it
396         atf_check mkdir -p ${root}
397         atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
398         atf_check mkdir -p ${root}/rescue
399         atf_check cp /rescue/rescue ${root}/rescue/rescue
400         atf_check bectl -r ${zpool}/ROOT umount default
401
402         # Prepare some more boot environments
403         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default target
404         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default 1234
405
406         # Attempt to unjail a BE with numeric name; jail_getid at one point
407         # did not validate that the input was a valid jid before returning the
408         # jid.
409         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b 1234
410         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail 1234
411
412         # When a jail name is not explicit, it should match the jail id.
413         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o jid=233637 default
414         atf_check -o inline:"233637\n" -s exit:0 -x "jls -j 233637 name"
415         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
416
417         # Basic command-mode tests, with and without jail cleanup
418         atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
419             jail default /rescue/rescue ls -1
420         atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
421             jail -Uo path=${root} default /rescue/rescue ls -1
422         atf_check [ -f ${root}/rescue/rescue ]
423         atf_check bectl -r ${zpool}/ROOT ujail default
424
425         # Batch mode tests
426         atf_check bectl -r ${zpool}/ROOT jail -bo path=${root} default
427         atf_check -o not-empty -x "jls | grep -F \"${root}\""
428         atf_check bectl -r ${zpool}/ROOT ujail default
429         atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
430         # 'unjail' naming
431         atf_check bectl -r ${zpool}/ROOT jail -b default
432         atf_check bectl -r ${zpool}/ROOT unjail default
433         atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
434         # 'unjail' by BE name. Force bectl to lookup jail id by the BE name.
435         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b default
436         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o name=bectl_test target
437         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail target
438         atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
439         # cannot unjail an unjailed BE (by either command name)
440         atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT ujail default
441         atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT unjail default
442
443         # set+unset
444         atf_check bectl -r ${zpool}/ROOT jail -b -o path=${root} -u path default
445         # Ensure that it didn't mount at ${root}
446         atf_check -s not-exit:0 -x "mount | grep -F '${root}'"
447         atf_check bectl -r ${zpool}/ROOT ujail default
448 }
449
450 # If a test has failed, it's possible that the boot environment hasn't
451 # been 'unjail'ed. We want to remove the jail before 'bectl_cleanup'
452 # attempts to destroy the zpool.
453 bectl_jail_cleanup()
454 {
455         if [ "$(atf_config_get ci false)" = "true" ] && \
456                 [ "$(uname -p)" = "i386" ]; then
457                 atf_skip "https://bugs.freebsd.org/249055"
458         fi
459
460         zpool=$(get_zpool_name)
461         for bootenv in "default" "target" "1234"; do
462                 # mountpoint of the boot environment
463                 mountpoint="$(bectl -r ${zpool}/ROOT list -H | grep ${bootenv} | awk '{print $3}')"
464
465                 # see if any jail paths match the boot environment mountpoint
466                 jailid="$(jls | grep ${mountpoint} | awk '{print $1}')"
467
468                 if [ -z "$jailid" ]; then
469                        continue;
470                 fi
471                 jail -r ${jailid}
472         done;
473
474         bectl_cleanup ${zpool}
475 }
476
477 atf_init_test_cases()
478 {
479         atf_add_test_case bectl_create
480         atf_add_test_case bectl_destroy
481         atf_add_test_case bectl_export_import
482         atf_add_test_case bectl_list
483         atf_add_test_case bectl_mount
484         atf_add_test_case bectl_rename
485         atf_add_test_case bectl_jail
486 }