385 lines
11 KiB
Bash
385 lines
11 KiB
Bash
|
#!/usr/bin/env bash
|
||
|
|
||
|
set -e
|
||
|
|
||
|
rootdir=$(readlink -f $(dirname $0)/../..)
|
||
|
SPDK_AUTOTEST_X=false
|
||
|
source "$rootdir/test/common/autotest_common.sh"
|
||
|
source "$rootdir/test/nvmf/common.sh"
|
||
|
|
||
|
set -x
|
||
|
|
||
|
if [[ $SPDK_TEST_ISCSI -eq 1 ]]; then
|
||
|
source "$rootdir/test/iscsi_tgt/common.sh"
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_VHOST -ne 1 && $SPDK_TEST_VHOST_INIT -eq 1 ]]; then
|
||
|
SPDK_TEST_VHOST=1
|
||
|
echo "WARNING: Virtio initiator JSON_config test requires vhost target."
|
||
|
echo " Setting SPDK_TEST_VHOST=1 for duration of current script."
|
||
|
fi
|
||
|
|
||
|
set -x
|
||
|
|
||
|
if (( SPDK_TEST_BLOCKDEV + \
|
||
|
SPDK_TEST_ISCSI +
|
||
|
SPDK_TEST_NVMF +
|
||
|
SPDK_TEST_VHOST +
|
||
|
SPDK_TEST_VHOST_INIT +
|
||
|
SPDK_TEST_PMDK +
|
||
|
SPDK_TEST_RBD == 0 )); then
|
||
|
echo "WARNING: No tests are enabled so not running JSON configuration tests"
|
||
|
exit 0
|
||
|
fi
|
||
|
|
||
|
declare -A app_pid=([target]= [initiator]=)
|
||
|
declare -A app_socket=([target]='/var/tmp/spdk_tgt.sock' [initiator]='/var/tmp/spdk_initiator.sock')
|
||
|
declare -A app_params=([target]='-m 0x1 -s 1024' [initiator]='-m 0x2 -g -u -s 1024')
|
||
|
declare -A configs_path=([target]="$rootdir/spdk_tgt_config.json" [initiator]="$rootdir/spdk_initiator_config.json")
|
||
|
|
||
|
function tgt_rpc() {
|
||
|
$rootdir/scripts/rpc.py -s "${app_socket[target]}" "$@"
|
||
|
}
|
||
|
|
||
|
function initiator_rpc() {
|
||
|
$rootdir/scripts/rpc.py -s "${app_socket[initiator]}" "$@"
|
||
|
}
|
||
|
|
||
|
# $1 - target / initiator
|
||
|
# $2..$n app parameters
|
||
|
function json_config_test_start_app() {
|
||
|
local app=$1
|
||
|
shift
|
||
|
|
||
|
[[ ! -z "${#app_socket[$app]}" ]] # Check app type
|
||
|
[[ -z "${app_pid[$app]}" ]] # Assert if app is not running
|
||
|
set -x
|
||
|
|
||
|
local app_extra_params=""
|
||
|
if [[ $SPDK_TEST_VHOST -eq 1 || $SPDK_TEST_VHOST_INIT -eq 1 ]]; then
|
||
|
# If PWD is nfs/sshfs we can't create UNIX sockets there. Always use safe location instead.
|
||
|
app_extra_params='-S /var/tmp'
|
||
|
fi
|
||
|
|
||
|
$rootdir/app/spdk_tgt/spdk_tgt ${app_params[$app]} ${app_extra_params} -r ${app_socket[$app]} "$@" &
|
||
|
app_pid[$app]=$!
|
||
|
|
||
|
echo "Waiting for $app to run..."
|
||
|
waitforlisten ${app_pid[$app]} ${app_socket[$app]}
|
||
|
echo ""
|
||
|
}
|
||
|
|
||
|
# $1 - target / initiator
|
||
|
function json_config_test_shutdown_app() {
|
||
|
local app=$1
|
||
|
|
||
|
# Check app type && assert app was started
|
||
|
[[ ! -z "${#app_socket[$app]}" ]]
|
||
|
[[ ! -z "${app_pid[$app]}" ]]
|
||
|
|
||
|
# kill_instance RPC will trigger ASAN
|
||
|
kill -SIGINT ${app_pid[$app]}
|
||
|
|
||
|
for (( i=0; i<10; i++ )); do
|
||
|
if ! kill -0 ${app_pid[$app]} 2>/dev/null; then
|
||
|
app_pid[$app]=
|
||
|
break
|
||
|
fi
|
||
|
sleep 0.5
|
||
|
done
|
||
|
|
||
|
if [[ ! -z "${app_pid[$app]}" ]]; then
|
||
|
echo "SPDK $app shutdown timeout"
|
||
|
return 1
|
||
|
fi
|
||
|
|
||
|
echo "SPDK $app shutdown done"
|
||
|
}
|
||
|
|
||
|
function create_bdev_subsystem_config() {
|
||
|
timing_enter $FUNCNAME
|
||
|
|
||
|
if [[ $SPDK_TEST_BLOCKDEV -eq 1 ]]; then
|
||
|
local lvol_store_base_bdev=Nvme0n1
|
||
|
if ! tgt_rpc get_bdevs --name ${lvol_store_base_bdev} >/dev/null; then
|
||
|
if [[ $(uname -s) = Linux ]]; then
|
||
|
lvol_store_base_bdev=aio_disk
|
||
|
echo "WARNING: No NVMe drive found. Using '$lvol_store_base_bdev' instead."
|
||
|
else
|
||
|
echo "ERROR: No NVMe drive found and bdev_aio is not supported on $(uname -s)."
|
||
|
timing_exit $FUNCNAME
|
||
|
return 1
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
tgt_rpc construct_split_vbdev $lvol_store_base_bdev 2
|
||
|
tgt_rpc construct_split_vbdev Malloc0 3
|
||
|
tgt_rpc construct_passthru_bdev -b Malloc3 -p PTBdevFromMalloc3
|
||
|
|
||
|
tgt_rpc construct_null_bdev Null0 32 512
|
||
|
|
||
|
tgt_rpc construct_malloc_bdev 32 512 --name Malloc0
|
||
|
tgt_rpc construct_malloc_bdev 16 4096 --name Malloc1
|
||
|
|
||
|
if [[ $(uname -s) = Linux ]]; then
|
||
|
# This AIO bdev must be large enough to be used as LVOL store
|
||
|
dd if=/dev/zero of=/tmp/sample_aio bs=1024 count=102400
|
||
|
tgt_rpc construct_aio_bdev /tmp/sample_aio aio_disk 1024
|
||
|
fi
|
||
|
|
||
|
# For LVOLs use split to check for proper order of initialization.
|
||
|
# If LVOLs cofniguration will be reordered (eg moved before splits or AIO/NVMe)
|
||
|
# it should fail loading JSON config from file.
|
||
|
tgt_rpc construct_lvol_store -c 1048576 ${lvol_store_base_bdev}p0 lvs_test
|
||
|
tgt_rpc construct_lvol_bdev -l lvs_test lvol0 32
|
||
|
tgt_rpc construct_lvol_bdev -l lvs_test -t lvol1 32
|
||
|
tgt_rpc snapshot_lvol_bdev lvs_test/lvol0 snapshot0
|
||
|
tgt_rpc clone_lvol_bdev lvs_test/snapshot0 clone0
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_CRYPTO -eq 1 ]]; then
|
||
|
tgt_rpc construct_malloc_bdev 8 1024 --name MallocForCryptoBdev
|
||
|
if [[ $(lspci -d:37c8 | wc -l) -eq 0 ]]; then
|
||
|
local crypto_dirver=crypto_aesni_mb
|
||
|
else
|
||
|
local crypto_dirver=crypto_qat
|
||
|
fi
|
||
|
|
||
|
tgt_rpc construct_crypto_bdev -b MallocForCryptoBdev -c CryptoMallocBdev -d $crypto_dirver -k 0123456789123456
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_PMDK -eq 1 ]]; then
|
||
|
pmem_pool_file=$(mktemp /tmp/pool_file1.XXXXX)
|
||
|
rm -f $pmem_pool_file
|
||
|
tgt_rpc create_pmem_pool $pmem_pool_file 128 4096
|
||
|
tgt_rpc construct_pmem_bdev -n pmem1 $pmem_pool_file
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_RBD -eq 1 ]]; then
|
||
|
rbd_setup 127.0.0.1
|
||
|
tgt_rpc construct_rbd_bdev $RBD_POOL $RBD_NAME 4096
|
||
|
fi
|
||
|
|
||
|
timing_exit $FUNCNAME
|
||
|
}
|
||
|
|
||
|
function cleanup_bdev_subsystem_config() {
|
||
|
timing_enter $FUNCNAME
|
||
|
|
||
|
if [[ $SPDK_TEST_BLOCKDEV -eq 1 ]]; then
|
||
|
tgt_rpc destroy_lvol_bdev lvs_test/clone0
|
||
|
tgt_rpc destroy_lvol_bdev lvs_test/lvol0
|
||
|
tgt_rpc destroy_lvol_bdev lvs_test/snapshot0
|
||
|
tgt_rpc destroy_lvol_store -l lvs_test
|
||
|
fi
|
||
|
|
||
|
if [[ $(uname -s) = Linux ]]; then
|
||
|
rm -f /tmp/sample_aio
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_PMDK -eq 1 && ! -z "$pmem_pool_file" && -f "$pmem_pool_file" ]]; then
|
||
|
tgt_rpc delete_pmem_bdev pmem1
|
||
|
tgt_rpc delete_pmem_pool $pmem_pool_file
|
||
|
rm -f $pmem_pool_file
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_RBD -eq 1 ]]; then
|
||
|
rbd_cleanup
|
||
|
fi
|
||
|
|
||
|
timing_exit $FUNCNAME
|
||
|
}
|
||
|
|
||
|
function create_vhost_subsystem_config() {
|
||
|
timing_enter $FUNCNAME
|
||
|
|
||
|
tgt_rpc construct_malloc_bdev 64 1024 --name MallocForVhost0
|
||
|
tgt_rpc construct_split_vbdev MallocForVhost0 8
|
||
|
|
||
|
tgt_rpc construct_vhost_scsi_controller VhostScsiCtrlr0
|
||
|
tgt_rpc add_vhost_scsi_lun VhostScsiCtrlr0 0 MallocForVhost0p3
|
||
|
tgt_rpc add_vhost_scsi_lun VhostScsiCtrlr0 1 MallocForVhost0p4
|
||
|
tgt_rpc set_vhost_controller_coalescing VhostScsiCtrlr0 1 100
|
||
|
|
||
|
tgt_rpc construct_vhost_blk_controller VhostBlkCtrlr0 MallocForVhost0p5
|
||
|
|
||
|
tgt_rpc construct_vhost_nvme_controller VhostNvmeCtrlr0 16
|
||
|
tgt_rpc add_vhost_nvme_ns VhostNvmeCtrlr0 MallocForVhost0p6
|
||
|
|
||
|
timing_exit $FUNCNAME
|
||
|
}
|
||
|
|
||
|
function create_iscsi_subsystem_config() {
|
||
|
timing_enter $FUNCNAME
|
||
|
tgt_rpc construct_malloc_bdev 64 1024 --name MallocForIscsi0
|
||
|
tgt_rpc add_portal_group $PORTAL_TAG 127.0.0.1:$ISCSI_PORT
|
||
|
tgt_rpc add_initiator_group $INITIATOR_TAG $INITIATOR_NAME $NETMASK
|
||
|
tgt_rpc construct_target_node Target3 Target3_alias 'MallocForIscsi0:0' $PORTAL_TAG:$INITIATOR_TAG 64 -d
|
||
|
timing_exit $FUNCNAME
|
||
|
}
|
||
|
|
||
|
function create_nvmf_subsystem_config() {
|
||
|
timing_enter $FUNCNAME
|
||
|
|
||
|
RDMA_IP_LIST=$(get_available_rdma_ips)
|
||
|
NVMF_FIRST_TARGET_IP=$(echo "$RDMA_IP_LIST" | head -n 1)
|
||
|
if [[ -z $NVMF_FIRST_TARGET_IP ]]; then
|
||
|
echo "Error: no NIC for nvmf test"
|
||
|
return 1
|
||
|
fi
|
||
|
|
||
|
tgt_rpc construct_malloc_bdev 8 512 --name MallocForNvmf0
|
||
|
tgt_rpc construct_malloc_bdev 4 1024 --name MallocForNvmf1
|
||
|
|
||
|
tgt_rpc nvmf_create_transport -t RDMA -u 8192 -p 4 -c 0
|
||
|
tgt_rpc nvmf_subsystem_create nqn.2016-06.io.spdk:cnode1 -a -s SPDK00000000000001
|
||
|
tgt_rpc nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 MallocForNvmf0
|
||
|
tgt_rpc nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 MallocForNvmf1
|
||
|
tgt_rpc nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t RDMA -a $NVMF_FIRST_TARGET_IP -s "$NVMF_PORT"
|
||
|
|
||
|
timing_exit $FUNCNAME
|
||
|
}
|
||
|
|
||
|
function create_virtio_initiator_config() {
|
||
|
timing_enter $FUNCNAME
|
||
|
initiator_rpc construct_virtio_dev -t user -a /var/tmp/VhostScsiCtrlr0 -d scsi VirtioScsiCtrlr0
|
||
|
initiator_rpc construct_virtio_dev -t user -a /var/tmp/VhostBlkCtrlr0 -d blk VirtioBlk0
|
||
|
# TODO: initiator_rpc construct_virtio_dev -t user -a /var/tmp/VhostNvmeCtrlr0 -d nvme VirtioNvme0
|
||
|
timing_exit $FUNCNAME
|
||
|
}
|
||
|
|
||
|
|
||
|
function json_config_test_init()
|
||
|
{
|
||
|
timing_enter $FUNCNAME
|
||
|
timing_enter json_config_setup_target
|
||
|
|
||
|
json_config_test_start_app target --wait-for-rpc
|
||
|
|
||
|
#TODO: global subsystem params
|
||
|
|
||
|
# Load nvme configuration. The load_config will issue start_subsystem_init automatically
|
||
|
(
|
||
|
echo '{"subsystems": [';
|
||
|
$rootdir/scripts/gen_nvme.sh --json
|
||
|
echo ']}'
|
||
|
) | tgt_rpc load_config
|
||
|
|
||
|
if [[ $SPDK_TEST_BLOCKDEV -eq 1 ]]; then
|
||
|
create_bdev_subsystem_config
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_VHOST -eq 1 ]]; then
|
||
|
create_vhost_subsystem_config
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_ISCSI -eq 1 ]]; then
|
||
|
create_iscsi_subsystem_config
|
||
|
fi
|
||
|
|
||
|
if [[ $SPDK_TEST_NVMF -eq 1 ]]; then
|
||
|
create_nvmf_subsystem_config
|
||
|
fi
|
||
|
timing_exit json_config_setup_target
|
||
|
|
||
|
if [[ $SPDK_TEST_VHOST_INIT -eq 1 ]]; then
|
||
|
json_config_test_start_app initiator
|
||
|
create_virtio_initiator_config
|
||
|
fi
|
||
|
|
||
|
tgt_rpc construct_malloc_bdev 8 512 --name MallocBdevForConfigChangeCheck
|
||
|
|
||
|
timing_exit $FUNCNAME
|
||
|
}
|
||
|
|
||
|
function json_config_test_fini() {
|
||
|
timing_enter $FUNCNAME
|
||
|
local ret=0
|
||
|
|
||
|
if [[ ! -z "${app_pid[initiator]}" ]]; then
|
||
|
if ! json_config_test_shutdown_app initiator; then
|
||
|
kill -9 ${app_pid[initiator]}
|
||
|
app_pid[initiator]=
|
||
|
ret=1
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
if [[ ! -z "${app_pid[target]}" ]]; then
|
||
|
|
||
|
# Remove any artifacts we created (files, lvol etc)
|
||
|
cleanup_bdev_subsystem_config
|
||
|
|
||
|
# SPDK_TEST_NVMF: Should we clear something?
|
||
|
|
||
|
if ! json_config_test_shutdown_app target; then
|
||
|
kill -9 ${app_pid[target]}
|
||
|
app_pid[target]=
|
||
|
ret=1
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
rm -f "${configs_path[@]}"
|
||
|
timing_exit $FUNCNAME
|
||
|
return $ret
|
||
|
}
|
||
|
|
||
|
function json_config_clear() {
|
||
|
[[ ! -z "${#app_socket[$1]}" ]] # Check app type
|
||
|
$rootdir/test/json_config/clear_config.py -s ${app_socket[$1]} clear_config
|
||
|
|
||
|
#TODO check if config is cleared
|
||
|
}
|
||
|
|
||
|
on_error_exit() {
|
||
|
set -x
|
||
|
set +e
|
||
|
print_backtrace
|
||
|
trap - ERR
|
||
|
echo "Error on $1 - $2"
|
||
|
json_config_test_fini
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
trap 'on_error_exit "${FUNCNAME}" "${LINENO}"' ERR
|
||
|
echo "INFO: JSON configuration test init"
|
||
|
json_config_test_init
|
||
|
|
||
|
tgt_rpc save_config > ${configs_path[target]}
|
||
|
|
||
|
echo "INFO: shutting down applications..."
|
||
|
if [[ $SPDK_TEST_VHOST_INIT -eq 1 ]]; then
|
||
|
initiator_rpc save_config > ${configs_path[initiator]}
|
||
|
json_config_clear initiator
|
||
|
json_config_test_shutdown_app initiator
|
||
|
fi
|
||
|
|
||
|
json_config_clear target
|
||
|
json_config_test_shutdown_app target
|
||
|
|
||
|
echo "INFO: relaunching applications..."
|
||
|
json_config_test_start_app target --json ${configs_path[target]}
|
||
|
if [[ $SPDK_TEST_VHOST_INIT -eq 1 ]]; then
|
||
|
json_config_test_start_app initiator --json ${configs_path[initiator]}
|
||
|
fi
|
||
|
|
||
|
echo "INFO: Checking if target configuration is the same..."
|
||
|
$rootdir/test/json_config/json_diff.sh <(tgt_rpc save_config) "${configs_path[target]}"
|
||
|
if [[ $SPDK_TEST_VHOST_INIT -eq 1 ]]; then
|
||
|
echo "INFO: Checking if virtio initiator configuration is the same..."
|
||
|
$rootdir/test/json_config/json_diff.sh <(initiator_rpc save_config) "${configs_path[initiator]}"
|
||
|
fi
|
||
|
|
||
|
echo "INFO: changing configuration and checking if this can be detected..."
|
||
|
# Self test to check if configuration diff can be detected.
|
||
|
tgt_rpc delete_malloc_bdev MallocBdevForConfigChangeCheck
|
||
|
if $rootdir/test/json_config/json_diff.sh <(tgt_rpc save_config) "${configs_path[target]}" >/dev/null; then
|
||
|
echo "ERROR: intentional configuration difference not detected!"
|
||
|
false
|
||
|
else
|
||
|
echo "INFO: configuration change detected."
|
||
|
fi
|
||
|
|
||
|
json_config_test_fini
|
||
|
|
||
|
echo "INFO: Success"
|