2 # SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 # Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
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.
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
29 ZPOOL_NAME_FILE=zpool_name
36 mktemp -u bectl_test_XXXXXX > $ZPOOL_NAME_FILE
40 # Establishes a bectl_create zpool that can be used for some light testing; contains
41 # a 'default' BE and not much else.
48 # Sanity check to make sure `make_zpool_name` succeeded
49 atf_check test -n "$zpool"
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 \
59 bectl_create_deep_setup()
65 # Sanity check to make sure `make_zpool_name` succeeded
66 atf_check test -n "$zpool"
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
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}
87 atf_test_case bectl_create cleanup
91 atf_set "descr" "Check the various forms of bectl create"
92 atf_set "require.user" root
96 if [ "$(atf_config_get ci false)" = "true" ] && \
97 [ "$(uname -p)" = "i386" ]; then
98 atf_skip "https://bugs.freebsd.org/249055"
101 if [ "$(atf_config_get ci false)" = "true" ] && \
102 [ "$(uname -p)" = "armv7" ]; then
103 atf_skip "https://bugs.freebsd.org/249229"
107 zpool=$(make_zpool_name)
111 bectl_create_setup ${zpool} ${disk} ${mount}
113 # Create a child dataset that will be used to test creation
114 # of recursive and non-recursive boot environments.
115 atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
116 ${zpool}/ROOT/default/usr
118 # Test standard creation, creation of a snapshot, and creation from a
120 atf_check bectl -r ${zpool}/ROOT create -e default default2
121 atf_check bectl -r ${zpool}/ROOT create default2@test_snap
122 atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3
124 # Test standard creation, creation of a snapshot, and creation from a
125 # snapshot for recursive boot environments.
126 atf_check bectl -r ${zpool}/ROOT create -r -e default recursive
127 atf_check bectl -r ${zpool}/ROOT create -r recursive@test_snap
128 atf_check bectl -r ${zpool}/ROOT create -r -e recursive@test_snap recursive-snap
130 # Test that non-recursive boot environments have no child datasets.
131 atf_check -e not-empty -s not-exit:0 \
132 zfs list "${zpool}/ROOT/default2/usr"
133 atf_check -e not-empty -s not-exit:0 \
134 zfs list "${zpool}/ROOT/default3/usr"
136 # Test that recursive boot environments have child datasets.
137 atf_check -o not-empty \
138 zfs list "${zpool}/ROOT/recursive/usr"
139 atf_check -o not-empty \
140 zfs list "${zpool}/ROOT/recursive-snap/usr"
142 bectl_create_cleanup()
144 bectl_cleanup $(get_zpool_name)
147 atf_test_case bectl_destroy cleanup
151 atf_set "descr" "Check bectl destroy"
152 atf_set "require.user" root
156 if [ "$(atf_config_get ci false)" = "true" ] && \
157 [ "$(uname -p)" = "i386" ]; then
158 atf_skip "https://bugs.freebsd.org/249055"
161 if [ "$(atf_config_get ci false)" = "true" ] && \
162 [ "$(uname -p)" = "armv7" ]; then
163 atf_skip "https://bugs.freebsd.org/249229"
167 zpool=$(make_zpool_name)
172 bectl_create_setup ${zpool} ${disk} ${mount}
173 atf_check bectl -r ${zpool}/ROOT create -e default default2
174 atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
175 atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
176 atf_check -e not-empty -s not-exit:0 zfs get mountpoint ${zpool}/ROOT/default2
178 # Test origin snapshot deletion when the snapshot to be destroyed
179 # belongs to a mounted dataset, see PR 236043.
180 atf_check mkdir -p ${root}
181 atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
182 atf_check bectl -r ${zpool}/ROOT create -e default default3
183 atf_check bectl -r ${zpool}/ROOT destroy -o default3
184 atf_check bectl -r ${zpool}/ROOT unmount default
186 # create two be from the same parent and destroy the parent
187 atf_check bectl -r ${zpool}/ROOT create -e default default2
188 atf_check bectl -r ${zpool}/ROOT create -e default default3
189 atf_check bectl -r ${zpool}/ROOT destroy default
190 atf_check bectl -r ${zpool}/ROOT destroy default2
191 atf_check bectl -r ${zpool}/ROOT rename default3 default
193 # Create a BE, have it be the parent for another and repeat, then start
194 # deleting environments. Arbitrarily chose default3 as the first.
195 # Sleeps are required to prevent conflicting snapshots- libbe will
196 # use the time with a serial at the end as needed to prevent collisions,
197 # but as BEs get promoted the snapshot names will convert and conflict
198 # anyways. libbe should perhaps consider adding something extra to the
199 # default name to prevent collisions like this, but the default name
200 # includes down to the second and creating BEs this rapidly is perhaps
202 atf_check bectl -r ${zpool}/ROOT create -e default default2
204 atf_check bectl -r ${zpool}/ROOT create -e default2 default3
206 atf_check bectl -r ${zpool}/ROOT create -e default3 default4
207 atf_check bectl -r ${zpool}/ROOT destroy default3
208 atf_check bectl -r ${zpool}/ROOT destroy default2
209 atf_check bectl -r ${zpool}/ROOT destroy default4
211 # Create two BEs, then create an unrelated snapshot on the originating
212 # BE and destroy it. We shouldn't have promoted the second BE, and it's
213 # only possible to tell if we promoted it by making sure we didn't
214 # demote the first BE at some point -- if we did, it's origin will no
216 atf_check bectl -r ${zpool}/ROOT create -e default default2
217 atf_check bectl -r ${zpool}/ROOT create default@test
219 atf_check bectl -r ${zpool}/ROOT destroy default@test
220 atf_check -o inline:"-\n" zfs get -Ho value origin ${zpool}/ROOT/default
221 atf_check bectl -r ${zpool}/ROOT destroy default2
223 # As observed by beadm, if we explicitly try to destroy a snapshot that
224 # leads to clones, we shouldn't have allowed it.
225 atf_check bectl -r ${zpool}/ROOT create default@test
226 atf_check bectl -r ${zpool}/ROOT create -e default@test default2
228 atf_check -e not-empty -s not-exit:0 bectl -r ${zpool}/ROOT destroy \
231 bectl_destroy_cleanup()
234 bectl_cleanup $(get_zpool_name)
237 atf_test_case bectl_export_import cleanup
238 bectl_export_import_head()
241 atf_set "descr" "Check bectl export and import"
242 atf_set "require.user" root
244 bectl_export_import_body()
246 if [ "$(atf_config_get ci false)" = "true" ] && \
247 [ "$(uname -p)" = "i386" ]; then
248 atf_skip "https://bugs.freebsd.org/249055"
251 if [ "$(atf_config_get ci false)" = "true" ] && \
252 [ "$(uname -p)" = "armv7" ]; then
253 atf_skip "https://bugs.freebsd.org/249229"
257 zpool=$(make_zpool_name)
261 bectl_create_setup ${zpool} ${disk} ${mount}
262 atf_check -o save:exported bectl -r ${zpool}/ROOT export default
263 atf_check -x "bectl -r ${zpool}/ROOT import default2 < exported"
264 atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
265 atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
266 atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
267 ${zpool}/ROOT/default2
269 bectl_export_import_cleanup()
272 bectl_cleanup $(get_zpool_name)
275 atf_test_case bectl_list cleanup
279 atf_set "descr" "Check bectl list"
280 atf_set "require.user" root
284 if [ "$(atf_config_get ci false)" = "true" ] && \
285 [ "$(uname -p)" = "i386" ]; then
286 atf_skip "https://bugs.freebsd.org/249055"
289 if [ "$(atf_config_get ci false)" = "true" ] && \
290 [ "$(uname -p)" = "armv7" ]; then
291 atf_skip "https://bugs.freebsd.org/249229"
295 zpool=$(make_zpool_name)
299 bectl_create_setup ${zpool} ${disk} ${mount}
300 # Test the list functionality, including that BEs come and go away
301 # as they're created and destroyed. Creation and destruction tests
302 # use the 'zfs' utility to verify that they're actually created, so
303 # these are just light tests that 'list' is picking them up.
304 atf_check -o save:list.out bectl -r ${zpool}/ROOT list
305 atf_check -o not-empty grep 'default' list.out
306 atf_check bectl -r ${zpool}/ROOT create -e default default2
307 atf_check -o save:list.out bectl -r ${zpool}/ROOT list
308 atf_check -o not-empty grep 'default2' list.out
309 atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2
310 atf_check -o save:list.out bectl -r ${zpool}/ROOT list
311 atf_check -s not-exit:0 grep 'default2' list.out
312 # XXX TODO: Formatting checks
317 bectl_cleanup $(get_zpool_name)
320 atf_test_case bectl_mount cleanup
324 atf_set "descr" "Check bectl mount/unmount"
325 atf_set "require.user" root
329 if [ "$(atf_config_get ci false)" = "true" ] && \
330 [ "$(uname -p)" = "i386" ]; then
331 atf_skip "https://bugs.freebsd.org/249055"
334 if [ "$(atf_config_get ci false)" = "true" ] && \
335 [ "$(uname -p)" = "armv7" ]; then
336 atf_skip "https://bugs.freebsd.org/249229"
340 zpool=$(make_zpool_name)
345 bectl_create_deep_setup ${zpool} ${disk} ${mount}
346 atf_check mkdir -p ${root}
347 # Test unmount first...
348 atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
349 atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
350 atf_check bectl -r ${zpool}/ROOT unmount default
351 atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
353 atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
354 atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
355 atf_check bectl -r ${zpool}/ROOT umount default
356 atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
358 bectl_mount_cleanup()
361 bectl_cleanup $(get_zpool_name)
364 atf_test_case bectl_rename cleanup
368 atf_set "descr" "Check bectl rename"
369 atf_set "require.user" root
373 if [ "$(atf_config_get ci false)" = "true" ] && \
374 [ "$(uname -p)" = "i386" ]; then
375 atf_skip "https://bugs.freebsd.org/249055"
378 if [ "$(atf_config_get ci false)" = "true" ] && \
379 [ "$(uname -p)" = "armv7" ]; then
380 atf_skip "https://bugs.freebsd.org/249229"
384 zpool=$(make_zpool_name)
388 bectl_create_setup ${zpool} ${disk} ${mount}
389 atf_check bectl -r ${zpool}/ROOT rename default default2
390 atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
391 atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
392 ${zpool}/ROOT/default
394 bectl_rename_cleanup()
397 bectl_cleanup $(get_zpool_name)
400 atf_test_case bectl_jail cleanup
404 atf_set "descr" "Check bectl rename"
405 atf_set "require.user" root
406 atf_set "require.progs" jail
410 if [ "$(atf_config_get ci false)" = "true" ] && \
411 [ "$(uname -p)" = "i386" ]; then
412 atf_skip "https://bugs.freebsd.org/249055"
415 if [ "$(atf_config_get ci false)" = "true" ] && \
416 [ "$(uname -p)" = "armv7" ]; then
417 atf_skip "https://bugs.freebsd.org/249229"
421 zpool=$(make_zpool_name)
426 if [ ! -f /rescue/rescue ]; then
427 atf_skip "This test requires a rescue binary"
429 bectl_create_deep_setup ${zpool} ${disk} ${mount}
430 # Prepare our minimal BE... plop a rescue binary into it
431 atf_check mkdir -p ${root}
432 atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
433 atf_check mkdir -p ${root}/rescue
434 atf_check cp /rescue/rescue ${root}/rescue/rescue
435 atf_check bectl -r ${zpool}/ROOT umount default
437 # Prepare some more boot environments
438 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default target
439 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default 1234
441 # Attempt to unjail a BE with numeric name; jail_getid at one point
442 # did not validate that the input was a valid jid before returning the
444 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b 1234
445 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail 1234
447 # When a jail name is not explicit, it should match the jail id.
448 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o jid=233637 default
449 atf_check -o inline:"233637\n" -s exit:0 -x "jls -j 233637 name"
450 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
452 # Basic command-mode tests, with and without jail cleanup
453 atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
454 jail default /rescue/rescue ls -1
455 atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
456 jail -Uo path=${root} default /rescue/rescue ls -1
457 atf_check [ -f ${root}/rescue/rescue ]
458 atf_check bectl -r ${zpool}/ROOT ujail default
461 atf_check bectl -r ${zpool}/ROOT jail -bo path=${root} default
462 atf_check -o not-empty -x "jls | grep -F \"${root}\""
463 atf_check bectl -r ${zpool}/ROOT ujail default
464 atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
466 atf_check bectl -r ${zpool}/ROOT jail -b default
467 atf_check bectl -r ${zpool}/ROOT unjail default
468 atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
469 # 'unjail' by BE name. Force bectl to lookup jail id by the BE name.
470 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b default
471 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o name=bectl_test target
472 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail target
473 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
474 # cannot unjail an unjailed BE (by either command name)
475 atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT ujail default
476 atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT unjail default
479 atf_check bectl -r ${zpool}/ROOT jail -b -o path=${root} -u path default
480 # Ensure that it didn't mount at ${root}
481 atf_check -s not-exit:0 -x "mount | grep -F '${root}'"
482 atf_check bectl -r ${zpool}/ROOT ujail default
485 # If a test has failed, it's possible that the boot environment hasn't
486 # been 'unjail'ed. We want to remove the jail before 'bectl_cleanup'
487 # attempts to destroy the zpool.
490 if [ "$(atf_config_get ci false)" = "true" ] && \
491 [ "$(uname -p)" = "i386" ]; then
492 atf_skip "https://bugs.freebsd.org/249055"
495 if [ "$(atf_config_get ci false)" = "true" ] && \
496 [ "$(uname -p)" = "armv7" ]; then
497 atf_skip "https://bugs.freebsd.org/249229"
500 zpool=$(get_zpool_name)
501 for bootenv in "default" "target" "1234"; do
502 # mountpoint of the boot environment
503 mountpoint="$(bectl -r ${zpool}/ROOT list -H | grep ${bootenv} | awk '{print $3}')"
505 # see if any jail paths match the boot environment mountpoint
506 jailid="$(jls | grep ${mountpoint} | awk '{print $1}')"
508 if [ -z "$jailid" ]; then
514 bectl_cleanup ${zpool}
517 atf_init_test_cases()
519 atf_add_test_case bectl_create
520 atf_add_test_case bectl_destroy
521 atf_add_test_case bectl_export_import
522 atf_add_test_case bectl_list
523 atf_add_test_case bectl_mount
524 atf_add_test_case bectl_rename
525 atf_add_test_case bectl_jail