xref: /freebsd/sbin/bectl/tests/bectl_test.sh (revision 6871d4882591c9a8fcab24d084c93f0a2972e1af)
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# Establishes a bectl_create zpool that can be used for some light testing; contains
30# a 'default' BE and not much else.
31bectl_create_setup()
32{
33	zpool=$1
34	disk=$2
35	mnt=$3
36
37	kldload -n -q zfs || atf_skip "ZFS module not loaded on the current system"
38	atf_check mkdir -p ${mnt}
39	atf_check truncate -s 1G ${disk}
40	atf_check zpool create -o altroot=${mnt} ${zpool} ${disk}
41	atf_check zfs create -o mountpoint=none ${zpool}/ROOT
42	atf_check zfs create -o mountpoint=/ -o canmount=noauto \
43	    ${zpool}/ROOT/default
44}
45
46bectl_cleanup()
47{
48	zpool=$1
49
50	if zpool get health ${zpool} >/dev/null 2>&1; then
51		zpool destroy ${zpool}
52	fi
53}
54
55atf_test_case bectl_create cleanup
56bectl_create_head()
57{
58
59	atf_set "descr" "Check the various forms of bectl create"
60	atf_set "require.user" root
61}
62bectl_create_body()
63{
64	cwd=$(realpath .)
65	zpool=bectl_test
66	disk=${cwd}/disk.img
67	mount=${cwd}/mnt
68
69	bectl_create_setup ${zpool} ${disk} ${mount}
70	# Test standard creation, creation of a snapshot, and creation from a
71	# snapshot.
72	atf_check bectl -r ${zpool}/ROOT create -e default default2
73	atf_check bectl -r ${zpool}/ROOT create default2@test_snap
74	atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3
75}
76bectl_create_cleanup()
77{
78
79	bectl_cleanup bectl_test
80}
81
82atf_test_case bectl_destroy cleanup
83bectl_destroy_head()
84{
85
86	atf_set "descr" "Check bectl destroy"
87	atf_set "require.user" root
88}
89bectl_destroy_body()
90{
91	cwd=$(realpath .)
92	zpool=bectl_test
93	disk=${cwd}/disk.img
94	mount=${cwd}/mnt
95
96	bectl_create_setup ${zpool} ${disk} ${mount}
97	atf_check bectl -r ${zpool}/ROOT create -e default default2
98	atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
99	atf_check bectl -r ${zpool}/ROOT destroy default2
100	atf_check -e not-empty -s not-exit:0 zfs get mountpoint ${zpool}/ROOT/default2
101}
102bectl_destroy_cleanup()
103{
104
105	bectl_cleanup bectl_test
106}
107
108atf_test_case bectl_export_import cleanup
109bectl_export_import_head()
110{
111
112	atf_set "descr" "Check bectl export and import"
113	atf_set "require.user" root
114}
115bectl_export_import_body()
116{
117	cwd=$(realpath .)
118	zpool=bectl_test
119	disk=${cwd}/disk.img
120	mount=${cwd}/mnt
121
122	bectl_create_setup ${zpool} ${disk} ${mount}
123	atf_check -o save:exported bectl -r ${zpool}/ROOT export default
124	atf_check -x "bectl -r ${zpool}/ROOT import default2 < exported"
125	atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
126	atf_check bectl -r ${zpool}/ROOT destroy default2
127	atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
128	    ${zpool}/ROOT/default2
129}
130bectl_export_import_cleanup()
131{
132
133	bectl_cleanup bectl_test
134}
135
136atf_test_case bectl_list cleanup
137bectl_list_head()
138{
139
140	atf_set "descr" "Check bectl list"
141	atf_set "require.user" root
142}
143bectl_list_body()
144{
145	cwd=$(realpath .)
146	zpool=bectl_test
147	disk=${cwd}/disk.img
148	mount=${cwd}/mnt
149
150	bectl_create_setup ${zpool} ${disk} ${mount}
151	# Test the list functionality, including that BEs come and go away
152	# as they're created and destroyed.  Creation and destruction tests
153	# use the 'zfs' utility to verify that they're actually created, so
154	# these are just light tests that 'list' is picking them up.
155	atf_check -o save:list.out bectl -r ${zpool}/ROOT list
156	atf_check -o not-empty grep 'default' list.out
157	atf_check bectl -r ${zpool}/ROOT create -e default default2
158	atf_check -o save:list.out bectl -r ${zpool}/ROOT list
159	atf_check -o not-empty grep 'default2' list.out
160	atf_check bectl -r ${zpool}/ROOT destroy default2
161	atf_check -o save:list.out bectl -r ${zpool}/ROOT list
162	atf_check -s not-exit:0 grep 'default2' list.out
163	# XXX TODO: Formatting checks
164}
165bectl_list_cleanup()
166{
167
168	bectl_cleanup bectl_test
169}
170
171atf_test_case bectl_mount cleanup
172bectl_mount_head()
173{
174
175	atf_set "descr" "Check bectl mount/unmount"
176	atf_set "require.user" root
177}
178bectl_mount_body()
179{
180	cwd=$(realpath .)
181	zpool=bectl_test
182	disk=${cwd}/disk.img
183	mount=${cwd}/mnt
184	root=${mount}/root
185
186	bectl_create_setup ${zpool} ${disk} ${mount}
187	atf_check mkdir -p ${root}
188	# Test unmount first...
189	atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
190	atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
191	atf_check bectl -r ${zpool}/ROOT unmount default
192	atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
193	# Then umount!
194	atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
195	atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
196	atf_check bectl -r ${zpool}/ROOT umount default
197	atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
198}
199bectl_mount_cleanup()
200{
201
202	bectl_cleanup bectl_test
203}
204
205atf_test_case bectl_rename cleanup
206bectl_rename_head()
207{
208
209	atf_set "descr" "Check bectl rename"
210	atf_set "require.user" root
211}
212bectl_rename_body()
213{
214	cwd=$(realpath .)
215	zpool=bectl_test
216	disk=${cwd}/disk.img
217	mount=${cwd}/mnt
218
219	bectl_create_setup ${zpool} ${disk} ${mount}
220	atf_check bectl -r ${zpool}/ROOT rename default default2
221	atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
222	atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
223	    ${zpool}/ROOT/default
224}
225bectl_rename_cleanup()
226{
227
228	bectl_cleanup bectl_test
229}
230
231atf_test_case bectl_jail cleanup
232bectl_jail_head()
233{
234
235	atf_set "descr" "Check bectl rename"
236	atf_set "require.user" root
237}
238bectl_jail_body()
239{
240	cwd=$(realpath .)
241	zpool=bectl_test
242	disk=${cwd}/disk.img
243	mount=${cwd}/mnt
244	root=${mount}/root
245
246	if [ ! -f /rescue/rescue ]; then
247		atf_skip "This test requires a rescue binary"
248	fi
249	bectl_create_setup ${zpool} ${disk} ${mount}
250	# Prepare our minimal BE... plop a rescue binary into it
251	atf_check mkdir -p ${root}
252	atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
253	atf_check mkdir -p ${root}/rescue
254	atf_check cp /rescue/rescue ${root}/rescue/rescue
255	atf_check bectl -r ${zpool}/ROOT umount default
256
257	# Prepare a second boot environment
258	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default target
259
260	# When a jail name is not explicit, it should match the jail id.
261	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o jid=233637 default
262	atf_check -o inline:"233637\n" -s exit:0 -x "jls -j 233637 name"
263	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
264
265	# Basic command-mode tests, with and without jail cleanup
266	atf_check -o inline:"rescue\n" bectl -r ${zpool}/ROOT \
267	    jail default /rescue/rescue ls -1
268	atf_check -o inline:"rescue\n" bectl -r ${zpool}/ROOT \
269	    jail -Uo path=${root} default /rescue/rescue ls -1
270	atf_check [ -f ${root}/rescue/rescue ]
271	atf_check bectl -r ${zpool}/ROOT ujail default
272
273	# Batch mode tests
274	atf_check bectl -r ${zpool}/ROOT jail -bo path=${root} default
275	atf_check -o not-empty -x "jls | grep -F \"${root}\""
276	atf_check bectl -r ${zpool}/ROOT ujail default
277	atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
278	# 'unjail' naming
279	atf_check bectl -r ${zpool}/ROOT jail -b default
280	atf_check bectl -r ${zpool}/ROOT unjail default
281	atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
282	# 'unjail' by BE name. Force bectl to lookup jail id by the BE name.
283	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b default
284	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o name=bectl_test target
285	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail target
286	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
287	# cannot unjail an unjailed BE (by either command name)
288	atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT ujail default
289	atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT unjail default
290
291	# set+unset
292	atf_check bectl -r ${zpool}/ROOT jail -b -o path=${root} -u path default
293	# Ensure that it didn't mount at ${root}
294	atf_check -s not-exit:0 -x "mount | grep -F '${root}'"
295	atf_check bectl -r ${zpool}/ROOT ujail default
296}
297
298# If a test has failed, it's possible that the boot environment hasn't
299# been 'unjail'ed. We want to remove the jail before 'bectl_cleanup'
300# attempts to destroy the zpool.
301bectl_jail_cleanup()
302{
303	for bootenv in "default" "target"; do
304		# mountpoint of the boot environment
305		mountpoint="$(bectl -r bectl_test/ROOT list -H | grep ${bootenv} | awk '{print $3}')"
306
307		# see if any jail paths match the boot environment mountpoint
308		jailid="$(jls | grep ${mountpoint} | awk '{print $1}')"
309
310		if [ -z "$jailid" ]; then
311		       continue;
312		fi
313		jail -r ${jailid}
314	done;
315
316	bectl_cleanup bectl_test
317}
318
319atf_init_test_cases()
320{
321	atf_add_test_case bectl_create
322	atf_add_test_case bectl_destroy
323	atf_add_test_case bectl_export_import
324	atf_add_test_case bectl_list
325	atf_add_test_case bectl_mount
326	atf_add_test_case bectl_rename
327	atf_add_test_case bectl_jail
328}
329