diff --git a/test/common/skipped_tests.txt b/test/common/skipped_tests.txt index 99f8440b8..1f4fda97f 100644 --- a/test/common/skipped_tests.txt +++ b/test/common/skipped_tests.txt @@ -92,3 +92,4 @@ zoned_fio # SMA tests - disabled in CI for now sma_nvmf_tcp +sma_plugins diff --git a/test/sma/plugins.sh b/test/sma/plugins.sh new file mode 100755 index 000000000..6d93074f1 --- /dev/null +++ b/test/sma/plugins.sh @@ -0,0 +1,149 @@ +#!/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 create_device() { + "$rootdir/scripts/sma-client.py" <<- EOF + { + "method": "CreateDevice", + "params": { + "$1": {} + } + } + EOF +} + +trap 'killprocess $smapid; exit 1' SIGINT SIGTERM EXIT + +# First check a single plugin with both its devices enabled in the config +PYTHONPATH=$testdir/plugins $rootdir/scripts/sma.py -c <( + cat <<- EOF + plugins: + - 'plugin1' + devices: + - name: 'plugin1-device1' + - name: 'plugin1-device2' + EOF +) & +smapid=$! +# Wait for a while to make sure SMA starts listening +sma_waitforlisten + +[[ $(create_device nvme | jq -r '.handle') == 'nvme:plugin1-device1' ]] +[[ $(create_device nvmf_tcp | jq -r '.handle') == 'nvmf_tcp:plugin1-device2' ]] + +killprocess $smapid + +# Check that it's possible to enable only a single device from a plugin +PYTHONPATH=$testdir/plugins $rootdir/scripts/sma.py -c <( + cat <<- EOF + plugins: + - 'plugin1' + devices: + - name: 'plugin1-device2' + EOF +) & +smapid=$! +sma_waitforlisten + +[[ $(create_device nvmf_tcp | jq -r '.handle') == 'nvmf_tcp:plugin1-device2' ]] +NOT create_device nvme + +killprocess $smapid + +# Load two different plugins, but only enable devices from one of them +PYTHONPATH=$testdir/plugins $rootdir/scripts/sma.py -c <( + cat <<- EOF + plugins: + - 'plugin1' + - 'plugin2' + devices: + - name: 'plugin1-device1' + - name: 'plugin1-device2' + EOF +) & +smapid=$! +sma_waitforlisten + +[[ $(create_device nvme | jq -r '.handle') == 'nvme:plugin1-device1' ]] +[[ $(create_device nvmf_tcp | jq -r '.handle') == 'nvmf_tcp:plugin1-device2' ]] + +killprocess $smapid + +# Check the same but take devices defined by the other plugin +PYTHONPATH=$testdir/plugins $rootdir/scripts/sma.py -c <( + cat <<- EOF + plugins: + - 'plugin1' + - 'plugin2' + devices: + - name: 'plugin2-device1' + - name: 'plugin2-device2' + EOF +) & +smapid=$! +sma_waitforlisten + +[[ $(create_device nvme | jq -r '.handle') == 'nvme:plugin2-device1' ]] +[[ $(create_device nvmf_tcp | jq -r '.handle') == 'nvmf_tcp:plugin2-device2' ]] + +killprocess $smapid + +# Now pick a device from each plugin +PYTHONPATH=$testdir/plugins $rootdir/scripts/sma.py -c <( + cat <<- EOF + plugins: + - 'plugin1' + - 'plugin2' + devices: + - name: 'plugin1-device1' + - name: 'plugin2-device2' + EOF +) & +smapid=$! +sma_waitforlisten + +[[ $(create_device nvme | jq -r '.handle') == 'nvme:plugin1-device1' ]] +[[ $(create_device nvmf_tcp | jq -r '.handle') == 'nvmf_tcp:plugin2-device2' ]] + +killprocess $smapid + +# Check the same, but register plugins via a env var +PYTHONPATH=$testdir/plugins SMA_PLUGINS=plugin1:plugin2 $rootdir/scripts/sma.py -c <( + cat <<- EOF + devices: + - name: 'plugin1-device1' + - name: 'plugin2-device2' + EOF +) & +smapid=$! +sma_waitforlisten + +[[ $(create_device nvme | jq -r '.handle') == 'nvme:plugin1-device1' ]] +[[ $(create_device nvmf_tcp | jq -r '.handle') == 'nvmf_tcp:plugin2-device2' ]] + +killprocess $smapid + +# Finally, register one plugin in a config and the other through env var +PYTHONPATH=$testdir/plugins SMA_PLUGINS=plugin1 $rootdir/scripts/sma.py -c <( + cat <<- EOF + plugins: + - 'plugin2' + devices: + - name: 'plugin1-device1' + - name: 'plugin2-device2' + EOF +) & +smapid=$! +sma_waitforlisten + +[[ $(create_device nvme | jq -r '.handle') == 'nvme:plugin1-device1' ]] +[[ $(create_device nvmf_tcp | jq -r '.handle') == 'nvmf_tcp:plugin2-device2' ]] + +killprocess $smapid + +trap - SIGINT SIGTERM EXIT diff --git a/test/sma/plugins/plugin1/__init__.py b/test/sma/plugins/plugin1/__init__.py new file mode 100644 index 000000000..d5daf5365 --- /dev/null +++ b/test/sma/plugins/plugin1/__init__.py @@ -0,0 +1,21 @@ +from spdk.sma import DeviceManager +from spdk.sma.proto import sma_pb2 + + +class TestDeviceManager1(DeviceManager): + def __init__(self, client): + super().__init__('plugin1-device1', 'nvme', client) + + def create_device(self, request): + return sma_pb2.CreateDeviceResponse(handle=f'{self.protocol}:{self.name}') + + +class TestDeviceManager2(DeviceManager): + def __init__(self, client): + super().__init__('plugin1-device2', 'nvmf_tcp', client) + + def create_device(self, request): + return sma_pb2.CreateDeviceResponse(handle=f'{self.protocol}:{self.name}') + + +devices = [TestDeviceManager1, TestDeviceManager2] diff --git a/test/sma/plugins/plugin2/__init__.py b/test/sma/plugins/plugin2/__init__.py new file mode 100644 index 000000000..8ff4165d5 --- /dev/null +++ b/test/sma/plugins/plugin2/__init__.py @@ -0,0 +1,21 @@ +from spdk.sma import DeviceManager +from spdk.sma.proto import sma_pb2 + + +class TestDeviceManager1(DeviceManager): + def __init__(self, client): + super().__init__('plugin2-device1', 'nvme', client) + + def create_device(self, request): + return sma_pb2.CreateDeviceResponse(handle=f'{self.protocol}:{self.name}') + + +class TestDeviceManager2(DeviceManager): + def __init__(self, client): + super().__init__('plugin2-device2', 'nvmf_tcp', client) + + def create_device(self, request): + return sma_pb2.CreateDeviceResponse(handle=f'{self.protocol}:{self.name}') + + +devices = [TestDeviceManager1, TestDeviceManager2] diff --git a/test/sma/sma.sh b/test/sma/sma.sh index a9a3ea56e..744edb656 100755 --- a/test/sma/sma.sh +++ b/test/sma/sma.sh @@ -6,3 +6,4 @@ rootdir=$(readlink -f "$testdir/../..") source "$rootdir/test/common/autotest_common.sh" run_test "sma_nvmf_tcp" $testdir/nvmf_tcp.sh +run_test "sma_plugins" $testdir/plugins.sh