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 29ZPOOL_NAME_FILE=zpool_name 30get_zpool_name() 31{ 32 cat $ZPOOL_NAME_FILE 33} 34make_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. 42bectl_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} 59bectl_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 77bectl_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 87atf_test_case bectl_create cleanup 88bectl_create_head() 89{ 90 91 atf_set "descr" "Check the various forms of bectl create" 92 atf_set "require.user" root 93} 94bectl_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 # Test standard creation, creation of a snapshot, and creation from a 103 # snapshot. 104 atf_check bectl -r ${zpool}/ROOT create -e default default2 105 atf_check bectl -r ${zpool}/ROOT create default2@test_snap 106 atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3 107} 108bectl_create_cleanup() 109{ 110 bectl_cleanup $(get_zpool_name) 111} 112 113atf_test_case bectl_destroy cleanup 114bectl_destroy_head() 115{ 116 117 atf_set "descr" "Check bectl destroy" 118 atf_set "require.user" root 119} 120bectl_destroy_body() 121{ 122 cwd=$(realpath .) 123 zpool=$(make_zpool_name) 124 disk=${cwd}/disk.img 125 mount=${cwd}/mnt 126 127 bectl_create_setup ${zpool} ${disk} ${mount} 128 atf_check bectl -r ${zpool}/ROOT create -e default default2 129 atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2 130 atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2 131 atf_check -e not-empty -s not-exit:0 zfs get mountpoint ${zpool}/ROOT/default2 132} 133bectl_destroy_cleanup() 134{ 135 136 bectl_cleanup $(get_zpool_name) 137} 138 139atf_test_case bectl_export_import cleanup 140bectl_export_import_head() 141{ 142 143 atf_set "descr" "Check bectl export and import" 144 atf_set "require.user" root 145} 146bectl_export_import_body() 147{ 148 cwd=$(realpath .) 149 zpool=$(make_zpool_name) 150 disk=${cwd}/disk.img 151 mount=${cwd}/mnt 152 153 bectl_create_setup ${zpool} ${disk} ${mount} 154 atf_check -o save:exported bectl -r ${zpool}/ROOT export default 155 atf_check -x "bectl -r ${zpool}/ROOT import default2 < exported" 156 atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2 157 atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2 158 atf_check -e not-empty -s not-exit:0 zfs get mountpoint \ 159 ${zpool}/ROOT/default2 160} 161bectl_export_import_cleanup() 162{ 163 164 bectl_cleanup $(get_zpool_name) 165} 166 167atf_test_case bectl_list cleanup 168bectl_list_head() 169{ 170 171 atf_set "descr" "Check bectl list" 172 atf_set "require.user" root 173} 174bectl_list_body() 175{ 176 cwd=$(realpath .) 177 zpool=$(make_zpool_name) 178 disk=${cwd}/disk.img 179 mount=${cwd}/mnt 180 181 bectl_create_setup ${zpool} ${disk} ${mount} 182 # Test the list functionality, including that BEs come and go away 183 # as they're created and destroyed. Creation and destruction tests 184 # use the 'zfs' utility to verify that they're actually created, so 185 # these are just light tests that 'list' is picking them up. 186 atf_check -o save:list.out bectl -r ${zpool}/ROOT list 187 atf_check -o not-empty grep 'default' list.out 188 atf_check bectl -r ${zpool}/ROOT create -e default default2 189 atf_check -o save:list.out bectl -r ${zpool}/ROOT list 190 atf_check -o not-empty grep 'default2' list.out 191 atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2 192 atf_check -o save:list.out bectl -r ${zpool}/ROOT list 193 atf_check -s not-exit:0 grep 'default2' list.out 194 # XXX TODO: Formatting checks 195} 196bectl_list_cleanup() 197{ 198 199 bectl_cleanup $(get_zpool_name) 200} 201 202atf_test_case bectl_mount cleanup 203bectl_mount_head() 204{ 205 206 atf_set "descr" "Check bectl mount/unmount" 207 atf_set "require.user" root 208} 209bectl_mount_body() 210{ 211 cwd=$(realpath .) 212 zpool=$(make_zpool_name) 213 disk=${cwd}/disk.img 214 mount=${cwd}/mnt 215 root=${mount}/root 216 217 bectl_create_deep_setup ${zpool} ${disk} ${mount} 218 atf_check mkdir -p ${root} 219 # Test unmount first... 220 atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root} 221 atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'" 222 atf_check bectl -r ${zpool}/ROOT unmount default 223 atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'" 224 # Then umount! 225 atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root} 226 atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'" 227 atf_check bectl -r ${zpool}/ROOT umount default 228 atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'" 229} 230bectl_mount_cleanup() 231{ 232 233 bectl_cleanup $(get_zpool_name) 234} 235 236atf_test_case bectl_rename cleanup 237bectl_rename_head() 238{ 239 240 atf_set "descr" "Check bectl rename" 241 atf_set "require.user" root 242} 243bectl_rename_body() 244{ 245 cwd=$(realpath .) 246 zpool=$(make_zpool_name) 247 disk=${cwd}/disk.img 248 mount=${cwd}/mnt 249 250 bectl_create_setup ${zpool} ${disk} ${mount} 251 atf_check bectl -r ${zpool}/ROOT rename default default2 252 atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2 253 atf_check -e not-empty -s not-exit:0 zfs get mountpoint \ 254 ${zpool}/ROOT/default 255} 256bectl_rename_cleanup() 257{ 258 259 bectl_cleanup $(get_zpool_name) 260} 261 262atf_test_case bectl_jail cleanup 263bectl_jail_head() 264{ 265 266 atf_set "descr" "Check bectl rename" 267 atf_set "require.user" root 268} 269bectl_jail_body() 270{ 271 cwd=$(realpath .) 272 zpool=$(make_zpool_name) 273 disk=${cwd}/disk.img 274 mount=${cwd}/mnt 275 root=${mount}/root 276 277 if [ ! -f /rescue/rescue ]; then 278 atf_skip "This test requires a rescue binary" 279 fi 280 bectl_create_deep_setup ${zpool} ${disk} ${mount} 281 # Prepare our minimal BE... plop a rescue binary into it 282 atf_check mkdir -p ${root} 283 atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root} 284 atf_check mkdir -p ${root}/rescue 285 atf_check cp /rescue/rescue ${root}/rescue/rescue 286 atf_check bectl -r ${zpool}/ROOT umount default 287 288 # Prepare a second boot environment 289 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default target 290 291 # When a jail name is not explicit, it should match the jail id. 292 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o jid=233637 default 293 atf_check -o inline:"233637\n" -s exit:0 -x "jls -j 233637 name" 294 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default 295 296 # Basic command-mode tests, with and without jail cleanup 297 atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \ 298 jail default /rescue/rescue ls -1 299 atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \ 300 jail -Uo path=${root} default /rescue/rescue ls -1 301 atf_check [ -f ${root}/rescue/rescue ] 302 atf_check bectl -r ${zpool}/ROOT ujail default 303 304 # Batch mode tests 305 atf_check bectl -r ${zpool}/ROOT jail -bo path=${root} default 306 atf_check -o not-empty -x "jls | grep -F \"${root}\"" 307 atf_check bectl -r ${zpool}/ROOT ujail default 308 atf_check -s not-exit:0 -x "jls | grep -F \"${root}\"" 309 # 'unjail' naming 310 atf_check bectl -r ${zpool}/ROOT jail -b default 311 atf_check bectl -r ${zpool}/ROOT unjail default 312 atf_check -s not-exit:0 -x "jls | grep -F \"${root}\"" 313 # 'unjail' by BE name. Force bectl to lookup jail id by the BE name. 314 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b default 315 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o name=bectl_test target 316 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail target 317 atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default 318 # cannot unjail an unjailed BE (by either command name) 319 atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT ujail default 320 atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT unjail default 321 322 # set+unset 323 atf_check bectl -r ${zpool}/ROOT jail -b -o path=${root} -u path default 324 # Ensure that it didn't mount at ${root} 325 atf_check -s not-exit:0 -x "mount | grep -F '${root}'" 326 atf_check bectl -r ${zpool}/ROOT ujail default 327} 328 329# If a test has failed, it's possible that the boot environment hasn't 330# been 'unjail'ed. We want to remove the jail before 'bectl_cleanup' 331# attempts to destroy the zpool. 332bectl_jail_cleanup() 333{ 334 for bootenv in "default" "target"; do 335 # mountpoint of the boot environment 336 mountpoint="$(bectl -r bectl_test/ROOT list -H | grep ${bootenv} | awk '{print $3}')" 337 338 # see if any jail paths match the boot environment mountpoint 339 jailid="$(jls | grep ${mountpoint} | awk '{print $1}')" 340 341 if [ -z "$jailid" ]; then 342 continue; 343 fi 344 jail -r ${jailid} 345 done; 346 347 bectl_cleanup $(get_zpool_name) 348} 349 350atf_init_test_cases() 351{ 352 atf_add_test_case bectl_create 353 atf_add_test_case bectl_destroy 354 atf_add_test_case bectl_export_import 355 atf_add_test_case bectl_list 356 atf_add_test_case bectl_mount 357 atf_add_test_case bectl_rename 358 atf_add_test_case bectl_jail 359} 360