diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml new file mode 100644 index 000000000..2771c1c49 --- /dev/null +++ b/.github/workflows/build-container.yml @@ -0,0 +1,67 @@ +name: Build container Test +on: [push, pull_request, workflow_dispatch] +env: + # Control gRPC port + PORT: 5500 + +jobs: + build-container-test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + # git submodule update --init --recursive + submodules: recursive + + - name: Build container images + run: make build + + - name: Setup huge pages + run: make setup + + - name: Compose Up + run: | + make up || (make logs; exit 1) + + - name: Wait for controller to start + run: | + until nc -z localhost $PORT; do + echo -n . + sleep 1 + done + echo + + - name: List containers + run: | + docker-compose ps + + - name: Create RBD image + run: | + echo "💁 ceph list pools:" + docker exec ceph-cluster ceph osd lspools + echo "💁 rbd create:" + docker exec ceph-cluster rbd create rbd/mytestdevimage --size 16 + echo "💁 ls rbd:" + docker exec ceph-cluster rbd ls rbd + + - name: Run CLI + run: | + docker-compose run ceph-nvmeof-cli + docker-compose run ceph-nvmeof-cli create_bdev -i mytestdevimage -p rbd -b Ceph0 + docker-compose run ceph-nvmeof-cli create_subsystem -n nqn.2016-06.io.spdk:cnode1 -s SPDK00000000000001 + docker-compose run ceph-nvmeof-cli add_namespace -n nqn.2016-06.io.spdk:cnode1 -b Ceph0 + docker-compose run ceph-nvmeof-cli add_host -n nqn.2016-06.io.spdk:cnode1 -t '*' + docker-compose run ceph-nvmeof-cli create_listener -n nqn.2016-06.io.spdk:cnode1 -s 5001 + # should fail https://github.com/ceph/ceph-nvmeof/issues/137 + if docker-compose run ceph-nvmeof-cli create_bdev -i mytestdevimage -p rbd -b Ceph0; then exit 1; fi + if docker-compose run ceph-nvmeof-cli create_bdev -i wrongimage -p rbd -b Ceph0; then exit 1; fi + - name: Display Logs + run: | + docker-compose logs + + - name: Compose Down + run: make down + + - name: Compose Stop + run: make stop diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 000000000..c218652af --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,62 @@ +name: Run pytest +on: [push, pull_request, workflow_dispatch] + +jobs: + pytest: + strategy: + matrix: + test: ["cli", "state", "multi-gateway"] + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + # git submodule update --init --recursive + submodules: recursive + + - name: Build images + run: | + make build + + - name: Setup huge pages + run: | + make setup + + - name: Start ceph-cluster + run: | + docker-compose up --detach ceph-cluster + + - name: Wait for the ceph-cluster container to become healthy + run: | + while true; do + container_status=$(docker inspect --format='{{.State.Health.Status}}' ceph-cluster) + if [[ $container_status == "healthy" ]]; then + break + else + # Wait for a specific time before checking again + sleep 1 + fi + done + + - name: Create RBD image + run: | + echo "💁 ceph list pools:" + docker exec ceph-cluster ceph osd lspools + echo "💁 rbd create:" + docker exec ceph-cluster rbd create rbd/mytestdevimage --size 16 + echo "💁 ls rbd:" + docker exec ceph-cluster rbd ls rbd + + - name: Run ${{ matrix.test }} test + run: | + docker-compose run ceph-nvmeof-pytest-${{ matrix.test }} || (docker-compose logs; exit 1) + + - name: Display Logs + run: | + docker-compose logs + + - name: Compose Down + run: make down + + - name: Compose Stop + run: make stop diff --git a/ceph-nvmeof.conf b/ceph-nvmeof.conf index 84af07563..92d6f4c6c 100644 --- a/ceph-nvmeof.conf +++ b/ceph-nvmeof.conf @@ -10,7 +10,7 @@ [gateway] name = group = -addr = 192.168.13.3 +addr = 0.0.0.0 port = 5500 enable_auth = False state_update_notify = True @@ -31,6 +31,8 @@ client_cert = ./client.crt tgt_path = /usr/local/bin/nvmf_tgt rpc_socket = /var/tmp/spdk.sock #tgt_cmd_extra_args = --env-context="--no-huge -m1024" --iova-mode=va +# https://github.com/spdk/spdk/issues/2731 +tgt_cmd_extra_args = --num-trace-entries 0 timeout = 60.0 log_level = WARN # conn_retries = 10 diff --git a/control/cli.py b/control/cli.py index 9b19947cc..1eea95a2b 100644 --- a/control/cli.py +++ b/control/cli.py @@ -21,7 +21,6 @@ def argument(*name_or_flags, **kwargs): return (list(name_or_flags), kwargs) - class Parser: """Class to simplify creation of client CLI. @@ -36,7 +35,7 @@ def __init__(self): description="CLI to manage NVMe gateways") self.parser.add_argument( "--server-address", - default="localhost", + default="ceph-nvmeof_ceph-nvmeof_1", type=str, help="Server address", ) @@ -165,6 +164,7 @@ def create_bdev(self, args): self.logger.info(f"Created bdev {ret.bdev_name}: {ret.status}") except Exception as error: self.logger.error(f"Failed to create bdev: \n {error}") + sys.exit(1) @cli.cmd([ argument("-b", "--bdev", help="Bdev name", required=True), @@ -178,6 +178,7 @@ def delete_bdev(self, args): self.logger.info(f"Deleted bdev {args.bdev}: {ret.status}") except Exception as error: self.logger.error(f"Failed to delete bdev: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -193,6 +194,7 @@ def create_subsystem(self, args): self.logger.info(f"Created subsystem {args.subnqn}: {ret.status}") except Exception as error: self.logger.error(f"Failed to create subsystem: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -206,6 +208,7 @@ def delete_subsystem(self, args): self.logger.info(f"Deleted subsystem {args.subnqn}: {ret.status}") except Exception as error: self.logger.error(f"Failed to delete subsystem: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -224,6 +227,7 @@ def add_namespace(self, args): f"Added namespace {ret.nsid} to {args.subnqn}: {ret.status}") except Exception as error: self.logger.error(f"Failed to add namespace: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -241,6 +245,7 @@ def remove_namespace(self, args): f" {ret.status}") except Exception as error: self.logger.error(f"Failed to remove namespace: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -262,6 +267,7 @@ def add_host(self, args): f" {ret.status}") except Exception as error: self.logger.error(f"Failed to add host: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -283,6 +289,7 @@ def remove_host(self, args): f" {ret.status}") except Exception as error: self.logger.error(f"Failed to remove host: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -308,6 +315,7 @@ def create_listener(self, args): self.logger.info(f"Created {args.subnqn} listener: {ret.status}") except Exception as error: self.logger.error(f"Failed to create listener: \n {error}") + sys.exit(1) @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), @@ -334,6 +342,7 @@ def delete_listener(self, args): f"Deleted {args.traddr} from {args.subnqn}: {ret.status}") except Exception as error: self.logger.error(f"Failed to delete listener: \n {error}") + sys.exit(1) @cli.cmd() def get_subsystems(self, args): @@ -347,6 +356,7 @@ def get_subsystems(self, args): self.logger.info(f"Get subsystems:\n{formatted_subsystems}") except Exception as error: self.logger.error(f"Failed to get subsystems: \n {error}") + sys.exit(1) def main(args=None): diff --git a/docker-compose.yaml b/docker-compose.yaml index e6fbe14ea..2c6a56548 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -44,7 +44,6 @@ services: build: context: . target: ceph-nvmeof - hostname: ceph-nvmeof volumes: # sudo bash -c 'echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages' # https://spdk.io/doc/containers.html @@ -54,19 +53,42 @@ services: cap_add: - SYS_ADMIN - CAP_SYS_NICE - networks: - default: - ipv4_address: 192.168.13.3 - ports: - - "4420:4420" # I/O controllers - - "5500:5500" # Gateway - - "8009:8009" # Discovery ceph-nvmeof: extends: service: ceph-nvmeof-base depends_on: ceph-cluster: condition: service_healthy + ports: + - 0.0.0.0:5500:5500 # Gateway RPC see addr/port in ceph-nvmeof.conf + - 0.0.0.0:4420:4420 # I/O controllers + - 0.0.0.0:8009:8009 # Discovery + + ceph-nvmeof-pytest-base: + # Run tests code in current dir + extends: + service: ceph-nvmeof-base + volumes: + - ./tests:/src/tests + + ceph-nvmeof-pytest-cli: + extends: + service: ceph-nvmeof-pytest-base + entrypoint: | + python3 -m pytest tests/test_cli.py + + ceph-nvmeof-pytest-multi-gateway: + extends: + service: ceph-nvmeof-pytest-base + entrypoint: | + python3 -m pytest tests/test_multi_gateway.py + + ceph-nvmeof-pytest-state: + extends: + service: ceph-nvmeof-pytest-base + entrypoint: | + python3 -m pytest tests/test_state.py + ceph-nvmeof-devel: # Runs from source code in current dir extends: diff --git a/pdm.lock b/pdm.lock index 1b7fcef23..6cf209b37 100644 --- a/pdm.lock +++ b/pdm.lock @@ -1,6 +1,18 @@ # This file is @generated by PDM. # It is not intended for manual editing. +[[package]] +name = "colorama" +version = "0.4.6" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +summary = "Cross-platform colored terminal text." + +[[package]] +name = "exceptiongroup" +version = "1.1.1" +requires_python = ">=3.7" +summary = "Backport of PEP 654 (exception groups)" + [[package]] name = "grpcio" version = "1.51.3" @@ -18,24 +30,69 @@ dependencies = [ "setuptools", ] +[[package]] +name = "iniconfig" +version = "2.0.0" +requires_python = ">=3.7" +summary = "brain-dead simple config-ini parsing" + +[[package]] +name = "packaging" +version = "23.1" +requires_python = ">=3.7" +summary = "Core utilities for Python packages" + +[[package]] +name = "pluggy" +version = "1.0.0" +requires_python = ">=3.6" +summary = "plugin and hook calling mechanisms for python" + [[package]] name = "protobuf" version = "4.22.3" requires_python = ">=3.7" summary = "" +[[package]] +name = "pytest" +version = "7.3.1" +requires_python = ">=3.7" +summary = "pytest: simple powerful testing with Python" +dependencies = [ + "colorama; sys_platform == \"win32\"", + "exceptiongroup>=1.0.0rc8; python_version < \"3.11\"", + "iniconfig", + "packaging", + "pluggy<2.0,>=0.12", + "tomli>=1.0.0; python_version < \"3.11\"", +] + [[package]] name = "setuptools" version = "67.6.1" requires_python = ">=3.7" summary = "Easily download, build, install, upgrade, and uninstall Python packages" +[[package]] +name = "tomli" +version = "2.0.1" +requires_python = ">=3.7" +summary = "A lil' TOML parser" + [metadata] lock_version = "4.2" +cross_platform = true groups = ["default"] -content_hash = "sha256:7c5ff98836a77ca8db2cdb86e2527f5325c8b4293934dbc3b50270ec6a71280b" +content_hash = "sha256:51b277072460b88d0b61f7689b194e6a597b8e690fd72d5c966f33544e9b6684" [metadata.files] +"colorama 0.4.6" = [ + {url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, +] +"exceptiongroup 1.1.1" = [ + {url = "https://files.pythonhosted.org/packages/61/97/17ed81b7a8d24d8f69b62c0db37abbd8c0042d4b3fc429c73dab986e7483/exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, +] "grpcio 1.51.3" = [ {url = "https://files.pythonhosted.org/packages/04/ff/bf51e638082314fd845f48cb761bca09b7ed9b20f2f7b87a6ec64a252f6b/grpcio-1.51.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2f8ff75e61e1227ba7a3f16b2eadbcc11d0a54096d52ab75a6b88cfbe56f55d1"}, {url = "https://files.pythonhosted.org/packages/06/06/5798d75123f63a7dbe57c99f3bfb63738e0adee867b1842477915d22fd87/grpcio-1.51.3-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:eef0450a4b5ed11feab639bf3eb1b6e23d0efa9b911bf7b06fb60e14f5f8a585"}, @@ -128,6 +185,15 @@ content_hash = "sha256:7c5ff98836a77ca8db2cdb86e2527f5325c8b4293934dbc3b50270ec6 {url = "https://files.pythonhosted.org/packages/ff/17/5dfbb5dd5d3f0add353e8f4905b7591f7af69b4df1ab2d5fd2c95f812e69/grpcio_tools-1.51.3-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:3c445a064b2ef3d3475e26e2add8ddb4ac2933741ecddf71d5b071a3ad078db4"}, {url = "https://files.pythonhosted.org/packages/ff/fc/daa42e82f8bb30a20e1c8dd20cfd3a58ddb6224237d5c5d38989e2f55689/grpcio_tools-1.51.3-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:83bf605fe2b3591d3c8a78646f37c72c5832c4dd84b5f92405c17cb10b136be6"}, ] +"iniconfig 2.0.0" = [ + {url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, +] +"packaging 23.1" = [ + {url = "https://files.pythonhosted.org/packages/ab/c3/57f0601a2d4fe15de7a553c00adbc901425661bf048f2a22dfc500caf121/packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, +] +"pluggy 1.0.0" = [ + {url = "https://files.pythonhosted.org/packages/9e/01/f38e2ff29715251cf25532b9082a1589ab7e4f571ced434f98d0139336dc/pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, +] "protobuf 4.22.3" = [ {url = "https://files.pythonhosted.org/packages/25/ca/79af03ceec0f9439d8fb5c2c8d99454c5c4f8c7fe00c8e7dbb280a8177c8/protobuf-4.22.3-cp38-cp38-win_amd64.whl", hash = "sha256:f2f4710543abec186aee332d6852ef5ae7ce2e9e807a3da570f36de5a732d88e"}, {url = "https://files.pythonhosted.org/packages/2f/db/42950497852aa35940a33e29118d8a2117fb20072bee08728f0948b70d7a/protobuf-4.22.3-cp38-cp38-win32.whl", hash = "sha256:f08aa300b67f1c012100d8eb62d47129e53d1150f4469fd78a29fa3cb68c66f2"}, @@ -142,6 +208,12 @@ content_hash = "sha256:7c5ff98836a77ca8db2cdb86e2527f5325c8b4293934dbc3b50270ec6 {url = "https://files.pythonhosted.org/packages/f4/fd/d8d309382c71c5e83a1920ae9840410396e595e3b36229d96e3ba755687e/protobuf-4.22.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:13233ee2b9d3bd9a5f216c1fa2c321cd564b93d8f2e4f521a85b585447747997"}, {url = "https://files.pythonhosted.org/packages/f8/70/6291e75633eeaa24fed46c9f66091bec184644e6159f392ac32eb92b1f65/protobuf-4.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:e0e630d8e6a79f48c557cd1835865b593d0547dce221c66ed1b827de59c66c97"}, ] +"pytest 7.3.1" = [ + {url = "https://files.pythonhosted.org/packages/1b/d1/72df649a705af1e3a09ffe14b0c7d3be1fd730da6b98beb4a2ed26b8a023/pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, +] "setuptools 67.6.1" = [ {url = "https://files.pythonhosted.org/packages/0b/fc/8781442def77b0aa22f63f266d4dadd486ebc0c5371d6290caf4320da4b7/setuptools-67.6.1-py3-none-any.whl", hash = "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078"}, ] +"tomli 2.0.1" = [ + {url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, +] diff --git a/pyproject.toml b/pyproject.toml index 9cce39678..55b7a25a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,8 +18,9 @@ authors = [ keywords = [] classifiers = [] # https://pypi.org/classifiers/ dependencies = [ - "grpcio == 1.51.3", - "grpcio_tools == 1.51.3" + "grpcio == 1.51.3", + "grpcio_tools == 1.51.3", + "pytest>=7.3.1", ] [tool.pdm.scripts] diff --git a/tests/test_cli.py b/tests/test_cli.py index 6a9588b95..cf1979597 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,8 +1,9 @@ import pytest +from control.server import GatewayServer import socket from control.cli import main as cli -image = "iscsidevimage" +image = "mytestdevimage" pool = "rbd" bdev = "Ceph0" subsystem = "nqn.2016-06.io.spdk:cnode1" @@ -15,56 +16,69 @@ listener_list = [["-g", gateway_name, "-a", addr, "-s", "5001"], ["-s", "5002"]] config = "ceph-nvmeof.conf" +@pytest.fixture(scope="module") +def gateway(config): + """Sets up and tears down Gateway""" + + # Start gateway + gateway = GatewayServer(config) + gateway.serve() + + yield + + # Stop gateway + gateway.server.stop(grace=1) + gateway.gateway_rpc.gateway_state.delete_state() class TestGet: - def test_get_subsystems(self, caplog): - cli(["-c", config, "get_subsystems"]) + def test_get_subsystems(self, caplog, gateway): + cli(["--server-address", "localhost", "get_subsystems"]) assert "Failed to get" not in caplog.text class TestCreate: - def test_create_bdev(self, caplog): - cli(["-c", config, "create_bdev", "-i", image, "-p", pool, "-b", bdev]) + def test_create_bdev(self, caplog, gateway): + cli(["--server-address", "localhost", "create_bdev", "-i", image, "-p", pool, "-b", bdev]) assert "Failed to create" not in caplog.text - def test_create_subsystem(self, caplog): - cli(["-c", config, "create_subsystem", "-n", subsystem, "-s", serial]) + def test_create_subsystem(self, caplog, gateway): + cli(["--server-address", "localhost", "create_subsystem", "-n", subsystem, "-s", serial]) assert "Failed to create" not in caplog.text - def test_add_namespace(self, caplog): - cli(["-c", config, "add_namespace", "-n", subsystem, "-b", bdev]) + def test_add_namespace(self, caplog, gateway): + cli(["--server-address", "localhost", "add_namespace", "-n", subsystem, "-b", bdev]) assert "Failed to add" not in caplog.text @pytest.mark.parametrize("host", host_list) def test_add_host(self, caplog, host): - cli(["-c", config, "add_host", "-n", subsystem, "-t", host]) + cli(["--server-address", "localhost", "add_host", "-n", subsystem, "-t", host]) assert "Failed to add" not in caplog.text @pytest.mark.parametrize("listener", listener_list) - def test_create_listener(self, caplog, listener): - cli(["-c", config, "create_listener", "-n", subsystem] + listener) + def test_create_listener(self, caplog, listener, gateway): + cli(["--server-address", "localhost", "create_listener", "-n", subsystem] + listener) assert "Failed to create" not in caplog.text class TestDelete: @pytest.mark.parametrize("host", host_list) - def test_remove_host(self, caplog, host): - cli(["-c", config, "remove_host", "-n", subsystem, "-t", host]) + def test_remove_host(self, caplog, host, gateway): + cli(["--server-address", "localhost", "remove_host", "-n", subsystem, "-t", host]) assert "Failed to remove" not in caplog.text @pytest.mark.parametrize("listener", listener_list) - def test_delete_listener(self, caplog, listener): - cli(["-c", config, "delete_listener", "-n", subsystem] + listener) + def test_delete_listener(self, caplog, listener, gateway): + cli(["--server-address", "localhost", "delete_listener", "-n", subsystem] + listener) assert "Failed to delete" not in caplog.text - def test_remove_namespace(self, caplog): - cli(["-c", config, "remove_namespace", "-n", subsystem, "-i", nsid]) + def test_remove_namespace(self, caplog, gateway): + cli(["--server-address", "localhost", "remove_namespace", "-n", subsystem, "-i", nsid]) assert "Failed to remove" not in caplog.text - def test_delete_bdev(self, caplog): - cli(["-c", config, "delete_bdev", "-b", bdev]) + def test_delete_bdev(self, caplog, gateway): + cli(["--server-address", "localhost", "delete_bdev", "-b", bdev]) assert "Failed to delete" not in caplog.text - def test_delete_subsystem(self, caplog): - cli(["-c", config, "delete_subsystem", "-n", subsystem]) + def test_delete_subsystem(self, caplog, gateway): + cli(["--server-address", "localhost", "delete_subsystem", "-n", subsystem]) assert "Failed to delete" not in caplog.text diff --git a/tests/test_multi_gateway.py b/tests/test_multi_gateway.py index c66eb1240..43b543279 100644 --- a/tests/test_multi_gateway.py +++ b/tests/test_multi_gateway.py @@ -4,8 +4,8 @@ import json import time from control.server import GatewayServer -from control.generated import gateway_pb2 as pb2 -from control.generated import gateway_pb2_grpc as pb2_grpc +from control.proto import gateway_pb2 as pb2 +from control.proto import gateway_pb2_grpc as pb2_grpc update_notify = True update_interval_sec = 5 @@ -20,6 +20,7 @@ def conn(config): configA.config["gateway"]["group"] = "Group1" configA.config["gateway"]["state_update_notify"] = str(update_notify) configB = copy.deepcopy(configA) + extra_args = configA.get("spdk", "tgt_cmd_extra_args") addr = configA.get("gateway", "addr") portA = configA.getint("gateway", "port") portB = portA + 1 @@ -28,7 +29,7 @@ def conn(config): configB.config["gateway"]["state_update_interval_sec"] = str( update_interval_sec) configB.config["spdk"]["rpc_socket"] = "/var/tmp/spdk_GatewayB.sock" - configB.config["spdk"]["tgt_cmd_extra_args"] = "-m 0x02" + configB.config["spdk"]["tgt_cmd_extra_args"] = extra_args + " -m 0x02" # Start servers gatewayA = GatewayServer(configA) @@ -51,7 +52,6 @@ def conn(config): gatewayB.server.stop(grace=1) gatewayB.gateway_rpc.gateway_state.delete_state() - def test_multi_gateway_coordination(config, image, conn): """Tests state coordination in a gateway group.