Commit b4118383 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Tomasz Zawadzki
Browse files

test/sma: add tests for nvmf-tcp



The test uses `scripts/sma-client.py` to send a series of gRPC methods
that are serviced by the SMA and then uses the regular SPDK RPC
interface to verify its effects on the application.

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I2b61c61cb475ec906bb6a594cda3082c0bd8ab44
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11728


Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
parent 4ee3d468
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -89,3 +89,6 @@ busy
balanced
core_load
zoned_fio

# SMA tests - disabled in CI for now
sma_nvmf_tcp

test/sma/common.sh

0 → 100644
+12 −0
Original line number Diff line number Diff line
function sma_waitforlisten() {
	local sma_addr=${1:-127.0.0.1}
	local sma_port=${2:-8080}

	for ((i = 0; i < 5; i++)); do
		if nc -z $sma_addr $sma_port; then
			return 0
		fi
		sleep 1s
	done
	return 1
}

test/sma/nvmf_tcp.sh

0 → 100755
+159 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash

testdir=$(readlink -f "$(dirname "$0")")
rootdir=$(readlink -f "$testdir/../..")

source "$rootdir/test/common/autotest_common.sh"
source "$testdir/common.sh"

function cleanup() {
	killprocess $tgtpid
	killprocess $smapid
}

function uuid2base64() {
	python <<- EOF
		import base64, uuid
		print(base64.b64encode(uuid.UUID("$1").bytes).decode())
	EOF
}

function create_device() {
	"$rootdir/scripts/sma-client.py" <<- EOF
		{
			"method": "CreateDevice",
			"params": {
				"nvmf_tcp": {
					"subnqn": "$1",
					"adrfam": "ipv4",
					"traddr": "127.0.0.1",
					"trsvcid": "4420"
				}
			}
		}
	EOF
}

function delete_device() {
	"$rootdir/scripts/sma-client.py" <<- EOF
		{
			"method": "DeleteDevice",
			"params": {
				"handle": "$1"
			}
		}
	EOF
}

function attach_volume() {
	"$rootdir/scripts/sma-client.py" <<- EOF
		{
			"method": "AttachVolume",
			"params": {
				"device_handle": "$1",
				"volume": {
					"volume_id": "$(uuid2base64 $2)"
				}
			}
		}
	EOF
}

function detach_volume() {
	"$rootdir/scripts/sma-client.py" <<- EOF
		{
			"method": "DetachVolume",
			"params": {
				"device_handle": "$1",
				"volume_id": "$(uuid2base64 $2)"
			}
		}
	EOF
}

trap "cleanup; exit 1" SIGINT SIGTERM EXIT

$rootdir/build/bin/spdk_tgt &
tgtpid=$!
waitforlisten $tgtpid

# Prepare the target
rpc_cmd bdev_null_create null0 100 4096

$rootdir/scripts/sma.py -c <(
	cat <<- EOF
		address: 127.0.0.1
		port: 8080
		devices:
		  - name: 'nvmf_tcp'
	EOF
) &
smapid=$!

# Wait until the SMA starts listening
sma_waitforlisten

# Make sure a TCP transport has been created
rpc_cmd nvmf_get_transports --trtype tcp

# Create a couple of devices and verify them via RPC
devid0=$(create_device nqn.2016-06.io.spdk:cnode0 | jq -r '.handle')
rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0

devid1=$(create_device nqn.2016-06.io.spdk:cnode1 | jq -r '.handle')
rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0
rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode1
[[ "$devid0" != "$devid1" ]]

# Check that there are three subsystems (2 created above + discovery)
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 3 ]]

# Verify the method is idempotent and sending the same gRPCs won't create new
# devices and will return the same handles
tmp0=$(create_device nqn.2016-06.io.spdk:cnode0 | jq -r '.handle')
tmp1=$(create_device nqn.2016-06.io.spdk:cnode1 | jq -r '.handle')

[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 3 ]]
[[ "$tmp0" == "$devid0" ]]
[[ "$tmp1" == "$devid1" ]]

# Now delete both of them verifying via RPC
delete_device "$devid0"
NOT rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 2 ]]

delete_device "$devid1"
NOT rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode1
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 1 ]]

# Finally check that removing a non-existing device is also sucessful
delete_device "$devid0"
delete_device "$devid1"

# Check volume attach/detach
devid0=$(create_device nqn.2016-06.io.spdk:cnode0 | jq -r '.handle')
devid1=$(create_device nqn.2016-06.io.spdk:cnode1 | jq -r '.handle')
uuid=$(rpc_cmd bdev_get_bdevs -b null0 | jq -r '.[].uuid')

# Attach the volume to a first device
attach_volume "$devid0" "$uuid"
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0 | jq -r '.[0].namespaces | length') -eq 1 ]]
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode1 | jq -r '.[0].namespaces | length') -eq 0 ]]
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0 | jq -r '.[0].namespaces[0].uuid') == "$uuid" ]]

# Attach the same device again and see that it won't fail
attach_volume "$devid0" "$uuid"
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0 | jq -r '.[0].namespaces | length') -eq 1 ]]
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode1 | jq -r '.[0].namespaces | length') -eq 0 ]]
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0 | jq -r '.[0].namespaces[0].uuid') == "$uuid" ]]

# Detach it and verify it's removed from the subsystem
detach_volume "$devid0" "$uuid"
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode0 | jq -r '.[0].namespaces | length') -eq 0 ]]
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:cnode1 | jq -r '.[0].namespaces | length') -eq 0 ]]

# Detach it again and verify it suceeds
detach_volume "$devid0" "$uuid"

cleanup
trap - SIGINT SIGTERM EXIT

test/sma/sma.sh

0 → 100755
+8 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash

testdir=$(readlink -f "$(dirname "$0")")
rootdir=$(readlink -f "$testdir/../..")

source "$rootdir/test/common/autotest_common.sh"

run_test "sma_nvmf_tcp" $testdir/nvmf_tcp.sh