xref: /freebsd/usr.sbin/ctladm/tests/port.sh (revision 4b15965daa99044daf184221b7c283bf7f2d7e66)
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
41skip_if_ctld() {
42	if service ctld onestatus > /dev/null; then
43		# If ctld is running on this server, let's not interfere.
44		atf_skip "Cannot run this test while ctld is running"
45	fi
46}
47
48cleanup() {
49	driver=$1
50
51	if [ -e port-create.txt ]; then
52		case "$driver" in
53		"ioctl")
54			PORTNUM=`awk '/port:/ {print $2}' port-create.txt`
55			ctladm port -r -d $driver -p $PORTNUM
56			;;
57		"iscsi")
58			TARGET=`awk '/target:/ {print $2}' port-create.txt`
59			ctladm port -r -d $driver -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target=$TARGET
60			;;
61		esac
62	fi
63}
64
65atf_test_case create_ioctl cleanup
66create_ioctl_head()
67{
68	atf_set "descr" "ctladm can create a new ioctl port"
69	atf_set "require.user" "root"
70	atf_set "require.progs" ctladm
71}
72create_ioctl_body()
73{
74	skip_if_ctld
75
76	atf_check -o save:port-create.txt ctladm port -c -d "ioctl"
77	atf_check egrep -q "Port created successfully" port-create.txt
78	atf_check egrep -q "frontend: *ioctl" port-create.txt
79	atf_check egrep -q "port: *[0-9]+" port-create.txt
80	portnum=`awk '/port:/ {print $2}' port-create.txt`
81	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
82	atf_check egrep -q "$portnum *YES *ioctl *ioctl" portlist.txt
83}
84create_ioctl_cleanup()
85{
86	cleanup ioctl
87}
88
89atf_test_case remove_ioctl_without_required_args cleanup
90remove_ioctl_without_required_args_head()
91{
92	atf_set "descr" "ctladm will gracefully fail to remove an ioctl target if required arguments are missing"
93	atf_set "require.user" "root"
94	atf_set "require.progs" ctladm
95}
96remove_ioctl_without_required_args_body()
97{
98	skip_if_ctld
99
100	atf_check -o save:port-create.txt ctladm port -c -d "ioctl"
101	atf_check egrep -q "Port created successfully" port-create.txt
102	atf_check -s exit:1 -e match:"Missing required argument: port_id" ctladm port -r -d "ioctl"
103}
104remove_ioctl_without_required_args_cleanup()
105{
106	cleanup ioctl
107}
108
109atf_test_case create_iscsi cleanup
110create_iscsi_head()
111{
112	atf_set "descr" "ctladm can create a new iscsi port"
113	atf_set "require.user" "root"
114	atf_set "require.progs" ctladm
115	atf_set "require.kmods" "cfiscsi"
116}
117create_iscsi_body()
118{
119	skip_if_ctld
120
121	TARGET=iqn.2018-10.myhost.create_iscsi
122	atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET"
123	echo "target: $TARGET" >> port-create.txt
124	atf_check egrep -q "Port created successfully" port-create.txt
125	atf_check egrep -q "frontend: *iscsi" port-create.txt
126	atf_check egrep -q "port: *[0-9]+" port-create.txt
127	atf_check -o save:portlist.txt ctladm portlist -qf iscsi
128	# Unlike the ioctl driver, the iscsi driver creates ports in a disabled
129	# state, so the port's lunmap may be set before enabling it.
130	atf_check egrep -q "$portnum *NO *iscsi *iscsi.*$TARGET" portlist.txt
131}
132create_iscsi_cleanup()
133{
134	cleanup iscsi
135}
136
137atf_test_case create_iscsi_alias cleanup
138create_iscsi_alias_head()
139{
140	atf_set "descr" "ctladm can create a new iscsi port with a target alias"
141	atf_set "require.user" "root"
142	atf_set "require.progs" ctladm
143	atf_set "require.kmods" "cfiscsi"
144}
145create_iscsi_alias_body()
146{
147	skip_if_ctld
148
149	TARGET=iqn.2018-10.myhost.create_iscsi_alias
150	ALIAS="foobar"
151	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"
152	echo "target: $TARGET" >> port-create.txt
153	atf_check egrep -q "Port created successfully" port-create.txt
154	atf_check egrep -q "frontend: *iscsi" port-create.txt
155	atf_check egrep -q "port: *[0-9]+" port-create.txt
156	atf_check -o save:portlist.txt ctladm portlist -qvf iscsi
157	atf_check egrep -q "cfiscsi_target_alias=$ALIAS" portlist.txt
158}
159create_iscsi_alias_cleanup()
160{
161	cleanup iscsi
162}
163
164atf_test_case create_iscsi_without_required_args
165create_iscsi_without_required_args_head()
166{
167	atf_set "descr" "ctladm will gracefully fail to create an iSCSI target if required arguments are missing"
168	atf_set "require.user" "root"
169	atf_set "require.progs" ctladm
170	atf_set "require.kmods" "cfiscsi"
171}
172create_iscsi_without_required_args_body()
173{
174	skip_if_ctld
175
176	TARGET=iqn.2018-10.myhost.create_iscsi
177	atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_target" ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG
178	atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_portal_group_tag" ctladm port -c -d "iscsi" -O cfiscsi_target=$TARGET
179}
180
181atf_test_case create_ioctl_options cleanup
182create_ioctl_options_head()
183{
184	atf_set "descr" "ctladm can set options when creating a new ioctl port"
185	atf_set "require.user" "root"
186	atf_set "require.progs" ctladm
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	atf_set "require.progs" ctladm
215}
216disable_ioctl_body()
217{
218	skip_if_ctld
219
220	atf_check -o save:port-create.txt ctladm port -c -d "ioctl"
221	portnum=`awk '/port:/ {print $2}' port-create.txt`
222	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
223	atf_check -o ignore ctladm port -o off -p $portnum
224	atf_check -o match:"^$portnum *NO" ctladm portlist -qf ioctl
225}
226disable_ioctl_cleanup()
227{
228	cleanup ioctl
229}
230
231atf_test_case enable_ioctl cleanup
232enable_ioctl_head()
233{
234	atf_set "descr" "ctladm can enable an ioctl port"
235	atf_set "require.user" "root"
236	atf_set "require.progs" ctladm
237}
238enable_ioctl_body()
239{
240	skip_if_ctld
241
242	atf_check -o save:port-create.txt ctladm port -c -d "ioctl"
243	portnum=`awk '/port:/ {print $2}' port-create.txt`
244	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
245	atf_check -o ignore ctladm port -o off -p $portnum
246	atf_check -o ignore ctladm port -o on -p $portnum
247	atf_check -o match:"^$portnum *YES" ctladm portlist -qf ioctl
248}
249enable_ioctl_cleanup()
250{
251	cleanup ioctl
252}
253
254atf_test_case remove_ioctl
255remove_ioctl_head()
256{
257	atf_set "descr" "ctladm can remove an ioctl port"
258	atf_set "require.user" "root"
259	atf_set "require.progs" ctladm
260}
261remove_ioctl_body()
262{
263	skip_if_ctld
264
265	# Specify exact pp and vp to make the post-removal portlist check
266	# unambiguous
267	atf_check -o save:port-create.txt ctladm port -c -d "ioctl" -O pp=10001 -O vp=10002
268	portnum=`awk '/port:/ {print $2}' port-create.txt`
269	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
270	atf_check -o inline:"Port destroyed successfully\n" ctladm port -r -d ioctl -p $portnum
271	# Check that the port was removed.  A new port may have been added with
272	# the same ID, so match against the pp and vp numbers, too.
273	if ctladm portlist -qf ioctl | egrep -q "^${portnum} .*10001 *10002"; then
274		ctladm portlist -qf ioctl
275		atf_fail "port was not removed"
276	fi
277}
278
279atf_test_case remove_iscsi
280remove_iscsi_head()
281{
282	atf_set "descr" "ctladm can remove an iscsi port"
283	atf_set "require.user" "root"
284	atf_set "require.progs" ctladm
285	atf_set "require.kmods" "cfiscsi"
286}
287remove_iscsi_body()
288{
289	skip_if_ctld
290
291	TARGET=iqn.2018-10.myhost.remove_iscsi
292	atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET"
293	portnum=`awk '/port:/ {print $2}' port-create.txt`
294	atf_check -o save:portlist.txt ctladm portlist -qf iscsi
295	atf_check -o inline:"Port destroyed successfully\n" ctladm port -r -d iscsi -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET"
296	# Check that the port was removed.  A new port may have been added with
297	# the same ID, so match against the target and tag, too.
298	PGTAGHEX=0x7631	# PGTAG in hex
299	if ctladm portlist -qf iscsi | egrep -q "^${portnum} .*$PGTAG +[0-9]+ +$TARGET,t,$PGTAGHEX"; then
300		ctladm portlist -qf iscsi
301		atf_fail "port was not removed"
302	fi
303}
304
305atf_test_case remove_iscsi_without_required_args cleanup
306remove_iscsi_without_required_args_head()
307{
308	atf_set "descr" "ctladm will gracefully fail to remove an iSCSI target if required arguments are missing"
309	atf_set "require.user" "root"
310	atf_set "require.progs" ctladm
311	atf_set "require.kmods" "cfiscsi"
312}
313remove_iscsi_without_required_args_body()
314{
315	skip_if_ctld
316
317	TARGET=iqn.2018-10.myhost.remove_iscsi_without_required_args
318	atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET"
319	echo "target: $TARGET" >> port-create.txt
320	atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_portal_group_tag" ctladm port -r -d iscsi -O cfiscsi_target="$TARGET"
321	atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_target" ctladm port -r -d iscsi -O cfiscsi_portal_group_tag=$PGTAG
322}
323remove_iscsi_without_required_args_cleanup()
324{
325	cleanup iscsi
326}
327
328atf_init_test_cases()
329{
330	atf_add_test_case create_ioctl
331	atf_add_test_case create_iscsi
332	atf_add_test_case create_iscsi_without_required_args
333	atf_add_test_case create_iscsi_alias
334	atf_add_test_case create_ioctl_options
335	atf_add_test_case disable_ioctl
336	atf_add_test_case enable_ioctl
337	atf_add_test_case remove_ioctl
338	atf_add_test_case remove_ioctl_without_required_args
339	atf_add_test_case remove_iscsi
340	atf_add_test_case remove_iscsi_without_required_args
341}
342