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} 77create_ioctl_body() 78{ 79 skip_if_ctld 80 81 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 82 atf_check egrep -q "Port created successfully" port-create.txt 83 atf_check egrep -q "frontend: *ioctl" port-create.txt 84 atf_check egrep -q "port: *[0-9]+" port-create.txt 85 portnum=`awk '/port:/ {print $2}' port-create.txt` 86 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 87 atf_check egrep -q "$portnum *YES *ioctl *ioctl" portlist.txt 88} 89create_ioctl_cleanup() 90{ 91 cleanup ioctl 92} 93 94atf_test_case remove_ioctl_without_required_args cleanup 95remove_ioctl_without_required_args_head() 96{ 97 atf_set "descr" "ctladm will gracefully fail to remove an ioctl target if required arguments are missing" 98 atf_set "require.user" "root" 99} 100remove_ioctl_without_required_args_body() 101{ 102 skip_if_ctld 103 104 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 105 atf_check egrep -q "Port created successfully" port-create.txt 106 atf_check -s exit:1 -e match:"Missing required argument: port_id" ctladm port -r -d "ioctl" 107} 108remove_ioctl_without_required_args_cleanup() 109{ 110 cleanup ioctl 111} 112 113atf_test_case create_iscsi cleanup 114create_iscsi_head() 115{ 116 atf_set "descr" "ctladm can create a new iscsi port" 117 atf_set "require.user" "root" 118} 119create_iscsi_body() 120{ 121 skip_if_ctld 122 load_cfiscsi 123 124 TARGET=iqn.2018-10.myhost.create_iscsi 125 atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 126 echo "target: $TARGET" >> port-create.txt 127 atf_check egrep -q "Port created successfully" port-create.txt 128 atf_check egrep -q "frontend: *iscsi" port-create.txt 129 atf_check egrep -q "port: *[0-9]+" port-create.txt 130 atf_check -o save:portlist.txt ctladm portlist -qf iscsi 131 # Unlike the ioctl driver, the iscsi driver creates ports in a disabled 132 # state, so the port's lunmap may be set before enabling it. 133 atf_check egrep -q "$portnum *NO *iscsi *iscsi.*$TARGET" portlist.txt 134} 135create_iscsi_cleanup() 136{ 137 cleanup iscsi 138} 139 140atf_test_case create_iscsi_alias cleanup 141create_iscsi_alias_head() 142{ 143 atf_set "descr" "ctladm can create a new iscsi port with a target alias" 144 atf_set "require.user" "root" 145} 146create_iscsi_alias_body() 147{ 148 skip_if_ctld 149 load_cfiscsi 150 151 TARGET=iqn.2018-10.myhost.create_iscsi_alias 152 ALIAS="foobar" 153 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" 154 echo "target: $TARGET" >> port-create.txt 155 atf_check egrep -q "Port created successfully" port-create.txt 156 atf_check egrep -q "frontend: *iscsi" port-create.txt 157 atf_check egrep -q "port: *[0-9]+" port-create.txt 158 atf_check -o save:portlist.txt ctladm portlist -qvf iscsi 159 atf_check egrep -q "cfiscsi_target_alias=$ALIAS" portlist.txt 160} 161create_iscsi_alias_cleanup() 162{ 163 cleanup iscsi 164} 165 166atf_test_case create_iscsi_without_required_args 167create_iscsi_without_required_args_head() 168{ 169 atf_set "descr" "ctladm will gracefully fail to create an iSCSI target if required arguments are missing" 170 atf_set "require.user" "root" 171} 172create_iscsi_without_required_args_body() 173{ 174 skip_if_ctld 175 load_cfiscsi 176 177 TARGET=iqn.2018-10.myhost.create_iscsi 178 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_target" ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG 179 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_portal_group_tag" ctladm port -c -d "iscsi" -O cfiscsi_target=$TARGET 180} 181 182atf_test_case create_ioctl_options cleanup 183create_ioctl_options_head() 184{ 185 atf_set "descr" "ctladm can set options when creating a new ioctl port" 186 atf_set "require.user" "root" 187} 188create_ioctl_options_body() 189{ 190 skip_if_ctld 191 192 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" -O pp=101 -O vp=102 193 atf_check egrep -q "Port created successfully" port-create.txt 194 atf_check egrep -q "frontend: *ioctl" port-create.txt 195 atf_check egrep -q "port: *[0-9]+" port-create.txt 196 portnum=`awk '/port:/ {print $2}' port-create.txt` 197 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 198 if ! egrep -q '101[[:space:]]+102' portlist.txt; then 199 ctladm portlist 200 atf_fail "Did not create the port with the specified options" 201 fi 202} 203create_ioctl_options_cleanup() 204{ 205 cleanup ioctl 206} 207 208 209atf_test_case disable_ioctl cleanup 210disable_ioctl_head() 211{ 212 atf_set "descr" "ctladm can disable an ioctl port" 213 atf_set "require.user" "root" 214} 215disable_ioctl_body() 216{ 217 skip_if_ctld 218 219 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 220 portnum=`awk '/port:/ {print $2}' port-create.txt` 221 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 222 atf_check -o ignore ctladm port -o off -p $portnum 223 atf_check -o match:"^$portnum *NO" ctladm portlist -qf ioctl 224} 225disable_ioctl_cleanup() 226{ 227 cleanup ioctl 228} 229 230atf_test_case enable_ioctl cleanup 231enable_ioctl_head() 232{ 233 atf_set "descr" "ctladm can enable an ioctl port" 234 atf_set "require.user" "root" 235} 236enable_ioctl_body() 237{ 238 skip_if_ctld 239 240 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" 241 portnum=`awk '/port:/ {print $2}' port-create.txt` 242 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 243 atf_check -o ignore ctladm port -o off -p $portnum 244 atf_check -o ignore ctladm port -o on -p $portnum 245 atf_check -o match:"^$portnum *YES" ctladm portlist -qf ioctl 246} 247enable_ioctl_cleanup() 248{ 249 cleanup ioctl 250} 251 252atf_test_case remove_ioctl 253remove_ioctl_head() 254{ 255 atf_set "descr" "ctladm can remove an ioctl port" 256 atf_set "require.user" "root" 257} 258remove_ioctl_body() 259{ 260 skip_if_ctld 261 262 # Specify exact pp and vp to make the post-removal portlist check 263 # unambiguous 264 atf_check -o save:port-create.txt ctladm port -c -d "ioctl" -O pp=10001 -O vp=10002 265 portnum=`awk '/port:/ {print $2}' port-create.txt` 266 atf_check -o save:portlist.txt ctladm portlist -qf ioctl 267 atf_check -o inline:"Port destroyed successfully\n" ctladm port -r -d ioctl -p $portnum 268 # Check that the port was removed. A new port may have been added with 269 # the same ID, so match against the pp and vp numbers, too. 270 if ctladm portlist -qf ioctl | egrep -q "^${portnum} .*10001 *10002"; then 271 ctladm portlist -qf ioctl 272 atf_fail "port was not removed" 273 fi 274} 275 276atf_test_case remove_iscsi 277remove_iscsi_head() 278{ 279 atf_set "descr" "ctladm can remove an iscsi port" 280 atf_set "require.user" "root" 281} 282remove_iscsi_body() 283{ 284 skip_if_ctld 285 load_cfiscsi 286 287 TARGET=iqn.2018-10.myhost.remove_iscsi 288 atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 289 portnum=`awk '/port:/ {print $2}' port-create.txt` 290 atf_check -o save:portlist.txt ctladm portlist -qf iscsi 291 atf_check -o inline:"Port destroyed successfully\n" ctladm port -r -d iscsi -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 292 # Check that the port was removed. A new port may have been added with 293 # the same ID, so match against the target and tag, too. 294 PGTAGHEX=0x7631 # PGTAG in hex 295 if ctladm portlist -qf iscsi | egrep -q "^${portnum} .*$PGTAG +[0-9]+ +$TARGET,t,$PGTAGHEX"; then 296 ctladm portlist -qf iscsi 297 atf_fail "port was not removed" 298 fi 299} 300 301atf_test_case remove_iscsi_without_required_args cleanup 302remove_iscsi_without_required_args_head() 303{ 304 atf_set "descr" "ctladm will gracefully fail to remove an iSCSI target if required arguments are missing" 305 atf_set "require.user" "root" 306} 307remove_iscsi_without_required_args_body() 308{ 309 skip_if_ctld 310 load_cfiscsi 311 312 TARGET=iqn.2018-10.myhost.remove_iscsi_without_required_args 313 atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" 314 echo "target: $TARGET" >> port-create.txt 315 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_portal_group_tag" ctladm port -r -d iscsi -O cfiscsi_target="$TARGET" 316 atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_target" ctladm port -r -d iscsi -O cfiscsi_portal_group_tag=$PGTAG 317} 318remove_iscsi_without_required_args_cleanup() 319{ 320 cleanup iscsi 321} 322 323atf_init_test_cases() 324{ 325 atf_add_test_case create_ioctl 326 atf_add_test_case create_iscsi 327 atf_add_test_case create_iscsi_without_required_args 328 atf_add_test_case create_iscsi_alias 329 atf_add_test_case create_ioctl_options 330 atf_add_test_case disable_ioctl 331 atf_add_test_case enable_ioctl 332 atf_add_test_case remove_ioctl 333 atf_add_test_case remove_ioctl_without_required_args 334 atf_add_test_case remove_iscsi 335 atf_add_test_case remove_iscsi_without_required_args 336} 337