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