Ejemplo n.º 1
0
def test_write_resource(
        tmpdir, sanlock_daemon, filename, encoding, size, offset):
    path = util.generate_path(tmpdir, filename, encoding)
    util.create_file(path, size)
    disks = [(path, offset)]

    # Test read and write with default alignment and sector size values.
    sanlock.write_resource(b"ls_name", b"res_name", disks)

    res = sanlock.read_resource(path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    # Test read and write with explicit alignment and sector size values.
    sanlock.write_resource(
        b"ls_name", b"res_name", disks, align=ALIGNMENT_1M,
        sector=SECTOR_SIZE_512)

    res = sanlock.read_resource(
        path, offset=offset, align=ALIGNMENT_1M, sector=SECTOR_SIZE_512)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    owners = sanlock.read_resource_owners(b"ls_name", b"res_name", disks)
    assert owners == []

    magic = util.read_magic(path, offset)
    assert magic == constants.PAXOS_DISK_MAGIC
    util.check_guard(path, size)
Ejemplo n.º 2
0
def test_read_resource_path_length(no_sanlock_daemon):
    path = "x" * constants.SANLK_PATH_LEN
    with pytest.raises(ValueError):
        sanlock.read_resource(path)

    path = "x" * (constants.SANLK_PATH_LEN - 1)
    with raises_sanlock_errno():
        sanlock.read_resource(path)
Ejemplo n.º 3
0
def test_read_resource_4k_invalid_sector_size(sanlock_daemon, user_4k_path):
    disks = [(user_4k_path, 0)]

    sanlock.write_resource(b"ls_name",
                           b"res_name",
                           disks,
                           align=ALIGNMENT_1M,
                           sector=SECTOR_SIZE_4K)

    with pytest.raises(sanlock.SanlockException) as e:
        sanlock.read_resource(user_4k_path, sector=SECTOR_SIZE_512)
    assert e.value.errno == errno.EINVAL
Ejemplo n.º 4
0
def test_read_resource_4k_invalid_sector_size(sanlock_daemon, user_4k_path):
    disks = [(user_4k_path, 0)]

    sanlock.write_resource(
        "ls_name",
        "res_name",
        disks,
        align=ALIGNMENT_1M,
        sector=SECTOR_SIZE_4K)

    with pytest.raises(sanlock.SanlockException) as e:
        sanlock.read_resource(user_4k_path, sector=SECTOR_SIZE_512)
    assert e.value.errno == errno.EINVAL
Ejemplo n.º 5
0
def test_write_resource_4k(sanlock_daemon, user_4k_path, align):
    disks = [(user_4k_path, 0)]

    # Poison resource area, ensuring that previous tests will not break this
    # test, and sanlock does not write beyond the lockspace area.
    with io.open(user_4k_path, "rb+") as f:
        f.write(align * b"x")
    util.write_guard(user_4k_path, align)

    sanlock.write_resource(
        b"ls_name", b"res_name", disks, align=align, sector=SECTOR_SIZE_4K)

    res = sanlock.read_resource(
        user_4k_path, align=align, sector=SECTOR_SIZE_4K)

    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    owners = sanlock.read_resource_owners(
        b"ls_name", b"res_name", disks, align=align, sector=SECTOR_SIZE_4K)
    assert owners == []

    # Verify that resource was written.
    magic = util.read_magic(user_4k_path)
    assert magic == constants.PAXOS_DISK_MAGIC

    # Check that sanlock did not write beyond the lockspace area.
    util.check_guard(user_4k_path, align)
Ejemplo n.º 6
0
def test_write_resource_4k(sanlock_daemon, user_4k_path, align):
    disks = [(user_4k_path, 0)]

    # Poison resource area, ensuring that previous tests will not break this
    # test, and sanlock does not write beyond the lockspace area.
    with io.open(user_4k_path, "rb+") as f:
        f.write(align * b"x")
    util.write_guard(user_4k_path, align)

    sanlock.write_resource(
        "ls_name", "res_name", disks, align=align, sector=SECTOR_SIZE_4K)

    res = sanlock.read_resource(
        user_4k_path, align=align, sector=SECTOR_SIZE_4K)

    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    owners = sanlock.read_resource_owners(
        "ls_name", "res_name", disks, align=align, sector=SECTOR_SIZE_4K)
    assert owners == []

    # Verify that resource was written.
    with io.open(user_4k_path, "rb") as f:
        magic, = struct.unpack("< I", f.read(4))
        assert magic == constants.PAXOS_DISK_MAGIC

    # Check that sanlock did not write beyond the lockspace area.
    util.check_guard(user_4k_path, align)
Ejemplo n.º 7
0
def _read_resource(path,
                   offset,
                   alignment=sc.ALIGNMENT_1M,
                   block_size=sc.BLOCK_SIZE_512):
    """
    Helper for reading sanlock resoruces, supporting both non-existing and
    deleted resources.

    Returns: ResourceInfo
    Raises: NoSuchResource if there is no resource at this offset
    """
    try:
        res = sanlock.read_resource(path,
                                    offset,
                                    align=alignment,
                                    sector=block_size)
    except sanlock.SanlockException as e:
        if e.errno != SANLK_LEADER_MAGIC:
            raise
        raise NoSuchResource(path, offset)
    if res["resource"] == b"":
        # lease deleted with a version of sanlock not supporting
        # resource clearning.
        raise NoSuchResource(path, offset)
    return ResourceInfo(res["lockspace"].decode("utf-8"),
                        res["resource"].decode("utf-8"), res["version"])
Ejemplo n.º 8
0
def test_write_resource(tmpdir, sanlock_daemon, size, offset):
    path = str(tmpdir.join("resources"))
    util.create_file(path, size)
    disks = [(path, offset)]

    # test read and write with default alignment and sector size values
    sanlock.write_resource("ls_name", "res_name", disks)

    res = sanlock.read_resource(path, offset=offset)
    assert res == {
        "lockspace": "ls_name",
        "resource": "res_name",
        "version": 0
    }

    # test read and write with explicit alignment and sector size values
    sanlock.write_resource("ls_name",
                           "res_name",
                           disks,
                           align=ALIGNMENT_1M,
                           sector=SECTOR_SIZE_512)

    res = sanlock.read_resource(path,
                                offset=offset,
                                align=ALIGNMENT_1M,
                                sector=SECTOR_SIZE_512)
    assert res == {
        "lockspace": "ls_name",
        "resource": "res_name",
        "version": 0
    }

    owners = sanlock.read_resource_owners("ls_name", "res_name", disks)
    assert owners == []

    with io.open(path, "rb") as f:
        f.seek(offset)
        magic, = struct.unpack("< I", f.read(4))
        assert magic == constants.PAXOS_DISK_MAGIC

        # TODO: check more stuff here...

    util.check_guard(path, size)
Ejemplo n.º 9
0
def test_clear_resource(tmpdir, sanlock_daemon):
    path = util.generate_path(tmpdir, "clear_test")
    util.create_file(path, MiB)
    disks = [(path, 0)]

    sanlock.write_resource(b"ls_name", b"res_name", disks)
    sanlock.write_resource(b"ls_name", b"res_name", disks, clear=True)

    with pytest.raises(sanlock.SanlockException) as e:
        sanlock.read_resource(path)
    assert e.value.errno == constants.SANLK_LEADER_MAGIC

    magic = util.read_magic(path)
    assert magic == constants.PAXOS_DISK_CLEAR

    util.check_guard(path, MiB)

    # run clear on already cleared resource
    sanlock.write_resource(b"ls_name", b"res_name", disks, clear=True)
    magic = util.read_magic(path)
    assert magic == constants.PAXOS_DISK_CLEAR
Ejemplo n.º 10
0
def test_write_resource(tmpdir, sanlock_daemon, filename, encoding, size, offset):
    path = util.generate_path(tmpdir, filename, encoding)
    util.create_file(path, size)
    disks = [(path, offset)]

    # Test read and write with default alignment and sector size values.
    sanlock.write_resource("ls_name", "res_name", disks)

    res = sanlock.read_resource(path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    # Test read and write with explicit alignment and sector size values.
    sanlock.write_resource(
        "ls_name", "res_name", disks, align=ALIGNMENT_1M,
        sector=SECTOR_SIZE_512)

    res = sanlock.read_resource(
        path, offset=offset, align=ALIGNMENT_1M, sector=SECTOR_SIZE_512)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    owners = sanlock.read_resource_owners("ls_name", "res_name", disks)
    assert owners == []

    with io.open(path, "rb") as f:
        f.seek(offset)
        magic, = struct.unpack("< I", f.read(4))
        assert magic == constants.PAXOS_DISK_MAGIC

        # TODO: check more stuff here...

    util.check_guard(path, size)
Ejemplo n.º 11
0
    def inquire(self):
        resource = sanlock.read_resource(self._leasesPath, SDM_LEASE_OFFSET)
        owners = sanlock.read_resource_owners(self._sdUUID, SDM_LEASE_NAME,
                                              self.getLockDisk())

        if len(owners) == 1:
            return resource.get("version"), owners[0].get("host_id")
        elif len(owners) > 1:
            self.log.error("Cluster lock is reported to have more than "
                           "one owner: %s", owners)
            raise RuntimeError("Cluster lock multiple owners error")

        return None, None
Ejemplo n.º 12
0
    def inquire(self, lease):
        resource = sanlock.read_resource(lease.path, lease.offset)
        owners = sanlock.read_resource_owners(self._sdUUID, lease.name,
                                              [(lease.path, lease.offset)])

        if len(owners) == 1:
            return resource.get("version"), owners[0].get("host_id")
        elif len(owners) > 1:
            self.log.error("Cluster lock is reported to have more than "
                           "one owner: %s", owners)
            raise RuntimeError("Multiple owners for %s" % (lease,))

        return None, None
Ejemplo n.º 13
0
    def inquire(self):
        resource = sanlock.read_resource(self._leasesPath, SDM_LEASE_OFFSET)
        owners = sanlock.read_resource_owners(self._sdUUID, SDM_LEASE_NAME,
                                              self.getLockDisk())

        if len(owners) == 1:
            return resource.get("version"), owners[0].get("host_id")
        elif len(owners) > 1:
            self.log.error(
                "Cluster lock is reported to have more than "
                "one owner: %s", owners)
            raise RuntimeError("Cluster lock multiple owners error")

        return None, None
Ejemplo n.º 14
0
    def inquire(self, lease):
        resource = sanlock.read_resource(lease.path, lease.offset)
        if resource["resource"] != lease.name:
            raise InvalidLeaseName(resource["resource"], lease)

        owners = sanlock.read_resource_owners(self._sdUUID, lease.name, [(lease.path, lease.offset)])

        if len(owners) == 1:
            return resource.get("version"), owners[0].get("host_id")
        elif len(owners) > 1:
            self.log.error("Cluster lock is reported to have more than " "one owner: %s", owners)
            raise RuntimeError("Multiple owners for %s" % (lease,))

        return None, None
Ejemplo n.º 15
0
def test_read_resource_parse_args(no_sanlock_daemon, filename, encoding):
    path = util.generate_path("/tmp/", filename, encoding)
    with raises_sanlock_errno():
        sanlock.read_resource(path)
Ejemplo n.º 16
0
def test_acquire_release_resource(tmpdir, sanlock_daemon, size, offset):
    ls_path = str(tmpdir.join("ls_name"))
    util.create_file(ls_path, size)

    res_path = str(tmpdir.join("res_name"))
    util.create_file(res_path, size)

    sanlock.write_lockspace(b"ls_name", ls_path, offset=offset, iotimeout=1)
    sanlock.add_lockspace(b"ls_name", 1, ls_path, offset=offset, iotimeout=1)

    # Host status is not available until the first renewal.
    with pytest.raises(sanlock.SanlockException) as e:
        sanlock.get_hosts(b"ls_name", 1)
    assert e.value.errno == errno.EAGAIN

    time.sleep(1)
    host = sanlock.get_hosts(b"ls_name", 1)[0]
    assert host["flags"] == sanlock.HOST_LIVE

    disks = [(res_path, offset)]
    sanlock.write_resource(b"ls_name", b"res_name", disks)

    res = sanlock.read_resource(res_path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    owners = sanlock.read_resource_owners(b"ls_name", b"res_name", disks)
    assert owners == []

    fd = sanlock.register()
    sanlock.acquire(b"ls_name", b"res_name", disks, slkfd=fd)

    res = sanlock.read_resource(res_path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 1
    }

    owner = sanlock.read_resource_owners(b"ls_name", b"res_name", disks)[0]

    assert owner["host_id"] == 1
    assert owner["flags"] == 0
    assert owner["generation"] == 1
    assert owner["io_timeout"] == 0  # Why 0?
    # TODO: check timestamp.

    host = sanlock.get_hosts(b"ls_name", 1)[0]
    assert host["flags"] == sanlock.HOST_LIVE
    assert host["generation"] == owner["generation"]

    sanlock.release(b"ls_name", b"res_name", disks, slkfd=fd)

    res = sanlock.read_resource(res_path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 1
    }

    owners = sanlock.read_resource_owners(b"ls_name", b"res_name", disks)
    assert owners == []
Ejemplo n.º 17
0
    def inspect(self, lease):
        resource = sanlock.read_resource(
            lease.path,
            lease.offset,
            align=self._alignment,
            sector=self._block_size)

        resource_name = lease.name.encode("utf-8")
        if resource["resource"] != resource_name:
            raise InvalidLeaseName(resource["resource"], lease)

        owners = sanlock.read_resource_owners(
            self._lockspace_name,
            resource_name,
            [(lease.path, lease.offset)],
            align=self._alignment,
            sector=self._block_size)

        if len(owners) > 1:
            self.log.error("Cluster lock is reported to have more than "
                           "one owner: %s", owners)
            raise RuntimeError("Multiple owners for %s" % (lease,))

        elif not owners:
            return None, None

        resource_owner = owners[0]
        resource_version = resource["version"]
        host_id = resource_owner["host_id"]
        try:
            host = sanlock.get_hosts(self._lockspace_name, host_id)[0]
        except sanlock.SanlockException as e:
            if e.errno == errno.ENOENT:
                # add_lockspace has not been completed yet,
                # the inquiry has to be retried.
                raise TemporaryFailure("inspect", lease, str(e))
            elif e.errno == errno.EAGAIN:
                # The host status is not available yet.
                # Normally, we'd raise it to the caller, but this
                # breaks the "Remove DC" flow in engine, so we assume
                # the lease is currently held by the host
                # See: https://bugzilla.redhat.com/1613838
                self.log.debug("host %s status in not available yet, "
                               "it may hold the lease %s",
                               host_id, lease)
                return resource_version, host_id
            else:
                raise

        host_status = self.STATUS_NAME[host["flags"]]

        if resource_owner["generation"] != host["generation"]:
            # The lease is considered free by sanlock because
            # the host reconnected to the storage but it no
            # longer has the lease
            self.log.debug("host %r generation %r does not match resource "
                           "generation %r, lease %s is free", host_id,
                           host, resource_owner["generation"], lease)
            return resource_version, None

        if host_status in (HOST_STATUS_DEAD, HOST_STATUS_FREE):
            # These are the only states that mean the host cannot hold
            # this lease. Any other state means the host either holding the
            # lease or could be holding the lease.
            self.log.debug("host %s cannot hold %s is effectively free",
                           host, lease)
            return resource_version, None

        return resource_version, host_id
Ejemplo n.º 18
0
def test_acquire_release_resource(tmpdir, sanlock_daemon, size, offset):
    ls_path = str(tmpdir.join("ls_name"))
    util.create_file(ls_path, size)

    res_path = str(tmpdir.join("res_name"))
    util.create_file(res_path, size)

    sanlock.write_lockspace("ls_name", ls_path, offset=offset, iotimeout=1)
    sanlock.add_lockspace("ls_name", 1, ls_path, offset=offset, iotimeout=1)

    # Host status is not available until the first renewal.
    with pytest.raises(sanlock.SanlockException) as e:
        sanlock.get_hosts("ls_name", 1)
    assert e.value.errno == errno.EAGAIN

    time.sleep(1)
    host = sanlock.get_hosts("ls_name", 1)[0]
    assert host["flags"] == sanlock.HOST_LIVE

    disks = [(res_path, offset)]
    sanlock.write_resource("ls_name", "res_name", disks)

    res = sanlock.read_resource(res_path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 0
    }

    owners = sanlock.read_resource_owners("ls_name", "res_name", disks)
    assert owners == []

    fd = sanlock.register()
    sanlock.acquire("ls_name", "res_name", disks, slkfd=fd)

    res = sanlock.read_resource(res_path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 1
    }

    owner = sanlock.read_resource_owners("ls_name", "res_name", disks)[0]

    assert owner["host_id"] == 1
    assert owner["flags"] == 0
    assert owner["generation"] == 1
    assert owner["io_timeout"] == 0  # Why 0?
    # TODO: check timestamp.

    host = sanlock.get_hosts("ls_name", 1)[0]
    assert host["flags"] == sanlock.HOST_LIVE
    assert host["generation"] == owner["generation"]

    sanlock.release("ls_name", "res_name", disks, slkfd=fd)

    res = sanlock.read_resource(res_path, offset=offset)
    assert res == {
        "lockspace": b"ls_name",
        "resource": b"res_name",
        "version": 1
    }

    owners = sanlock.read_resource_owners("ls_name", "res_name", disks)
    assert owners == []