xref: /freebsd/usr.sbin/ctladm/tests/port.sh (revision 7f50027321db3b08477f6236abded0297e9e5ed8)
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.
39 PGTAG=30257
40 
41 load_cfiscsi() {
42 	if ! kldstat -q -m cfiscsi; then
43 		kldload cfiscsi || atf_skip "could not load cfscsi kernel mod"
44 	fi
45 }
46 
47 skip_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 
54 cleanup() {
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 
71 atf_test_case create_ioctl cleanup
72 create_ioctl_head()
73 {
74 	atf_set "descr" "ctladm can create a new ioctl port"
75 	atf_set "require.user" "root"
76 }
77 create_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 }
89 create_ioctl_cleanup()
90 {
91 	cleanup ioctl
92 }
93 
94 atf_test_case remove_ioctl_without_required_args cleanup
95 remove_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 }
100 remove_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 }
108 remove_ioctl_without_required_args_cleanup()
109 {
110 	cleanup ioctl
111 }
112 
113 atf_test_case create_iscsi cleanup
114 create_iscsi_head()
115 {
116 	atf_set "descr" "ctladm can create a new iscsi port"
117 	atf_set "require.user" "root"
118 }
119 create_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 }
135 create_iscsi_cleanup()
136 {
137 	cleanup iscsi
138 }
139 
140 atf_test_case create_iscsi_alias cleanup
141 create_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 }
146 create_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 }
161 create_iscsi_alias_cleanup()
162 {
163 	cleanup iscsi
164 }
165 
166 atf_test_case create_iscsi_without_required_args
167 create_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 }
172 create_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 
182 atf_test_case create_ioctl_options cleanup
183 create_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 }
188 create_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 }
203 create_ioctl_options_cleanup()
204 {
205 	cleanup ioctl
206 }
207 
208 
209 atf_test_case disable_ioctl cleanup
210 disable_ioctl_head()
211 {
212 	atf_set "descr" "ctladm can disable an ioctl port"
213 	atf_set "require.user" "root"
214 }
215 disable_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 }
225 disable_ioctl_cleanup()
226 {
227 	cleanup ioctl
228 }
229 
230 atf_test_case enable_ioctl cleanup
231 enable_ioctl_head()
232 {
233 	atf_set "descr" "ctladm can enable an ioctl port"
234 	atf_set "require.user" "root"
235 }
236 enable_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 }
247 enable_ioctl_cleanup()
248 {
249 	cleanup ioctl
250 }
251 
252 atf_test_case remove_ioctl
253 remove_ioctl_head()
254 {
255 	atf_set "descr" "ctladm can remove an ioctl port"
256 	atf_set "require.user" "root"
257 }
258 remove_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 
276 atf_test_case remove_iscsi
277 remove_iscsi_head()
278 {
279 	atf_set "descr" "ctladm can remove an iscsi port"
280 	atf_set "require.user" "root"
281 }
282 remove_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 
301 atf_test_case remove_iscsi_without_required_args cleanup
302 remove_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 }
307 remove_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 }
318 remove_iscsi_without_required_args_cleanup()
319 {
320 	cleanup iscsi
321 }
322 
323 atf_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