git: 1dc90424b26f - stable/13 - ctladm: print port number with a succesful "port -c" command

From: Alan Somers <asomers_at_FreeBSD.org>
Date: Fri, 28 Jun 2024 19:36:12 UTC
The branch stable/13 has been updated by asomers:

URL: https://cgit.FreeBSD.org/src/commit/?id=1dc90424b26f80e4a9475a722f46e754fe7aba76

commit 1dc90424b26f80e4a9475a722f46e754fe7aba76
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-06-05 23:54:46 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2024-06-28 19:25:54 +0000

    ctladm: print port number with a succesful "port -c" command
    
    Make "ctladm port -c" print the port number of the newly successful
    port.  This way it won't have to be guessed by a subsequent "ctladm
    portlist" command.  That means it's safe to use it concurrently with
    other ctladm processes.  In particular, this allows the tests to be run
    in parallel.
    
    Sponsored by:   Axcient
    Reviewed by:    mav
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1279
    
    (cherry picked from commit 591de7534fb3acb2e6eef94a1e5e92000d2cf83d)
---
 usr.sbin/ctladm/ctladm.c       | 18 +++++++++++
 usr.sbin/ctladm/tests/Makefile |  4 ---
 usr.sbin/ctladm/tests/port.sh  | 70 ++++++++++++++++++++----------------------
 3 files changed, 52 insertions(+), 40 deletions(-)

diff --git a/usr.sbin/ctladm/ctladm.c b/usr.sbin/ctladm/ctladm.c
index 1cf42aa5933b..6af25ed28925 100644
--- a/usr.sbin/ctladm/ctladm.c
+++ b/usr.sbin/ctladm/ctladm.c
@@ -392,7 +392,9 @@ static struct ctladm_opts cctl_fe_table[] = {
 static int
 cctl_port(int fd, int argc, char **argv, char *combinedopt)
 {
+	char result_buf[1024];
 	int c;
+	uint64_t created_port = -1;
 	int32_t targ_port = -1;
 	int retval = 0;
 	int wwnn_set = 0, wwpn_set = 0;
@@ -582,6 +584,8 @@ cctl_port(int fd, int argc, char **argv, char *combinedopt)
 	case CCTL_PORT_MODE_CREATE: {
 		bzero(&req, sizeof(req));
 		strlcpy(req.driver, driver, sizeof(req.driver));
+		req.result = result_buf;
+		req.result_len = sizeof(result_buf);
 
 		if (port_mode == CCTL_PORT_MODE_REMOVE) {
 			req.reqtype = CTL_REQ_REMOVE;
@@ -614,6 +618,20 @@ cctl_port(int fd, int argc, char **argv, char *combinedopt)
 			warnx("warning: %s", req.error_str);
 			break;
 		case CTL_LUN_OK:
+			if (port_mode == CCTL_PORT_MODE_CREATE) {
+				req.result_nvl = nvlist_unpack(result_buf, req.result_len, 0);
+				if (req.result_nvl == NULL) {
+					warnx("error unpacking result nvlist");
+					break;
+				}
+				created_port = nvlist_get_number(req.result_nvl, "port_id");
+				printf("Port created successfully\n"
+				    "frontend: %s\n"
+				    "port:     %ju\n", driver,
+				    (uintmax_t) created_port);
+				nvlist_destroy(req.result_nvl);
+			} else
+				printf("Port destroyed successfully\n");
 			break;
 		default:
 			warnx("unknown status: %d", req.status);
diff --git a/usr.sbin/ctladm/tests/Makefile b/usr.sbin/ctladm/tests/Makefile
index 73ac94d77d21..825e38e6c6e3 100644
--- a/usr.sbin/ctladm/tests/Makefile
+++ b/usr.sbin/ctladm/tests/Makefile
@@ -3,8 +3,4 @@ PACKAGE=	tests
 
 ATF_TESTS_SH=	port
 
-# "ctladm port" does not report the name of the port just created, so we can't
-# cleanup unless we assume that no other test created a port too.
-TEST_METADATA+= is_exclusive="true"
-
 .include <bsd.test.mk>
diff --git a/usr.sbin/ctladm/tests/port.sh b/usr.sbin/ctladm/tests/port.sh
index 110b89bd965b..782a8ee5b6c1 100644
--- a/usr.sbin/ctladm/tests/port.sh
+++ b/usr.sbin/ctladm/tests/port.sh
@@ -45,8 +45,9 @@ skip_if_ctld() {
 cleanup() {
 	driver=$1
 
-	if [ -e after-ports ]; then
-		diff before-ports after-ports | awk "/$driver/ {print \$2}" | xargs -n1 ctladm port -r -d ioctl -p
+	if [ -e port-create.txt ]; then
+		portnum=`awk '/port:/ {print $2}' port-create.txt`
+		ctladm port -r -d $driver -p $portnum
 	fi
 }
 
@@ -60,12 +61,13 @@ create_ioctl_body()
 {
 	skip_if_ctld
 
-	atf_check -o save:before-ports ctladm portlist -qf ioctl
-	atf_check ctladm port -c -d "ioctl"
-	atf_check -o save:after-ports ctladm portlist -qf ioctl
-	if test `wc -l before-ports | cut -w -f2` -ge `wc -l after-ports | cut -w -f2`; then
-		atf_fail "Did not create a new ioctl port"
-	fi
+	atf_check -o save:port-create.txt ctladm port -c -d "ioctl"
+	atf_check egrep -q "Port created successfully" port-create.txt
+	atf_check egrep -q "frontend: *ioctl" port-create.txt
+	atf_check egrep -q "port: *[0-9]+" port-create.txt
+	portnum=`awk '/port:/ {print $2}' port-create.txt`
+	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
+	atf_check egrep -q "$portnum *YES *ioctl *ioctl" portlist.txt
 }
 create_ioctl_cleanup()
 {
@@ -82,13 +84,13 @@ create_ioctl_options_body()
 {
 	skip_if_ctld
 
-	atf_check -o save:before-ports ctladm portlist -qf ioctl
-	atf_check ctladm port -c -d "ioctl" -O pp=101 -O vp=102
-	atf_check -o save:after-ports ctladm portlist -qf ioctl
-	if test `wc -l before-ports | cut -w -f2` -ge `wc -l after-ports | cut -w -f2`; then
-		atf_fail "Did not create a new ioctl port"
-	fi
-	if ! egrep -q '101[[:space:]]+102' after-ports; then
+	atf_check -o save:port-create.txt ctladm port -c -d "ioctl" -O pp=101 -O vp=102
+	atf_check egrep -q "Port created successfully" port-create.txt
+	atf_check egrep -q "frontend: *ioctl" port-create.txt
+	atf_check egrep -q "port: *[0-9]+" port-create.txt
+	portnum=`awk '/port:/ {print $2}' port-create.txt`
+	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
+	if ! egrep -q '101[[:space:]]+102' portlist.txt; then
 		ctladm portlist
 		atf_fail "Did not create the port with the specified options"
 	fi
@@ -109,13 +111,9 @@ disable_ioctl_body()
 {
 	skip_if_ctld
 
-	atf_check -o save:before-ports ctladm portlist -qf ioctl
-	atf_check ctladm port -c -d "ioctl"
-	atf_check -o save:after-ports ctladm portlist -qf ioctl
-	if test `wc -l before-ports | cut -w -f2` -ge `wc -l after-ports | cut -w -f2`; then
-		atf_fail "Did not create a new ioctl port"
-	fi
-	portnum=`diff before-ports after-ports | awk '/ioctl/ {print $2}'`;
+	atf_check -o save:port-create.txt ctladm port -c -d "ioctl"
+	portnum=`awk '/port:/ {print $2}' port-create.txt`
+	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
 	atf_check -o ignore ctladm port -o off -p $portnum
 	atf_check -o match:"^$portnum *NO" ctladm portlist -qf ioctl
 }
@@ -134,13 +132,9 @@ enable_ioctl_body()
 {
 	skip_if_ctld
 
-	atf_check -o save:before-ports ctladm portlist -qf ioctl
-	atf_check ctladm port -c -d "ioctl"
-	atf_check -o save:after-ports ctladm portlist -qf ioctl
-	if test `wc -l before-ports | cut -w -f2` -ge `wc -l after-ports | cut -w -f2`; then
-		atf_fail "Did not create a new ioctl port"
-	fi
-	portnum=`diff before-ports after-ports | awk '/ioctl/ {print $2}'`;
+	atf_check -o save:port-create.txt ctladm port -c -d "ioctl"
+	portnum=`awk '/port:/ {print $2}' port-create.txt`
+	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
 	atf_check -o ignore ctladm port -o off -p $portnum
 	atf_check -o ignore ctladm port -o on -p $portnum
 	atf_check -o match:"^$portnum *YES" ctladm portlist -qf ioctl
@@ -160,14 +154,18 @@ remove_ioctl_body()
 {
 	skip_if_ctld
 
-	atf_check -o save:before-ports ctladm portlist -qf ioctl
-	atf_check ctladm port -c -d "ioctl"
-	atf_check -o save:after-ports ctladm portlist -qf ioctl
-	if test `wc -l before-ports | cut -w -f2` -ge `wc -l after-ports | cut -w -f2`; then
-		atf_fail "Did not create a new ioctl port"
+	# Specify exact pp and vp to make the post-removal portlist check
+	# unambiguous
+	atf_check -o save:port-create.txt ctladm port -c -d "ioctl" -O pp=10001 -O vp=10002
+	portnum=`awk '/port:/ {print $2}' port-create.txt`
+	atf_check -o save:portlist.txt ctladm portlist -qf ioctl
+	atf_check -o inline:"Port destroyed successfully\n" ctladm port -r -d ioctl -p $portnum
+	# Check that the port was removed.  A new port may have been added with
+	# the same ID, so match against the pp and vp numbers, too.
+	if ctladm portlist -qf ioctl | egrep -q "^${portnum} .*10001 *10002"; then
+		ctladm portlist -qf ioctl
+		atf_fail "port was not removed"
 	fi
-	portnum=`diff before-ports after-ports | awk '/ioctl/ {print $2}'`;
-	atf_check ctladm port -r -d ioctl -p $portnum
 }
 
 atf_init_test_cases()