예제 #1
0
    def acquire(self, hostId, lease):
        with nested(self._lock, SANLock._sanlock_lock):
            self.log.info("Acquiring %s for host id %s", lease, hostId)

            while True:
                if SANLock._sanlock_fd is None:
                    try:
                        SANLock._sanlock_fd = sanlock.register()
                    except sanlock.SanlockException as e:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot register to sanlock", str(e))

                try:
                    sanlock.acquire(self._sdUUID, lease.name,
                                    [(lease.path, lease.offset)],
                                    slkfd=SANLock._sanlock_fd)
                except sanlock.SanlockException as e:
                    if e.errno != errno.EPIPE:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot acquire %s" % (lease,), str(e))
                    SANLock._sanlock_fd = None
                    continue

                break

            self.log.debug("Successfully acquired %s for host id %s",
                           lease, hostId)
예제 #2
0
    def acquire(self, hostId):
        with nested(self._lock, SANLock._sanlock_lock):
            self.log.info("Acquiring cluster lock for domain %s (id: %s)",
                          self._sdUUID, hostId)

            while True:
                if SANLock._sanlock_fd is None:
                    try:
                        SANLock._sanlock_fd = sanlock.register()
                    except sanlock.SanlockException as e:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot register to sanlock", str(e))

                try:
                    sanlock.acquire(self._sdUUID,
                                    SDM_LEASE_NAME,
                                    self.getLockDisk(),
                                    slkfd=SANLock._sanlock_fd)
                except sanlock.SanlockException as e:
                    if e.errno != os.errno.EPIPE:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot acquire cluster lock", str(e))
                    SANLock._sanlock_fd = None
                    continue

                break

            self.log.debug(
                "Cluster lock for domain %s successfully acquired "
                "(id: %s)", self._sdUUID, hostId)
예제 #3
0
    def acquire(self, hostID, lease):
        if lease != self._lease:
            raise MultipleLeasesNotSupported("acquire", lease)
        leaseTimeMs = self._leaseTimeSec * 1000
        ioOpTimeoutMs = self._ioOpTimeoutSec * 1000
        with self._lock:
            self.log.debug("Acquiring cluster lock for domain %s" %
                           self._sdUUID)

            lockUtil = self.getLockUtilFullPath()
            acquireLockCommand = subprocess.list2cmdline([
                lockUtil, "start", self._sdUUID, str(hostID),
                str(self._lockRenewalIntervalSec), str(lease.path),
                str(leaseTimeMs), str(ioOpTimeoutMs),
                str(self._leaseFailRetry), str(os.getpid())
            ])

            cmd = [constants.EXT_SU, misc.IOUSER, '-s', constants.EXT_SH, '-c',
                   acquireLockCommand]
            (rc, out, err) = misc.execCmd(cmd, cwd=self.lockUtilPath,
                                          sudo=True,
                                          ioclass=utils.IOCLASS.REALTIME,
                                          ioclassdata=0, setsid=True)
            if rc != 0:
                raise se.AcquireLockFailure(self._sdUUID, rc, out, err)
            self.log.debug("Clustered lock acquired successfully")
예제 #4
0
    def acquire(self, hostId, lease):
        self.log.info("Acquiring %s for host id %s", lease, hostId)

        # If host id was acquired by this thread, this will return immediately.
        # If host is id being acquired asynchronically by the domain monitor,
        # wait until the domain monitor find that host id was acquired.
        #
        # IMPORTANT: This must be done *before* entering the lock. Once we
        # enter the lock, the domain monitor cannot check if host id was
        # acquired, since hasHostId() is using the same lock.
        if not self._ready.wait(self.ACQUIRE_HOST_ID_TIMEOUT):
            raise se.AcquireHostIdFailure(
                "Timeout acquiring host id, cannot acquire %s (id=%s)" %
                (lease, hostId))

        with self._lock, SANLock._sanlock_lock:
            while True:
                if SANLock._sanlock_fd is None:
                    try:
                        SANLock._sanlock_fd = sanlock.register()
                    except sanlock.SanlockException as e:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot register to sanlock", str(e))

                resource_name = lease.name.encode("utf-8")
                try:
                    sanlock.acquire(self._lockspace_name,
                                    resource_name,
                                    [(lease.path, lease.offset)],
                                    slkfd=SANLock._sanlock_fd)
                except sanlock.SanlockException as e:
                    if e.errno != errno.EPIPE:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot acquire %s" % (lease, ), str(e))
                    SANLock._sanlock_fd = None
                    continue

                break

        self.log.info("Successfully acquired %s for host id %s", lease, hostId)
예제 #5
0
    def acquire(self, hostId, lease):
        if lease != self._lease:
            raise MultipleLeasesNotSupported("acquire", lease)
        with self._globalLockMapSync:
            self.log.info("Acquiring local lock for domain %s (id: %s)",
                          self._sdUUID, hostId)

            hostId, lockFile = self._getLease()

            if lockFile:
                try:
                    osutils.uninterruptible(fcntl.fcntl, lockFile,
                                            fcntl.F_GETFD)
                except IOError as e:
                    # We found a stale file descriptor, removing.
                    del self._globalLockMap[self._sdUUID]

                    # Raise any other unkown error.
                    if e.errno != errno.EBADF:
                        raise
                else:
                    self.log.debug(
                        "Local lock already acquired for domain "
                        "%s (id: %s)", self._sdUUID, hostId)
                    return  # success, the lock was already acquired

            lockFile = osutils.uninterruptible(os.open, self._idsPath,
                                               os.O_RDONLY)

            try:
                osutils.uninterruptible(fcntl.flock, lockFile,
                                        fcntl.LOCK_EX | fcntl.LOCK_NB)
            except IOError as e:
                osutils.close_fd(lockFile)
                if e.errno in (errno.EACCES, errno.EAGAIN):
                    raise se.AcquireLockFailure(self._sdUUID, e.errno,
                                                "Cannot acquire local lock",
                                                str(e))
                raise
            else:
                self._globalLockMap[self._sdUUID] = (hostId, lockFile)

        self.log.debug(
            "Local lock for domain %s successfully acquired "
            "(id: %s)", self._sdUUID, hostId)
예제 #6
0
    def acquire(self, hostId, lease, lvb=False):
        if lvb and not supports_lvb:
            raise se.UnsupportedOperation(
                "This sanlock version does not support LVB")

        self.log.info("Acquiring %s for host id %s, lvb=%s",
                      lease, hostId, lvb)

        # If host id was acquired by this thread, this will return immediately.
        # If host is id being acquired asynchronically by the domain monitor,
        # wait until the domain monitor find that host id was acquired.
        #
        # IMPORTANT: This must be done *before* entering the lock. Once we
        # enter the lock, the domain monitor cannot check if host id was
        # acquired, since hasHostId() is using the same lock.
        if not self._ready.wait(self.ACQUIRE_HOST_ID_TIMEOUT):
            raise se.AcquireHostIdFailure(
                "Timeout acquiring host id, cannot acquire %s (id=%s)"
                % (lease, hostId))

        with self._lock, SANLock._process_lock:
            while True:
                if SANLock._process_fd is None:
                    try:
                        SANLock._process_fd = sanlock.register()
                    except sanlock.SanlockException as e:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot register to sanlock", str(e))

                    self.log.info("Using sanlock process fd %d",
                                  SANLock._process_fd)

                # TODO: remove once sanlock 3.8.3 is available on centos.
                extra_args = {"lvb": lvb} if supports_lvb else {}

                try:
                    sanlock.acquire(
                        self._lockspace_name,
                        lease.name.encode("utf-8"),
                        [(lease.path, lease.offset)],
                        slkfd=SANLock._process_fd,
                        **extra_args)
                except sanlock.SanlockException as e:
                    if e.errno != errno.EPIPE:
                        raise se.AcquireLockFailure(
                            self._sdUUID, e.errno,
                            "Cannot acquire %s" % (lease,), str(e))

                    # If we hold leases, we just lost them, since sanlock is
                    # releasing all process leases when the process fd is
                    # closed. The only way to recover is to panic; child
                    # processes run by vdsm will be killed, and vdsm will lose
                    # the SPM role.
                    if SANLock._lease_count > 0:
                        panic("Sanlock process fd was closed while "
                              "holding {} leases: {}"
                              .format(SANLock._lease_count, e))

                    self.log.warning("Sanlock process fd was closed: %s", e)
                    SANLock._process_fd = None
                    continue

                SANLock._lease_count += 1
                break

        self.log.info("Successfully acquired %s for host id %s", lease, hostId)
예제 #7
0
 def error(*args):
     raise se.AcquireLockFailure('id', 'rc', 'out', 'err')