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
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
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
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
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
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