コード例 #1
0
 def run_it(runner, failed=False, result=None, simulate_run=False):
     try:
         # Add the task to be rolled back *immediately* so that even if
         # the task fails while producing results it will be given a
         # chance to rollback.
         rb = utils.RollbackTask(context, runner.task, result=None)
         self._accumulator.add(rb)
         self.task_notifier.notify(states.STARTED,
                                   details={
                                       'context': context,
                                       'flow': self,
                                       'runner': runner,
                                   })
         if not simulate_run:
             result = runner(context, *args, **kwargs)
         else:
             if failed:
                 # TODO(harlowja): make this configurable??
                 # If we previously failed, we want to fail again at
                 # the same place.
                 if not result:
                     # If no exception or exception message was provided
                     # or captured from the previous run then we need to
                     # form one for this task.
                     result = "%s failed running." % (runner.task)
                 if isinstance(result, basestring):
                     result = exc.InvalidStateException(result)
                 if not isinstance(result, Exception):
                     LOG.warn(
                         "Can not raise a non-exception"
                         " object: %s", result)
                     result = exc.InvalidStateException()
                 raise result
         # Adjust the task result in the accumulator before
         # notifying others that the task has finished to
         # avoid the case where a listener might throw an
         # exception.
         rb.result = result
         runner.result = result
         self.results[runner.uuid] = result
         self.task_notifier.notify(states.SUCCESS,
                                   details={
                                       'context': context,
                                       'flow': self,
                                       'runner': runner,
                                   })
     except Exception as e:
         runner.result = e
         cause = utils.FlowFailure(runner, self, e)
         with excutils.save_and_reraise_exception():
             # Notify any listeners that the task has errored.
             self.task_notifier.notify(states.FAILURE,
                                       details={
                                           'context': context,
                                           'flow': self,
                                           'runner': runner,
                                       })
             self.rollback(context, cause)
コード例 #2
0
ファイル: base.py プロジェクト: twilight327426371/cinder
 def soft_reset(self):
     """Partially resets the internal state of this flow, allowing for the
     flow to be ran again from an interrupted state only.
     """
     if self.state not in self.SOFT_RESETTABLE_STATES:
         raise exc.InvalidStateException(("Can not soft reset when"
                                          " in state %s") % (self.state))
     self._change_state(None, states.PENDING)
コード例 #3
0
ファイル: base.py プロジェクト: twilight327426371/cinder
    def reset(self):
        """Fully resets the internal state of this flow, allowing for the flow
        to be ran again.

        Note: Listeners are also reset.
        """
        if self.state not in self.RESETTABLE_STATES:
            raise exc.InvalidStateException(("Can not reset when"
                                             " in state %s") % (self.state))
        self.notifier.reset()
        self.task_notifier.reset()
        self._change_state(None, states.PENDING)
コード例 #4
0
ファイル: base.py プロジェクト: twilight327426371/cinder
    def interrupt(self):
        """Attempts to interrupt the current flow and any tasks that are
        currently not running in the flow.

        Returns how many tasks were interrupted (if any).
        """
        if self.state in self.UNINTERRUPTIBLE_STATES:
            raise exc.InvalidStateException(("Can not interrupt when"
                                             " in state %s") % (self.state))
        # Note(harlowja): Do *not* acquire the lock here so that the flow may
        # be interrupted while running. This does mean the the above check may
        # not be valid but we can worry about that if it becomes an issue.
        old_state = self.state
        if old_state != states.INTERRUPTED:
            self._state = states.INTERRUPTED
            self.notifier.notify(self.state,
                                 details={
                                     'context': None,
                                     'flow': self,
                                     'old_state': old_state,
                                 })
        return 0
コード例 #5
0
ファイル: base.py プロジェクト: twilight327426371/cinder
 def run(self, context, *args, **kwargs):
     """Executes the workflow."""
     if self.state not in self.RUNNABLE_STATES:
         raise exc.InvalidStateException("Unable to run flow when "
                                         "in state %s" % (self.state))