1# SPDX-License-Identifier: BSD-2-Clause 2# 3# Copyright (c) 2024 Axcient 4# All rights reserved. 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 DOCUMENTATION IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26# Things that aren't tested due to lack of kernel support: 27# * Creating camsim ports 28# * Creating tpc ports 29# * Creating camtgt ports 30# * Creating umass ports 31 32# TODO 33# * Creating nvmf ports 34# * Creating ha ports 35# * Creating fc ports 36 37# The PGTAG can be any 16-bit number. The only constraint is that each 38# PGTAG,TARGET pair must be globally unique. 39PGTAG=30257 40 41load_cfiscsi() { 42 if ! kldstat -q -m cfiscsi; then 43 kldload cfiscsi || atf_skip "could not load cfscsi kernel mod" 44 fi 45} 46 47skip_if_ctld() { 48 if service ctld onestatus > /dev/null; then 49 # If ctld is running on this server, let's not interfere. 50 atf_skip "Cannot run this test while ctld is running" 51 fi 52} 53 54cleanup() { 55 driver=$1 56 57 if [ -e port-create.txt ]; then 58 case "$driver" in 59 "ioctl") 60 PORTNUM=`awk '/port:/ {print $2}' port-create.txt` 61 ctladm port -r -d $driver -p $PORTNUM 62 ;; 63 "iscsi") 64 TARGET=`awk '/target:/ {print $2}' port-create.txt` 65 ctladm port -r -d $driver -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target=$TARGET 66 ;; 67 esac 68 fi 69} 70 71atf_test_case create_ioctl cleanup 72create_ioctl_head() 73{ 74 atf_set "descr" "ctladm can create a new ioctl port" 75 atf_set "require.user" "root" 76 atf_set "require.progs" ctladm 77} 78create_ioctl_body() 79{ 80 skip_if_ctld 81 82 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 83 atf_check egrep -q "Port created successfully" port-create.txt 84 atf_check egrep -q "frontend: *ioctl" port-create.txt 85 atf_check egrep -q "port: *[0-9]+" port-create.txt 86 portnum=`awk '/port:/ {print $2}' port-create.txt` 87 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 88 atf_check egrep -q "$portnum *YES *ioctl *ioctl" portlist.txt 89} 90create_ioctl_cleanup() 91{ 92 cleanup ioctl 93} 94 95atf_test_case remove_ioctl_without_required_args cleanup 96remove_ioctl_without_required_args_head() 97{ 98 atf_set "descr" "ctladm will gracefully fail to remove an ioctl target if required arguments are missing" 99 atf_set "require.user" "root" 100 atf_set "require.progs" ctladm 101} 102remove_ioctl_without_required_args_body() 103{ 104 skip_if_ctld 105 106 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 107 atf_check egrep -q "Port created successfully" port-create.txt 108 atf_check -s exit:1 -e match:"Missing required argument: port_id" ctladm port -r -d "ioctl" 109} 110remove_ioctl_without_required_args_cleanup() 111{ 112 cleanup ioctl 113} 114 115atf_test_case create_iscsi cleanup 116create_iscsi_head() 117{ 118 atf_set "descr" "ctladm can create a new iscsi port" 119 atf_set "require.user" "root" 120 atf_set "require.progs" ctladm 121} 122create_iscsi_body() 123{ 124 skip_if_ctld 125 load_cfiscsi 126 127 TARGET=iqn.2018-10.myhost.create_iscsi 128 atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 129 echo "target: $TARGET" >> port-create.txt 130 atf_check egrep -q "Port created successfully" port-create.txt 131 atf_check egrep -q "frontend: *iscsi" port-create.txt 132 atf_check egrep -q "port: *[0-9]+" port-create.txt 133 atf_check -o save:portlist.txt ctladm portlist -qf iscsi 134 # Unlike the ioctl driver, the iscsi driver creates ports in a disabled 135 # state, so the port's lunmap may be set before enabling it. 136 atf_check egrep -q "$portnum *NO *iscsi *iscsi.*$TARGET" portlist.txt 137} 138create_iscsi_cleanup() 139{ 140 cleanup iscsi 141} 142 143atf_test_case create_iscsi_alias cleanup 144create_iscsi_alias_head() 145{ 146 atf_set "descr" "ctladm can create a new iscsi port with a target alias" 147 atf_set "require.user" "root" 148 atf_set "require.progs" ctladm 149} 150create_iscsi_alias_body() 151{ 152 skip_if_ctld 153 load_cfiscsi 154 155 TARGET=iqn.2018-10.myhost.create_iscsi_alias 156 ALIAS="foobar" 157 atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" -O cfiscsi_target_alias="$ALIAS" 158 echo "target: $TARGET" >> port-create.txt 159 atf_check egrep -q "Port created successfully" port-create.txt 160 atf_check egrep -q "frontend: *iscsi" port-create.txt 161 atf_check egrep -q "port: *[0-9]+" port-create.txt 162 atf_check -o save:portlist.txt ctladm portlist -qvf iscsi 163 atf_check egrep -q "cfiscsi_target_alias=$ALIAS" portlist.txt 164} 165create_iscsi_alias_cleanup() 166{ 167 cleanup iscsi 168} 169 170atf_test_case create_iscsi_without_required_args 171create_iscsi_without_required_args_head() 172{ 173 atf_set "descr" "ctladm will gracefully fail to create an iSCSI target if required arguments are missing" 174 atf_set "require.user" "root" 175 atf_set "require.progs" ctladm 176} 177create_iscsi_without_required_args_body() 178{ 179 skip_if_ctld 180 load_cfiscsi 181 182 TARGET=iqn.2018-10.myhost.create_iscsi 183 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_target" ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG 184 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_portal_group_tag" ctladm port -c -d "iscsi" -O cfiscsi_target=$TARGET 185} 186 187atf_test_case create_ioctl_options cleanup 188create_ioctl_options_head() 189{ 190 atf_set "descr" "ctladm can set options when creating a new ioctl port" 191 atf_set "require.user" "root" 192 atf_set "require.progs" ctladm 193} 194create_ioctl_options_body() 195{ 196 skip_if_ctld 197 198 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" -O pp=101 -O vp=102 199 atf_check egrep -q "Port created successfully" port-create.txt 200 atf_check egrep -q "frontend: *ioctl" port-create.txt 201 atf_check egrep -q "port: *[0-9]+" port-create.txt 202 portnum=`awk '/port:/ {print $2}' port-create.txt` 203 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 204 if ! egrep -q '101[[:space:]]+102' portlist.txt; then 205 ctladm portlist 206 atf_fail "Did not create the port with the specified options" 207 fi 208} 209create_ioctl_options_cleanup() 210{ 211 cleanup ioctl 212} 213 214 215atf_test_case disable_ioctl cleanup 216disable_ioctl_head() 217{ 218 atf_set "descr" "ctladm can disable an ioctl port" 219 atf_set "require.user" "root" 220 atf_set "require.progs" ctladm 221} 222disable_ioctl_body() 223{ 224 skip_if_ctld 225 226 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 227 portnum=`awk '/port:/ {print $2}' port-create.txt` 228 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 229 atf_check -o ignore ctladm port -o off -p $portnum 230 atf_check -o match:"^$portnum *NO" ctladm portlist -qf ioctl 231} 232disable_ioctl_cleanup() 233{ 234 cleanup ioctl 235} 236 237atf_test_case enable_ioctl cleanup 238enable_ioctl_head() 239{ 240 atf_set "descr" "ctladm can enable an ioctl port" 241 atf_set "require.user" "root" 242 atf_set "require.progs" ctladm 243} 244enable_ioctl_body() 245{ 246 skip_if_ctld 247 248 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 249 portnum=`awk '/port:/ {print $2}' port-create.txt` 250 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 251 atf_check -o ignore ctladm port -o off -p $portnum 252 atf_check -o ignore ctladm port -o on -p $portnum 253 atf_check -o match:"^$portnum *YES" ctladm portlist -qf ioctl 254} 255enable_ioctl_cleanup() 256{ 257 cleanup ioctl 258} 259 260atf_test_case remove_ioctl 261remove_ioctl_head() 262{ 263 atf_set "descr" "ctladm can remove an ioctl port" 264 atf_set "require.user" "root" 265 atf_set "require.progs" ctladm 266} 267remove_ioctl_body() 268{ 269 skip_if_ctld 270 271 # Specify exact pp and vp to make the post-removal portlist check 272 # unambiguous 273 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" -O pp=10001 -O vp=10002 274 portnum=`awk '/port:/ {print $2}' port-create.txt` 275 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 276 atf_check -o inline:"Port destroyed successfully\n" ctladm port -r -d ioctl -p $portnum 277 # Check that the port was removed. A new port may have been added with 278 # the same ID, so match against the pp and vp numbers, too. 279 if ctladm portlist -qf ioctl | egrep -q "^${portnum} .*10001 *10002"; then 280 ctladm portlist -qf ioctl 281 atf_fail "port was not removed" 282 fi 283} 284 285atf_test_case remove_iscsi 286remove_iscsi_head() 287{ 288 atf_set "descr" "ctladm can remove an iscsi port" 289 atf_set "require.user" "root" 290 atf_set "require.progs" ctladm 291} 292remove_iscsi_body() 293{ 294 skip_if_ctld 295 load_cfiscsi 296 297 TARGET=iqn.2018-10.myhost.remove_iscsi 298 atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 299 portnum=`awk '/port:/ {print $2}' port-create.txt` 300 atf_check -o save:portlist.txt ctladm portlist -qf iscsi 301 atf_check -o inline:"Port destroyed successfully\n" ctladm port -r -d iscsi -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 302 # Check that the port was removed. A new port may have been added with 303 # the same ID, so match against the target and tag, too. 304 PGTAGHEX=0x7631 # PGTAG in hex 305 if ctladm portlist -qf iscsi | egrep -q "^${portnum} .*$PGTAG +[0-9]+ +$TARGET,t,$PGTAGHEX"; then 306 ctladm portlist -qf iscsi 307 atf_fail "port was not removed" 308 fi 309} 310 311atf_test_case remove_iscsi_without_required_args cleanup 312remove_iscsi_without_required_args_head() 313{ 314 atf_set "descr" "ctladm will gracefully fail to remove an iSCSI target if required arguments are missing" 315 atf_set "require.user" "root" 316 atf_set "require.progs" ctladm 317} 318remove_iscsi_without_required_args_body() 319{ 320 skip_if_ctld 321 load_cfiscsi 322 323 TARGET=iqn.2018-10.myhost.remove_iscsi_without_required_args 324 atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 325 echo "target: $TARGET" >> port-create.txt 326 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_portal_group_tag" ctladm port -r -d iscsi -O cfiscsi_target="$TARGET" 327 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_target" ctladm port -r -d iscsi -O cfiscsi_portal_group_tag=$PGTAG 328} 329remove_iscsi_without_required_args_cleanup() 330{ 331 cleanup iscsi 332} 333 334atf_init_test_cases() 335{ 336 atf_add_test_case create_ioctl 337 atf_add_test_case create_iscsi 338 atf_add_test_case create_iscsi_without_required_args 339 atf_add_test_case create_iscsi_alias 340 atf_add_test_case create_ioctl_options 341 atf_add_test_case disable_ioctl 342 atf_add_test_case enable_ioctl 343 atf_add_test_case remove_ioctl 344 atf_add_test_case remove_ioctl_without_required_args 345 atf_add_test_case remove_iscsi 346 atf_add_test_case remove_iscsi_without_required_args 347} 348