예제 #1
0
    def __call__(self, timeout):
        """Wait for something to happen on the pipe.

    @type timeout: float or None
    @param timeout: Timeout for waiting (can be None)

    """
        running_timeout = utils.RunningTimeout(timeout, True)
        poller = select.poll()
        poller.register(self._fd, select.POLLHUP)

        while True:
            remaining_time = running_timeout.Remaining()

            if remaining_time is not None:
                if remaining_time < 0.0:
                    break

                # Our calculation uses seconds, poll() wants milliseconds
                remaining_time *= 1000

            try:
                result = poller.poll(remaining_time)
            except EnvironmentError, err:
                if err.errno != errno.EINTR:
                    raise
                result = None

            # Check whether we were notified
            if result and result[0][0] == self._fd:
                break
예제 #2
0
    def ExecOpCode(self, op, cbs, timeout=None):
        """Execute an opcode.

    @type op: an OpCode instance
    @param op: the opcode to be executed
    @type cbs: L{OpExecCbBase}
    @param cbs: Runtime callbacks
    @type timeout: float or None
    @param timeout: Maximum time to acquire all locks, None for no timeout
    @raise LockAcquireTimeout: In case locks couldn't be acquired in specified
        amount of time

    """
        if not isinstance(op, opcodes.OpCode):
            raise errors.ProgrammerError("Non-opcode instance passed"
                                         " to ExecOpcode (%s)" % type(op))

        lu_class = self.DISPATCH_TABLE.get(op.__class__, None)
        if lu_class is None:
            raise errors.OpCodeUnknown("Unknown opcode")

        if timeout is None:
            calc_timeout = lambda: None
        else:
            calc_timeout = utils.RunningTimeout(timeout, False).Remaining

        self._cbs = cbs
        try:
            result = self._PrepareLockListsAndExecLU(op, lu_class,
                                                     calc_timeout)

            # The post hooks below are always executed with a SUCCESS status because
            # all the possible errors during pre hooks and LU execution cause
            # exception and therefore the statement below will be skipped.
            if self._hm is not None:
                self._hm.RunPhase(
                    constants.HOOKS_PHASE_POST,
                    is_global=True,
                    post_status=constants.POST_HOOKS_STATUS_SUCCESS)
        except:
            # execute global post hooks with the failed status on any exception
            hooksmaster.ExecGlobalPostHooks(op.OP_ID,
                                            self.cfg.GetMasterNodeName(),
                                            self.rpc.call_hooks_runner,
                                            logging.warning,
                                            self.cfg.GetClusterName(),
                                            self.cfg.GetMasterNode(),
                                            self.GetECId(),
                                            constants.POST_HOOKS_STATUS_ERROR)
            raise

        self._CheckLUResult(op, result)
        return result
예제 #3
0
    def run(self, max_delay=None):  # pylint: disable=W0221
        """Run any pending events.

    @type max_delay: None or number
    @param max_delay: Maximum delay (useful if caller has timeouts running)

    """
        assert self._max_delay is None

        # The delay function used by the scheduler can't be different on each run,
        # hence an instance variable must be used.
        if max_delay is None:
            self._max_delay = None
        else:
            self._max_delay = utils.RunningTimeout(max_delay, False)

        try:
            return sched.scheduler.run(self)
        finally:
            self._max_delay = None
예제 #4
0
    def CanShutdown(self):
        """Checks whether mainloop can be stopped.

    @rtype: bool

    """
        if self._defer and self._defer.Remaining() > 0:
            # A deferred check has already been scheduled
            return False

        # Ask mainloop driver whether we can stop or should check again
        timeout = self._fn()

        if timeout is None:
            # Yes, can stop mainloop
            return True

        # Schedule another check in the future
        self._defer = utils.RunningTimeout(timeout, True)

        return False
예제 #5
0
    def __call__(self, jq_prepare_result):
        """Determines if master daemon is ready for shutdown.

    @param jq_prepare_result: Result of L{jqueue.JobQueue.PrepareShutdown}
    @rtype: None or number
    @return: None if master daemon is ready, timeout if the check must be
             repeated

    """
        if jq_prepare_result:
            # Check again shortly
            logging.info(
                "Job queue has been notified for shutdown but is still"
                " busy; next check in %s seconds", self._CHECK_INTERVAL)
            self._had_active_jobs = True
            return self._CHECK_INTERVAL

        if not self._had_active_jobs:
            # Can shut down as there were no active jobs on the first check
            return None

        # No jobs are running anymore, but maybe some clients want to collect some
        # information. Give them a short amount of time.
        if self._linger_timeout is None:
            self._linger_timeout = utils.RunningTimeout(
                self._SHUTDOWN_LINGER, True)

        remaining = self._linger_timeout.Remaining()

        logging.info(
            "Job queue no longer busy; shutting down master daemon"
            " in %s seconds", remaining)

        # TODO: Should the master daemon socket be closed at this point? Doing so
        # wouldn't affect existing connections.

        if remaining < 0:
            return None
        else:
            return remaining
예제 #6
0
    def ExecOpCode(self, op, cbs, timeout=None):
        """Execute an opcode.

    @type op: an OpCode instance
    @param op: the opcode to be executed
    @type cbs: L{OpExecCbBase}
    @param cbs: Runtime callbacks
    @type timeout: float or None
    @param timeout: Maximum time to acquire all locks, None for no timeout
    @raise LockAcquireTimeout: In case locks couldn't be acquired in specified
        amount of time

    """
        if not isinstance(op, opcodes.OpCode):
            raise errors.ProgrammerError("Non-opcode instance passed"
                                         " to ExecOpcode (%s)" % type(op))

        lu_class = self.DISPATCH_TABLE.get(op.__class__, None)
        if lu_class is None:
            raise errors.OpCodeUnknown("Unknown opcode")

        if timeout is None:
            calc_timeout = lambda: None
        else:
            calc_timeout = utils.RunningTimeout(timeout, False).Remaining

        self._cbs = cbs
        try:
            if self._enable_locks:
                # Acquire the Big Ganeti Lock exclusively if this LU requires it,
                # and in a shared fashion otherwise (to prevent concurrent run with
                # an exclusive LU.
                self._AcquireLocks(locking.LEVEL_CLUSTER, locking.BGL,
                                   not lu_class.REQ_BGL, False, calc_timeout())
            elif lu_class.REQ_BGL:
                raise errors.ProgrammerError(
                    "Opcode '%s' requires BGL, but locks are"
                    " disabled" % op.OP_ID)

            lu = lu_class(self, op, self.cfg, self.rpc, self._wconfdcontext,
                          self.wconfd)
            lu.wconfdlocks = self.wconfd.Client().ListLocks(
                self._wconfdcontext)
            _CheckSecretParameters(op)
            lu.ExpandNames()
            assert lu.needed_locks is not None, "needed_locks not set by LU"

            try:
                result = self._LockAndExecLU(lu, locking.LEVEL_CLUSTER + 1,
                                             calc_timeout)
            finally:
                if self._ec_id:
                    self.cfg.DropECReservations(self._ec_id)
        finally:
            self.wconfd.Client().FreeLocksLevel(
                self._wconfdcontext,
                locking.LEVEL_NAMES[locking.LEVEL_CLUSTER])
            self._cbs = None

        self._CheckLUResult(op, result)

        return result