示例#1
0
async def test_rpc_timeout(container_mod, mayastor_mod, create_temp_file,
                           pool_file):
    ms1_c = container_mod.get("ms1")
    ms1 = mayastor_mod.get("ms1")
    uuid = str(guid.uuid4())

    timeout_pattern = 'destroy_replica: gRPC method timed out, args: DestroyReplicaRequest {{ uuid: "{}" }}'.format(
        uuid)

    # Create a pool and a big replica (> 1 GB)
    ms1.pool_create("pool1", "uring://{}".format(pool_file))
    ms1.replica_create("pool1", uuid, 2 * 1024 * 1024 * 1024)

    # Set timeout to the minimum possible value and reconnect handles.
    ms1.set_timeout(1)
    ms1.reconnect()

    # Destroy the replica and trigger the timeout.
    with pytest.raises(grpc.RpcError) as error:
        ms1.replica_destroy(uuid)
    assert error.value.code() == grpc.StatusCode.INVALID_ARGUMENT

    # Should not see error message pattern, as we expect the call to be timed out.
    assert str(ms1_c.logs()).find(timeout_pattern) == -1

    # Try to destroy the replica one more time - the call should complete
    # without assertions.
    # We expect this call to detect the incompleted previous call and emit
    # a warning.
    ms1.replica_destroy(uuid)

    # Now we should see the evidence that the gRPC call was timed out.
    assert str(ms1_c.logs()).find(timeout_pattern) > 0
def create_nexus_2(mayastor_mod, nexus_name, nexus_uuid, min_cntlid_2,
                   resv_key_2):
    """ Create a 2nd nexus on ms0 with the same 2 replicas but with resv_key_2 """
    hdls = mayastor_mod
    NEXUS_NAME = nexus_name

    replicas = []
    list = mayastor_mod.get("ms3").nexus_list_v2()
    nexus = next(n for n in list if n.name == NEXUS_NAME)
    replicas.append(nexus.children[0].uri)
    replicas.append(nexus.children[1].uri)

    NEXUS_UUID, size_mb = nexus_uuid

    hdls["ms0"].nexus_create_v2(
        NEXUS_NAME,
        NEXUS_UUID,
        size_mb,
        min_cntlid_2,
        min_cntlid_2 + 9,
        resv_key_2,
        0,
        replicas,
    )
    uri = hdls["ms0"].nexus_publish(NEXUS_NAME)
    assert len(hdls["ms0"].bdev_list()) == 1
    assert len(hdls["ms1"].bdev_list()) == 2
    assert len(hdls["ms2"].bdev_list()) == 2
    assert len(hdls["ms3"].bdev_list()) == 1

    dev = nvme_connect(uri)

    yield dev
    nvme_disconnect(uri)
    hdls["ms0"].nexus_destroy(NEXUS_NAME)
示例#3
0
async def test_mayastor_features(mayastor_mod):
    ms1 = mayastor_mod.get("ms1")
    ms3 = mayastor_mod.get("ms3")

    for replica, ms in ((True, ms1), (False, ms3)):
        ms_info = ms.mayastor_info()

        assert ms_info.version.startswith("v0.")

        # Should see ANA disabled on mayastors where environment
        # variable is not set.
        features = ms_info.supportedFeatures
        if replica:
            assert features.asymmetricNamespaceAccess == False
        else:
            assert features.asymmetricNamespaceAccess == True
示例#4
0
async def test_controller_stats(mayastor_mod, create_replicas, create_nexus):
    nexus = mayastor_mod.get("ms3")
    mscli = get_msclient().with_json_output().with_url(nexus.ip_address())

    # Should see exactly 2 controllers on the nexus instance.
    assure_controllers(mscli, create_replicas)

    # Check that stats exist for all controllers and are initially empty.
    output = mscli("controller", "stats")
    assert len(output["controllers"]) == len(create_replicas)
    names = [c["name"] for c in output["controllers"]]

    for r in create_replicas:
        c = ctrl_name_from_uri(r)
        assert c in names, "Controller for replica %s not found" % c

    for s in output["controllers"]:
        stats = s["stats"]
        for n in stats.keys():
            assert stats[n] == 0, "Stat %s is not zero for a new controller" % n

    # Issue I/O to replicas and make sure stats reflect that.
    job = FioSpdk("job1", "readwrite", create_nexus, runtime=5).build()
    await run_cmd_async(job)

    target_stats = ["num_read_ops", "num_write_ops", "bytes_read", "bytes_written"]
    cached_stats = {"num_write_ops": 0, "bytes_written": 0}

    output = mscli("controller", "stats")
    assert len(output["controllers"]) == 2
    for c in output["controllers"]:
        stats = c["stats"]

        # Make sure all related I/O stats are counted.
        for s in target_stats:
            assert stats[s] > 0, "I/O stat %s is zero after active I/O operations" % s

        # Make sure IOPS and number of bytes are sane (fio uses 4k block).
        assert (
            stats["bytes_read"] == stats["num_read_ops"] * 4096
        ), "Read IOPs don't match number of bytes"
        assert (
            stats["bytes_written"] == stats["num_write_ops"] * 4096
        ), "Write IOPs don't match number of bytes"

        # Check that write-related stats are equal for all controllers in the same nexus
        # and make sure all unrelated stats remained untouched.
        for s in stats.keys():
            if s in cached_stats:
                # Cache I/O stat to check across all controllers against the same value.
                if cached_stats[s] == 0:
                    cached_stats[s] = stats[s]
                else:
                    # I/O stats for all controllers in a nexus must be equal.
                    assert cached_stats[s] == stats[s], (
                        "I/O statistics %s for replicas mismatch" % s
                    )
            elif s not in target_stats:
                assert stats[s] == 0, "Unrelated I/O stat %s got impacted by I/O" % s
示例#5
0
def create_replicas(mayastor_mod):
    ms1 = mayastor_mod.get("ms1")
    ms2 = mayastor_mod.get("ms2")

    replicas = []

    for m in (ms1, ms2):
        p = m.pool_create(POOL_NAME, "malloc:///disk0?size_mb=100")
        assert p.state == pb.POOL_ONLINE
        r = m.replica_create(POOL_NAME, str(uuid.uuid4()), 32 * 1024 * 1024)
        replicas.append(r.uri)
    yield replicas
    try:
        for m in (ms1, ms2):
            m.pool_destroy(POOL_NAME)
    except Exception:
        pass
示例#6
0
def create_nexuses(mayastor_mod, create_replicas):
    uris = []

    nvme_disconnect_all()

    for n in ["ms2", "ms3"]:
        ms = mayastor_mod.get(n)
        ms.nexus_create(NEXUS_GUID, 32 * 1024 * 1024, create_replicas)
        uri = ms.nexus_publish(NEXUS_GUID)
        uris.append(uri)

    yield uris

    nvme_disconnect_all()

    for n in ["ms2", "ms3"]:
        ms = mayastor_mod.get(n)
        ms.nexus_destroy(NEXUS_GUID)
示例#7
0
async def test_controller_list(mayastor_mod, create_replicas, create_nexus):
    replica1 = mayastor_mod.get("ms1")
    replica2 = mayastor_mod.get("ms2")
    replicas = [replica1, replica2]
    nexus = mayastor_mod.get("ms3")
    mscli = get_msclient().with_json_output()

    # Should not see any controllers on replica instances.
    for r in replicas:
        output = mscli.with_url(r.ip_address())("controller", "list")
        assert len(output["controllers"]) == 0

    # Should see exactly 2 controllers on the nexus instance.
    mscli.with_url(nexus.ip_address())
    assure_controllers(mscli, create_replicas)

    # Should not see a controller for the removed replica.
    nexus.nexus_remove_replica(NEXUS_GUID, create_replicas[0])
    assure_controllers(mscli, create_replicas[1:])

    # Should see controller for the newly added replica.
    nexus.nexus_add_replica(NEXUS_GUID, create_replicas[0], True)
    assure_controllers(mscli, create_replicas)
示例#8
0
async def test_io_policy(create_replicas, create_nexuses, mayastor_mod):
    devs = connect_multipath_nexuses(create_nexuses)
    assert devs[0] == devs[1], "Paths are different for multipath nexus"

    # Make sure all we see exactly 2 paths and all paths are 'live optimized'
    device = devs[0]
    descr = nvme_list_subsystems(device)
    paths = descr["Subsystems"][0]["Paths"]
    assert len(paths) == 2, "Number of paths to Nexus mismatches"

    for p in paths:
        assert p["State"] == "live"
        assert p["ANAState"] == "optimized"

    # Make sure there are 2 virtual NVMe controllers for the namespace.
    ns = os.path.basename(device)
    for i in range(2):
        cname = ns.replace("n1", "c%dn1" % i)
        cpath = "/sys/block/%s" % cname
        l = os.readlink(cpath)
        assert l.startswith(
            "../devices/virtual/nvme-fabrics/ctl/"
        ), "Path device is not a virtual controller"

    # Make sure virtual NVMe namespace exists for multipath nexus.
    l = os.readlink("/sys/block/%s" % ns)
    assert l.startswith(
        "../devices/virtual/nvme-subsystem/nvme-subsys"
    ), "No virtual NVMe subsystem exists for multipath Nexus"

    # Make sure I/O policy is NUMA.
    subsys = descr["Subsystems"][0]["Name"]
    pfile = "/sys/class/nvme-subsystem/%s/iopolicy" % subsys
    assert os.path.isfile(pfile), "No iopolicy file exists"
    with open(pfile) as f:
        iopolicy = f.read().strip()
        assert iopolicy == "numa", "I/O policy is not NUMA"

    # Make sure ANA state is reported properly for both nexuses.
    for n in ["ms2", "ms3"]:
        ms = mayastor_mod.get(n)
        nexuses = ms.nexus_list_v2()
        assert len(nexuses) == 1, "Number of nexuses mismatches"
        assert (
            nexuses[0].ana_state == pb.NVME_ANA_OPTIMIZED_STATE
        ), "ANA state of nexus mismatches"
示例#9
0
def test_nexus_multipath(
    create_nexus,
    create_nexus_2,
    nexus_name,
    nexus_uuid,
    mayastor_mod,
    resv_key,
    resv_key_2,
):
    """Create 2 nexuses, each with 2 replicas, with different NVMe reservation keys"""

    uri = create_nexus
    uri2 = create_nexus_2
    NEXUS_UUID, _ = nexus_uuid
    NEXUS_NAME = nexus_name
    resv_key = resv_key
    resv_key_2 = resv_key_2

    list = mayastor_mod.get("ms3").nexus_list_v2()
    nexus = next(n for n in list if n.name == NEXUS_NAME)
    assert nexus.uuid == NEXUS_UUID

    for c in range(2):
        child_uri = nexus.children[c].uri

        dev = nvme_connect(child_uri)
        report = nvme_resv_report(dev)

        assert (report["rtype"] == 5
                ), "should have write exclusive, all registrants reservation"
        assert report["regctl"] == 2, "should have 2 registered controllers"
        assert report[
            "ptpls"] == 0, "should have Persist Through Power Loss State of 0"
        for i in range(2):
            assert (report["regctlext"][i]["cntlid"] == 0xFFFF
                    ), "should have dynamic controller ID"
        assert report["regctlext"][0]["rkey"] == resv_key
        assert report["regctlext"][1]["rkey"] == resv_key_2
        assert (report["regctlext"][0]["rcsts"] & 0x1) == 1
        assert (report["regctlext"][1]["rcsts"] & 0x1) == 0

        nvme_disconnect(child_uri)
示例#10
0
def create_nexus_3_dev(mayastor_mod, nexus_name, nexus_uuid, replica_uuid,
                       min_cntlid_3, resv_key_3):
    """ Create a 3rd nexus on ms1 with the same 2 replicas but with resv_key_3 """
    hdls = mayastor_mod
    NEXUS_NAME = nexus_name

    replicas = []
    list = mayastor_mod.get("ms3").nexus_list_v2()
    nexus = next(n for n in list if n.name == NEXUS_NAME)
    # use loopback until nvme initiator can connect to target in same instance
    REP_UUID, rep_size_mb = replica_uuid
    replicas.append("loopback:///" + REP_UUID)
    replicas.append(nexus.children[1].uri)

    NEXUS_UUID, size_mb = nexus_uuid

    hdls["ms1"].nexus_create_v2(
        NEXUS_NAME,
        NEXUS_UUID,
        size_mb,
        min_cntlid_3,
        min_cntlid_3 + 9,
        resv_key_3,
        0,
        replicas,
    )
    uri = hdls["ms1"].nexus_publish(NEXUS_NAME)
    assert len(hdls["ms0"].bdev_list()) == 1
    assert len(hdls["ms1"].bdev_list()) == 3
    assert len(hdls["ms2"].bdev_list()) == 2
    assert len(hdls["ms3"].bdev_list()) == 1

    dev = nvme_connect(uri)

    yield dev
    nvme_disconnect(uri)
    hdls["ms1"].nexus_destroy(NEXUS_NAME)
示例#11
0
def create_nexus(mayastor_mod, create_replicas):
    ms3 = mayastor_mod.get("ms3")
    ms3.nexus_create(NEXUS_GUID, 32 * 1024 * 1024, create_replicas)
    uri = ms3.nexus_publish(NEXUS_GUID)
    yield uri
    ms3.nexus_destroy(NEXUS_GUID)