Example #1
0
def main():
    signal.signal(signal.SIGTERM, sigTermHandler)

    print "Creating the sanlock disk"
    fd, disk = tempfile.mkstemp()
    os.close(fd)

    os.chown(disk,
             pwd.getpwnam("sanlock").pw_uid,
             grp.getgrnam("sanlock").gr_gid)
    offset = sanlock.get_alignment(disk)

    SNLK_DISKS = [(disk, offset)]

    print "Registering to sanlock"
    fd = sanlock.register()

    print "Initializing '%s'" % (LOCKSPACE_NAME, )
    sanlock.write_lockspace(LOCKSPACE_NAME, disk)

    print "Initializing '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME)
    sanlock.write_resource(LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS)

    print "Acquiring the id '%i' on '%s'" % (HOST_ID, LOCKSPACE_NAME)
    sanlock.add_lockspace(LOCKSPACE_NAME, HOST_ID, disk)

    try:
        print "Acquiring '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME)
        sanlock.acquire(LOCKSPACE_NAME,
                        RESOURCE_NAME,
                        SNLK_DISKS,
                        slkfd=fd,
                        version=0)
        while True:
            print "Trying to get lockspace '%s' hosts" % LOCKSPACE_NAME
            try:
                hosts_list = sanlock.get_hosts(LOCKSPACE_NAME)
            except sanlock.SanlockException as e:
                if e.errno != os.errno.EAGAIN:
                    raise
            else:
                print "Lockspace '%s' hosts: " % LOCKSPACE_NAME, hosts_list
                break
            time.sleep(5)
        print "Resource '%s' owners: " % RESOURCE_NAME, \
            sanlock.read_resource_owners(
                LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS)
        print "Releasing '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME)
        sanlock.release(LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS, slkfd=fd)
    except Exception as e:
        print "Exception: ", e
    finally:
        print "Releasing the id '%i' on '%s'" % (HOST_ID, LOCKSPACE_NAME)
        sanlock.rem_lockspace(LOCKSPACE_NAME, HOST_ID, disk)

    print "Removing the sanlock disk"
    os.remove(disk)
Example #2
0
 def getHostStatus(self, hostId):
     try:
         hosts = sanlock.get_hosts(self._sdUUID, hostId)
     except sanlock.SanlockException as e:
         self.log.debug("Unable to get host %d status in lockspace %s: %s", hostId, self._sdUUID, e)
         return HOST_STATUS_UNAVAILABLE
     else:
         status = hosts[0]["flags"]
         return self.STATUS_NAME[status]
Example #3
0
 def getHostStatus(self, hostId):
     try:
         hosts = sanlock.get_hosts(self._lockspace_name, hostId)
     except sanlock.SanlockException as e:
         self.log.debug("Unable to get host %d status in lockspace %s: %s",
                        hostId, self._sdUUID, e)
         return HOST_STATUS_UNAVAILABLE
     else:
         status = hosts[0]['flags']
         return self.STATUS_NAME[status]
Example #4
0
def main():
    signal.signal(signal.SIGTERM, sigTermHandler)

    print "Creating the sanlock disk"
    fd, disk = tempfile.mkstemp()
    os.close(fd)

    os.chown(disk, pwd.getpwnam("sanlock").pw_uid, grp.getgrnam("sanlock").gr_gid)
    offset = sanlock.get_alignment(disk)

    SNLK_DISKS = [(disk, offset)]

    print "Registering to sanlock"
    fd = sanlock.register()

    print "Initializing '%s'" % (LOCKSPACE_NAME,)
    sanlock.write_lockspace(LOCKSPACE_NAME, disk, max_hosts=0, iotimeout=0, align=1048576, sector=512)

    print "Initializing '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME)
    sanlock.write_resource(LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS, align=1048576, sector=512)

    print "Acquiring the id '%i' on '%s'" % (HOST_ID, LOCKSPACE_NAME)
    sanlock.add_lockspace(LOCKSPACE_NAME, HOST_ID, disk)

    try:
        print "Acquiring '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME)
        sanlock.acquire(LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS, slkfd=fd,
                        version=0)
        while True:
            print "Trying to get lockspace '%s' hosts" % LOCKSPACE_NAME
            try:
                hosts_list = sanlock.get_hosts(LOCKSPACE_NAME)
            except sanlock.SanlockException as e:
                if e.errno != os.errno.EAGAIN:
                    raise
            else:
                print "Lockspace '%s' hosts: " % LOCKSPACE_NAME, hosts_list
                break
            time.sleep(5)
        print "Resource '%s' owners: " % RESOURCE_NAME, \
            sanlock.read_resource_owners(
                LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS, align=1048576, sector=512)
        print "Releasing '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME)
        sanlock.release(LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS, slkfd=fd)
    except Exception as e:
        print "Exception: ", e
    finally:
        print "Releasing the id '%i' on '%s'" % (HOST_ID, LOCKSPACE_NAME)
        sanlock.rem_lockspace(LOCKSPACE_NAME, HOST_ID, disk)

    print "Removing the sanlock disk"
    os.remove(disk)
Example #5
0
    def getHostStatus(self, hostId):
        # Note: get_hosts has off-by-one bug when asking for particular host
        # id, so get all hosts info and filter.
        # See https://bugzilla.redhat.com/1111210
        try:
            hosts = sanlock.get_hosts(self._sdUUID)
        except sanlock.SanlockException as e:
            self.log.debug("Unable to get host %d status in lockspace %s: %s",
                           hostId, self._sdUUID, e)
            return HOST_STATUS_UNAVAILABLE

        for info in hosts:
            if info['host_id'] == hostId:
                status = info['flags']
                return self.STATUS_NAME[status]

        # get_hosts with host_id=0 returns only hosts with timestamp != 0,
        # which means that no host is using this host id now. If there a
        # timestamp, sanlock will return HOST_UNKNOWN and then HOST_LIVE or
        # HOST_FAIL.
        return HOST_STATUS_FREE
Example #6
0
    def getHostStatus(self, hostId):
        # Note: get_hosts has off-by-one bug when asking for particular host
        # id, so get all hosts info and filter.
        # See https://bugzilla.redhat.com/1111210
        try:
            hosts = sanlock.get_hosts(self._sdUUID)
        except sanlock.SanlockException as e:
            self.log.debug("Unable to get host %d status in lockspace %s: %s",
                           hostId, self._sdUUID, e)
            return HOST_STATUS_UNAVAILABLE

        for info in hosts:
            if info['host_id'] == hostId:
                status = info['flags']
                return self.STATUS_NAME[status]

        # get_hosts with host_id=0 returns only hosts with timestamp != 0,
        # which means that no host is using this host id now. If there a
        # timestamp, sanlock will return HOST_UNKNOWN and then HOST_LIVE or
        # HOST_FAIL.
        return HOST_STATUS_FREE
Example #7
0
def test_get_hosts_parse_args(no_sanlock_daemon, name):
    with raises_sanlock_errno():
        sanlock.get_hosts(name, 1)
Example #8
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 == []
SANLOCK_PATH = '/var/lib/libvirt/sanlock/'
SANLOCK_PATH = os.path.abspath(SANLOCK_PATH + RESOURCE_NAME)
offset = sanlock.get_alignment(SANLOCK_PATH)
SNLK_DISKS = [(SANLOCK_PATH, offset)]


def sanlock_acquire(hostId, lockspacePath, leasePath):
    sfd = sanlock.register()
    if not sanlock.inq_lockspace(LOCKSPACE_NAME, hostId, lockspacePath):
        msg = "Try to acquire host id %s:%s:%s:0" % (LOCKSPACE_NAME, hostId,
                                                     lockspacePath)
        print(msg)
        sanlock.add_lockspace(LOCKSPACE_NAME, hostId, lockspacePath)
    msg = "Try to acquire leader lease:%s" % str(leasePath)
    print(msg)
    sanlock.acquire(LOCKSPACE_NAME, RESOURCE_NAME, [(leasePath, 0)], sfd)


if __name__ == "__main__":
    host_id = int(sys.argv[1])
    lockspace_path = sys.argv[2]
    lease_path = sys.argv[3]
    hosts_list = sanlock.get_hosts(LOCKSPACE_NAME)
    msg = 'sanlock hosts:%s' % str(hosts_list)
    print msg
    sanlock_acquire(host_id, lockspace_path, lease_path)
    time.sleep(180)
    resource_owners = sanlock.read_resource_owners(LOCKSPACE_NAME,
                                                   RESOURCE_NAME, SNLK_DISKS)
    print 'resource_owners:%s' % str(resource_owners)
Example #10
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
Example #11
0
def test_get_hosts_parse_args(no_sanlock_daemon, name):
    with raises_sanlock_errno():
        sanlock.get_hosts(name, 1)
Example #12
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 == []