def update_status(liveaction, new_status, result=None, publish=True): if liveaction.status == new_status: return liveaction old_status = liveaction.status liveaction = action_utils.update_liveaction_status( status=new_status, result=result, liveaction_id=liveaction.id, publish=False ) action_execution = executions.update_execution(liveaction) msg = "The status of action execution is changed from %s to %s. " "<LiveAction.id=%s, ActionExecution.id=%s>" % ( old_status, new_status, liveaction.id, action_execution.id, ) extra = {"action_execution_db": action_execution, "liveaction_db": liveaction} LOG.audit(msg, extra=extra) LOG.info(msg) if publish: LiveAction.publish_status(liveaction) return liveaction
def update_status(liveaction, new_status, result=None, publish=True): if liveaction.status == new_status: return liveaction old_status = liveaction.status liveaction = action_utils.update_liveaction_status( status=new_status, result=result, liveaction_id=liveaction.id, publish=False) action_execution = executions.update_execution(liveaction) msg = ('The status of action execution is changed from %s to %s. ' '<LiveAction.id=%s, ActionExecution.id=%s>' % (old_status, new_status, liveaction.id, action_execution.id)) extra = { 'action_execution_db': action_execution, 'liveaction_db': liveaction } LOG.audit(msg, extra=extra) LOG.info(msg) if publish: LiveAction.publish_status(liveaction) return liveaction
def _update_to_scheduled(liveaction_db, execution_queue_item_db): liveaction_id = str(liveaction_db.id) queue_item_id = str(execution_queue_item_db.id) extra = { 'liveaction_id': liveaction_id, 'liveaction_status': liveaction_db.status, 'queue_item_id': queue_item_id } # Update liveaction status to "scheduled". LOG.info('Liveaction (%s) Status Update to Scheduled 1: %s (%s)', liveaction_id, liveaction_db.status, queue_item_id, extra=extra) if liveaction_db.status in [action_constants.LIVEACTION_STATUS_REQUESTED, action_constants.LIVEACTION_STATUS_DELAYED]: liveaction_db = action_service.update_status( liveaction_db, action_constants.LIVEACTION_STATUS_SCHEDULED, publish=False) # Publish the "scheduled" status here manually. Otherwise, there could be a # race condition with the update of the action_execution_db if the execution # of the liveaction completes first. LiveAction.publish_status(liveaction_db) extra['liveaction_status'] = liveaction_db.status # Delete execution queue entry only after status is published. ActionExecutionSchedulingQueue.delete(execution_queue_item_db) LOG.info('Liveaction (%s) Status Update to Scheduled 2: %s (%s)', liveaction_id, liveaction_db.status, queue_item_id)
def update_liveaction_status(status=None, result=None, context=None, end_timestamp=None, liveaction_id=None, runner_info=None, liveaction_db=None, publish=True): """ Update the status of the specified LiveAction to the value provided in new_status. The LiveAction may be specified using either liveaction_id, or as an liveaction_db instance. """ if (liveaction_id is None) and (liveaction_db is None): raise ValueError( 'Must specify an liveaction_id or an liveaction_db when ' 'calling update_LiveAction_status') if liveaction_db is None: liveaction_db = get_liveaction_by_id(liveaction_id) if status not in LIVEACTION_STATUSES: raise ValueError( 'Attempting to set status for LiveAction "%s" ' 'to unknown status string. Unknown status is "%s"', liveaction_db, status) extra = {'liveaction_db': liveaction_db} LOG.debug('Updating ActionExection: "%s" with status="%s"', liveaction_db.id, status, extra=extra) old_status = liveaction_db.status liveaction_db.status = status if result: liveaction_db.result = result if context: liveaction_db.context.update(context) if end_timestamp: liveaction_db.end_timestamp = end_timestamp if runner_info: liveaction_db.runner_info = runner_info liveaction_db = LiveAction.add_or_update(liveaction_db) LOG.debug('Updated status for LiveAction object.', extra=extra) if publish and status != old_status: LiveAction.publish_status(liveaction_db) LOG.debug('Published status for LiveAction object.', extra=extra) return liveaction_db
def update_status(liveaction, new_status, publish=True): if liveaction.status == new_status: return liveaction old_status = liveaction.status liveaction = action_utils.update_liveaction_status( status=new_status, liveaction_id=liveaction.id, publish=False) action_execution = executions.update_execution(liveaction) msg = ('The status of action execution is changed from %s to %s. ' '<LiveAction.id=%s, ActionExecution.id=%s>' % (old_status, new_status, liveaction.id, action_execution.id)) extra = { 'action_execution_db': action_execution, 'liveaction_db': liveaction } LOG.audit(msg, extra=extra) LOG.info(msg) if publish: LiveAction.publish_status(liveaction) return liveaction
def _update_to_scheduled(liveaction_db, execution_queue_item_db): action_execution_id = str(execution_queue_item_db.action_execution_id) liveaction_id = str(execution_queue_item_db.liveaction_id) queue_item_id = str(execution_queue_item_db.id) extra = {'queue_item_id': queue_item_id} # Update liveaction status to "scheduled". LOG.info( '[%s] Liveaction "%s" with status "%s" is updated to status "scheduled."', action_execution_id, liveaction_id, liveaction_db.status, extra=extra) if liveaction_db.status in [ action_constants.LIVEACTION_STATUS_REQUESTED, action_constants.LIVEACTION_STATUS_DELAYED ]: liveaction_db = action_service.update_status( liveaction_db, action_constants.LIVEACTION_STATUS_SCHEDULED, publish=False) # Publish the "scheduled" status here manually. Otherwise, there could be a # race condition with the update of the action_execution_db if the execution # of the liveaction completes first. LiveAction.publish_status(liveaction_db) # Delete execution queue entry only after status is published. ActionExecutionSchedulingQueue.delete(execution_queue_item_db)
def update_liveaction_status( status=None, result=None, context=None, end_timestamp=None, liveaction_id=None, runner_info=None, liveaction_db=None, publish=True, ): """ Update the status of the specified LiveAction to the value provided in new_status. The LiveAction may be specified using either liveaction_id, or as an liveaction_db instance. """ if (liveaction_id is None) and (liveaction_db is None): raise ValueError("Must specify an liveaction_id or an liveaction_db when " "calling update_LiveAction_status") if liveaction_db is None: liveaction_db = get_liveaction_by_id(liveaction_id) if status not in LIVEACTION_STATUSES: raise ValueError( 'Attempting to set status for LiveAction "%s" ' 'to unknown status string. Unknown status is "%s"', liveaction_db, status, ) extra = {"liveaction_db": liveaction_db} LOG.debug('Updating ActionExection: "%s" with status="%s"', liveaction_db.id, status, extra=extra) old_status = liveaction_db.status liveaction_db.status = status if result: liveaction_db.result = result if context: liveaction_db.context.update(context) if end_timestamp: liveaction_db.end_timestamp = end_timestamp if runner_info: liveaction_db.runner_info = runner_info liveaction_db = LiveAction.add_or_update(liveaction_db) LOG.debug("Updated status for LiveAction object.", extra=extra) if publish and status != old_status: LiveAction.publish_status(liveaction_db) LOG.debug("Published status for LiveAction object.", extra=extra) return liveaction_db
def process(self, request): """Schedules the LiveAction and publishes the request to the appropriate action runner(s). LiveAction in statuses other than "requested" are ignored. :param request: Action execution request. :type request: ``st2common.models.db.liveaction.LiveActionDB`` """ if request.status != action_constants.LIVEACTION_STATUS_REQUESTED: LOG.info( '%s is ignoring %s (id=%s) with "%s" status.', self.__class__.__name__, type(request), request.id, request.status, ) return try: liveaction_db = action_utils.get_liveaction_by_id(request.id) except StackStormDBObjectNotFoundError: LOG.exception("Failed to find liveaction %s in the database.", request.id) raise # Apply policies defined for the action. liveaction_db = self._apply_pre_run_policies(liveaction_db=liveaction_db) # Exit if the status of the request is no longer runnable. # The status could have be changed by one of the policies. if liveaction_db.status not in [ action_constants.LIVEACTION_STATUS_REQUESTED, action_constants.LIVEACTION_STATUS_SCHEDULED, ]: LOG.info( '%s is ignoring %s (id=%s) with "%s" status after policies are applied.', self.__class__.__name__, type(request), request.id, liveaction_db.status, ) return # Update liveaction status to "scheduled". if liveaction_db.status == action_constants.LIVEACTION_STATUS_REQUESTED: liveaction_db = action_service.update_status( liveaction_db, action_constants.LIVEACTION_STATUS_SCHEDULED, publish=False ) # Publish the "scheduled" status here manually. Otherwise, there could be a # race condition with the update of the action_execution_db if the execution # of the liveaction completes first. LiveAction.publish_status(liveaction_db)
def test_no_double_entries(self): self.reset() liveaction_db = self._create_liveaction_db() LiveAction.publish_status(liveaction_db) LiveAction.publish_status(liveaction_db) schedule_q_db = self.scheduling_queue._get_next_execution() self.assertIsNotNone(schedule_q_db) schedule_q_db = self.scheduling_queue._get_next_execution() self.assertIsNone(schedule_q_db)
def test_no_processing_of_non_requested_actions(self): self.reset() for status in action_constants.LIVEACTION_STATUSES: liveaction_db = self._create_liveaction_db(status=status) LiveAction.publish_status(liveaction_db) schedule_q_db = self.scheduling_queue._get_next_execution() if status is action_constants.LIVEACTION_STATUS_REQUESTED: self.assertIsNotNone(schedule_q_db) else: self.assertIsNone(schedule_q_db)
def process(self, request): """Schedules the LiveAction and publishes the request to the appropriate action runner(s). LiveAction in statuses other than "requested" are ignored. :param request: Action execution request. :type request: ``st2common.models.db.liveaction.LiveActionDB`` """ if request.status != action_constants.LIVEACTION_STATUS_REQUESTED: LOG.info('%s is ignoring %s (id=%s) with "%s" status.', self.__class__.__name__, type(request), request.id, request.status) return try: liveaction_db = action_utils.get_liveaction_by_id(request.id) except StackStormDBObjectNotFoundError: LOG.exception('Failed to find liveaction %s in the database.', request.id) raise # Apply policies defined for the action. liveaction_db = self._apply_pre_run_policies( liveaction_db=liveaction_db) # Exit if the status of the request is no longer runnable. # The status could have be changed by one of the policies. if liveaction_db.status not in [ action_constants.LIVEACTION_STATUS_REQUESTED, action_constants.LIVEACTION_STATUS_SCHEDULED ]: LOG.info( '%s is ignoring %s (id=%s) with "%s" status after policies are applied.', self.__class__.__name__, type(request), request.id, liveaction_db.status) return # Update liveaction status to "scheduled". if liveaction_db.status == action_constants.LIVEACTION_STATUS_REQUESTED: liveaction_db = action_service.update_status( liveaction_db, action_constants.LIVEACTION_STATUS_SCHEDULED, publish=False) # Publish the "scheduled" status here manually. Otherwise, there could be a # race condition with the update of the action_execution_db if the execution # of the liveaction completes first. LiveAction.publish_status(liveaction_db)
def update_status( liveaction, new_status, result=None, publish=True, set_result_size=False, context=None, ): if liveaction.status == new_status: return liveaction old_status = liveaction.status updates = { "liveaction_id": liveaction.id, "status": new_status, "result": result, "publish": False, "context": context, } if new_status in action_constants.LIVEACTION_COMPLETED_STATES: updates["end_timestamp"] = date_utils.get_datetime_utc_now() liveaction = action_utils.update_liveaction_status(**updates) action_execution = executions.update_execution( liveaction, set_result_size=set_result_size) msg = ("The status of action execution is changed from %s to %s. " "<LiveAction.id=%s, ActionExecution.id=%s>" % (old_status, new_status, liveaction.id, action_execution.id)) extra = { "action_execution_db": action_execution, "liveaction_db": liveaction } LOG.audit(msg, extra=extra) LOG.info(msg) # Invoke post run if liveaction status is completed or paused. if (new_status in action_constants.LIVEACTION_COMPLETED_STATES or new_status == action_constants.LIVEACTION_STATUS_PAUSED): runners_utils.invoke_post_run(liveaction) if publish: LiveAction.publish_status(liveaction) return liveaction
def test_processing_when_task_completed(self, mock_execution_queue_delete, mock_action_service): self.reset() liveaction_db = self._create_liveaction_db() LiveAction.publish_status(liveaction_db) liveaction_db.status = action_constants.LIVEACTION_STATUS_CANCELED LiveAction.add_or_update(liveaction_db) schedule_q_db = self.scheduling_queue._get_next_execution() scheduling_queue.get_handler()._handle_execution(schedule_q_db) mock_action_service.update_status.assert_not_called() mock_execution_queue_delete.assert_called_once() ActionExecutionSchedulingQueue.delete(schedule_q_db)
def publish_request(liveaction, execution): """ Publish an action execution. :return: (liveaction, execution) :rtype: tuple """ # Assume that this is a creation. LiveAction.publish_create(liveaction) LiveAction.publish_status(liveaction) ActionExecution.publish_create(execution) extra = {'liveaction_db': liveaction, 'execution_db': execution} LOG.audit('Action execution requested. LiveAction.id=%s, ActionExecution.id=%s' % (liveaction.id, execution.id), extra=extra) return liveaction, execution
def publish_request(liveaction, execution): """ Publish an action execution. :return: (liveaction, execution) :rtype: tuple """ # Assume that this is a creation. LiveAction.publish_create(liveaction) LiveAction.publish_status(liveaction) ActionExecution.publish_create(execution) # TODO: This results in two queries, optimize it # extra = {'liveaction_db': liveaction, 'execution_db': execution} extra = {} LOG.audit('Action execution requested. LiveAction.id=%s, ActionExecution.id=%s' % (liveaction.id, execution.id), extra=extra) return liveaction, execution
def process(self, request): """Schedules the LiveAction and publishes the request to the appropriate action runner(s). LiveAction in statuses other than "requested" are ignored. :param request: Action execution request. :type request: ``st2common.models.db.liveaction.LiveActionDB`` """ if request.status != action_constants.LIVEACTION_STATUS_REQUESTED: LOG.info('%s is ignoring %s (id=%s) with "%s" status.', self.__class__.__name__, type(request), request.id, request.status) return try: liveaction_db = action_utils.get_liveaction_by_id(request.id) except StackStormDBObjectNotFoundError: LOG.exception('Failed to find liveaction %s in the database.', request.id) raise # Update liveaction status to "scheduled" liveaction_db = action_utils.update_liveaction_status( status=action_constants.LIVEACTION_STATUS_SCHEDULED, liveaction_id=liveaction_db.id, publish=False) action_execution_db = executions.update_execution(liveaction_db) # Publish the "scheduled" status here manually. Otherwise, there could be a # race condition with the update of the action_execution_db if the execution # of the liveaction completes first. LiveAction.publish_status(liveaction_db) extra = {'action_execution_db': action_execution_db, 'liveaction_db': liveaction_db} LOG.audit('Scheduled action execution.', extra=extra) # the extra field will not be shown in non-audit logs so temporarily log at info. LOG.info('Scheduled {~}action_execution: %s / {~}live_action: %s with "%s" status.', action_execution_db.id, liveaction_db.id, request.status)
def update_status(liveaction, new_status, result=None, publish=True): if liveaction.status == new_status: return liveaction old_status = liveaction.status updates = { 'liveaction_id': liveaction.id, 'status': new_status, 'result': result, 'publish': False } if new_status in action_constants.LIVEACTION_COMPLETED_STATES: updates['end_timestamp'] = date_utils.get_datetime_utc_now() liveaction = action_utils.update_liveaction_status(**updates) action_execution = executions.update_execution(liveaction) msg = ('The status of action execution is changed from %s to %s. ' '<LiveAction.id=%s, ActionExecution.id=%s>' % (old_status, new_status, liveaction.id, action_execution.id)) extra = { 'action_execution_db': action_execution, 'liveaction_db': liveaction } LOG.audit(msg, extra=extra) LOG.info(msg) # Invoke post run if liveaction status is completed or paused. if (new_status in action_constants.LIVEACTION_COMPLETED_STATES or new_status == action_constants.LIVEACTION_STATUS_PAUSED): runners_utils.invoke_post_run(liveaction) if publish: LiveAction.publish_status(liveaction) return liveaction
def request(liveaction): """ Request an action execution. :return: (liveaction, execution) :rtype: tuple """ # Use the user context from the parent action execution. Subtasks in a workflow # action can be invoked by a system user and so we want to use the user context # from the original workflow action. if getattr(liveaction, "context", None) and "parent" in liveaction.context: parent_user = liveaction.context["parent"].get("user", None) if parent_user: liveaction.context["user"] = parent_user # Validate action. action_db = action_utils.get_action_by_ref(liveaction.action) if not action_db: raise ValueError('Action "%s" cannot be found.' % liveaction.action) if not action_db.enabled: raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action) runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type["name"]) if not hasattr(liveaction, "parameters"): liveaction.parameters = dict() # Validate action parameters. schema = util_schema.get_parameter_schema(action_db) validator = util_schema.get_validator() util_schema.validate(liveaction.parameters, schema, validator, use_default=True) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. immutables = _get_immutable_params(action_db.parameters) immutables.extend(_get_immutable_params(runnertype_db.runner_parameters)) overridden_immutables = [p for p in six.iterkeys(liveaction.parameters) if p in immutables] if len(overridden_immutables) > 0: raise ValueError("Override of immutable parameter(s) %s is unsupported." % str(overridden_immutables)) # Set notification settings for action. # XXX: There are cases when we don't want notifications to be sent for a particular # execution. So we should look at liveaction.parameters['notify'] # and not set liveaction.notify. if action_db.notify: liveaction.notify = action_db.notify # Write to database and send to message queue. liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction.start_timestamp = date_utils.get_datetime_utc_now() # Publish creation after both liveaction and actionexecution are created. liveaction = LiveAction.add_or_update(liveaction, publish=False) execution = executions.create_execution_object(liveaction, publish=False) # Assume that this is a creation. LiveAction.publish_create(liveaction) LiveAction.publish_status(liveaction) ActionExecution.publish_create(execution) extra = {"liveaction_db": liveaction, "execution_db": execution} LOG.audit( "Action execution requested. LiveAction.id=%s, ActionExecution.id=%s" % (liveaction.id, execution.id), extra=extra, ) return liveaction, execution
def request(liveaction): """ Request an action execution. :return: (liveaction, execution) :rtype: tuple """ # Use the user context from the parent action execution. Subtasks in a workflow # action can be invoked by a system user and so we want to use the user context # from the original workflow action. if getattr(liveaction, 'context', None) and 'parent' in liveaction.context: parent_user = liveaction.context['parent'].get('user', None) if parent_user: liveaction.context['user'] = parent_user # Validate action. action_db = action_utils.get_action_by_ref(liveaction.action) if not action_db: raise ValueError('Action "%s" cannot be found.' % liveaction.action) if not action_db.enabled: raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action) runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name']) if not hasattr(liveaction, 'parameters'): liveaction.parameters = dict() # Validate action parameters. schema = util_schema.get_parameter_schema(action_db) validator = util_schema.get_validator() util_schema.validate(liveaction.parameters, schema, validator, use_default=True) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. immutables = _get_immutable_params(action_db.parameters) immutables.extend(_get_immutable_params(runnertype_db.runner_parameters)) overridden_immutables = [p for p in six.iterkeys(liveaction.parameters) if p in immutables] if len(overridden_immutables) > 0: raise ValueError('Override of immutable parameter(s) %s is unsupported.' % str(overridden_immutables)) # Set notification settings for action. # XXX: There are cases when we don't want notifications to be sent for a particular # execution. So we should look at liveaction.parameters['notify'] # and not set liveaction.notify. if action_db.notify: liveaction.notify = action_db.notify # Write to database and send to message queue. liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction.start_timestamp = date_utils.get_datetime_utc_now() # Publish creation after both liveaction and actionexecution are created. liveaction = LiveAction.add_or_update(liveaction, publish=False) # Get trace_db if it exists. This could throw. If it throws, we have to cleanup # liveaction object so we don't see things in requested mode. trace_db = None try: _, trace_db = trace_service.get_trace_db_by_live_action(liveaction) except StackStormDBObjectNotFoundError as e: _cleanup_liveaction(liveaction) raise TraceNotFoundException(str(e)) execution = executions.create_execution_object(liveaction, publish=False) if trace_db: trace_service.add_or_update_given_trace_db( trace_db=trace_db, action_executions=[str(execution.id)]) # Assume that this is a creation. LiveAction.publish_create(liveaction) LiveAction.publish_status(liveaction) ActionExecution.publish_create(execution) extra = {'liveaction_db': liveaction, 'execution_db': execution} LOG.audit('Action execution requested. LiveAction.id=%s, ActionExecution.id=%s' % (liveaction.id, execution.id), extra=extra) return liveaction, execution
def update_liveaction_status(status=None, result=None, context=None, end_timestamp=None, liveaction_id=None, runner_info=None, liveaction_db=None, publish=True): """ Update the status of the specified LiveAction to the value provided in new_status. The LiveAction may be specified using either liveaction_id, or as an liveaction_db instance. """ if (liveaction_id is None) and (liveaction_db is None): raise ValueError('Must specify an liveaction_id or an liveaction_db when ' 'calling update_LiveAction_status') if liveaction_db is None: liveaction_db = get_liveaction_by_id(liveaction_id) if status not in LIVEACTION_STATUSES: raise ValueError('Attempting to set status for LiveAction "%s" ' 'to unknown status string. Unknown status is "%s"' % (liveaction_db, status)) if result and cfg.CONF.system.validate_output_schema and status == LIVEACTION_STATUS_SUCCEEDED: action_db = get_action_by_ref(liveaction_db.action) runner_db = get_runnertype_by_name(action_db.runner_type['name']) result, status = output_schema.validate_output( runner_db.output_schema, action_db.output_schema, result, status, runner_db.output_key, ) # If liveaction_db status is set then we need to decrement the counter # because it is transitioning to a new state if liveaction_db.status: get_driver().dec_counter('action.executions.%s' % (liveaction_db.status)) # If status is provided then we need to increment the timer because the action # is transitioning into this new state if status: get_driver().inc_counter('action.executions.%s' % (status)) extra = {'liveaction_db': liveaction_db} LOG.debug('Updating ActionExection: "%s" with status="%s"', liveaction_db.id, status, extra=extra) # If liveaction is already canceled, then do not allow status to be updated. if liveaction_db.status == LIVEACTION_STATUS_CANCELED and status != LIVEACTION_STATUS_CANCELED: LOG.info('Unable to update ActionExecution "%s" with status="%s". ' 'ActionExecution is already canceled.', liveaction_db.id, status, extra=extra) return liveaction_db old_status = liveaction_db.status liveaction_db.status = status if result: liveaction_db.result = result if context: liveaction_db.context.update(context) if end_timestamp: liveaction_db.end_timestamp = end_timestamp if runner_info: liveaction_db.runner_info = runner_info # TODO: This is not efficient. Perform direct partial update and only update # manipulated fields liveaction_db = LiveAction.add_or_update(liveaction_db) LOG.debug('Updated status for LiveAction object.', extra=extra) if publish and status != old_status: LiveAction.publish_status(liveaction_db) LOG.debug('Published status for LiveAction object.', extra=extra) return liveaction_db
def request(liveaction): """ Request an action execution. :return: (liveaction, execution) :rtype: tuple """ # Use the user context from the parent action execution. Subtasks in a workflow # action can be invoked by a system user and so we want to use the user context # from the original workflow action. if getattr(liveaction, 'context', None) and 'parent' in liveaction.context: parent = LiveAction.get_by_id(liveaction.context['parent']) liveaction.context['user'] = getattr(parent, 'context', dict()).get('user') # Validate action. action_db = action_utils.get_action_by_ref(liveaction.action) if not action_db: raise ValueError('Action "%s" cannot be found.' % liveaction.action) if not action_db.enabled: raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action) runnertype_db = action_utils.get_runnertype_by_name( action_db.runner_type['name']) if not hasattr(liveaction, 'parameters'): liveaction.parameters = dict() # Validate action parameters. schema = util_schema.get_parameter_schema(action_db) validator = util_schema.get_validator() util_schema.validate(liveaction.parameters, schema, validator, use_default=True) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. immutables = _get_immutable_params(action_db.parameters) immutables.extend(_get_immutable_params(runnertype_db.runner_parameters)) overridden_immutables = [ p for p in six.iterkeys(liveaction.parameters) if p in immutables ] if len(overridden_immutables) > 0: raise ValueError( 'Override of immutable parameter(s) %s is unsupported.' % str(overridden_immutables)) # Set notification settings for action. # XXX: There are cases when we don't want notifications to be sent for a particular # execution. So we should look at liveaction.parameters['notify'] # and not set liveaction.notify. if action_db.notify: liveaction.notify = action_db.notify # Write to database and send to message queue. liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction.start_timestamp = date_utils.get_datetime_utc_now() # Publish creation after both liveaction and actionexecution are created. liveaction = LiveAction.add_or_update(liveaction, publish=False) execution = executions.create_execution_object(liveaction, publish=False) # Assume that this is a creation. LiveAction.publish_create(liveaction) LiveAction.publish_status(liveaction) ActionExecution.publish_create(execution) extra = {'liveaction_db': liveaction, 'execution_db': execution} LOG.audit( 'Action execution requested. LiveAction.id=%s, ActionExecution.id=%s' % (liveaction.id, execution.id), extra=extra) return liveaction, execution
def update_liveaction_status(status=None, result=None, context=None, end_timestamp=None, liveaction_id=None, runner_info=None, liveaction_db=None, publish=True): """ Update the status of the specified LiveAction to the value provided in new_status. The LiveAction may be specified using either liveaction_id, or as an liveaction_db instance. """ if (liveaction_id is None) and (liveaction_db is None): raise ValueError('Must specify an liveaction_id or an liveaction_db when ' 'calling update_LiveAction_status') if liveaction_db is None: liveaction_db = get_liveaction_by_id(liveaction_id) if status not in LIVEACTION_STATUSES: raise ValueError('Attempting to set status for LiveAction "%s" ' 'to unknown status string. Unknown status is "%s"', liveaction_db, status) # If liveaction_db status is set then we need to decrement the counter # because it is transitioning to a new state if liveaction_db.status: get_driver().dec_counter( format_metrics_key( liveaction_db=liveaction_db, key='action.%s' % liveaction_db.status ) ) # If status is provided then we need to increment the timer because the action # is transitioning into this new state if status: get_driver().inc_counter( format_metrics_key( liveaction_db=liveaction_db, key='action.%s' % status ) ) extra = {'liveaction_db': liveaction_db} LOG.debug('Updating ActionExection: "%s" with status="%s"', liveaction_db.id, status, extra=extra) # If liveaction is already canceled, then do not allow status to be updated. if liveaction_db.status == LIVEACTION_STATUS_CANCELED and status != LIVEACTION_STATUS_CANCELED: LOG.info('Unable to update ActionExecution "%s" with status="%s". ' 'ActionExecution is already canceled.', liveaction_db.id, status, extra=extra) return liveaction_db old_status = liveaction_db.status liveaction_db.status = status if result: liveaction_db.result = result if context: liveaction_db.context.update(context) if end_timestamp: liveaction_db.end_timestamp = end_timestamp if runner_info: liveaction_db.runner_info = runner_info liveaction_db = LiveAction.add_or_update(liveaction_db) LOG.debug('Updated status for LiveAction object.', extra=extra) if publish and status != old_status: LiveAction.publish_status(liveaction_db) LOG.debug('Published status for LiveAction object.', extra=extra) return liveaction_db
def update_liveaction_status( status=None, result=None, context=None, end_timestamp=None, liveaction_id=None, runner_info=None, liveaction_db=None, publish=True, ): """ Update the status of the specified LiveAction to the value provided in new_status. The LiveAction may be specified using either liveaction_id, or as an liveaction_db instance. """ if (liveaction_id is None) and (liveaction_db is None): raise ValueError( "Must specify an liveaction_id or an liveaction_db when " "calling update_LiveAction_status" ) if liveaction_db is None: liveaction_db = get_liveaction_by_id(liveaction_id) if status not in LIVEACTION_STATUSES: raise ValueError( 'Attempting to set status for LiveAction "%s" ' 'to unknown status string. Unknown status is "%s"' % (liveaction_db, status) ) if ( result and cfg.CONF.system.validate_output_schema and status == LIVEACTION_STATUS_SUCCEEDED ): action_db = get_action_by_ref(liveaction_db.action) runner_db = get_runnertype_by_name(action_db.runner_type["name"]) result, status = output_schema.validate_output( runner_db.output_schema, action_db.output_schema, result, status, runner_db.output_key, ) # If liveaction_db status is set then we need to decrement the counter # because it is transitioning to a new state if liveaction_db.status: get_driver().dec_counter("action.executions.%s" % (liveaction_db.status)) # If status is provided then we need to increment the timer because the action # is transitioning into this new state if status: get_driver().inc_counter("action.executions.%s" % (status)) extra = {"liveaction_db": liveaction_db} LOG.debug( 'Updating ActionExection: "%s" with status="%s"', liveaction_db.id, status, extra=extra, ) # If liveaction is already canceled, then do not allow status to be updated. if ( liveaction_db.status == LIVEACTION_STATUS_CANCELED and status != LIVEACTION_STATUS_CANCELED ): LOG.info( 'Unable to update ActionExecution "%s" with status="%s". ' "ActionExecution is already canceled.", liveaction_db.id, status, extra=extra, ) return liveaction_db old_status = liveaction_db.status liveaction_db.status = status if result: liveaction_db.result = result if context: liveaction_db.context.update(context) if end_timestamp: liveaction_db.end_timestamp = end_timestamp if runner_info: liveaction_db.runner_info = runner_info # TODO: This is not efficient. Perform direct partial update and only update # manipulated fields liveaction_db = LiveAction.add_or_update(liveaction_db) LOG.debug("Updated status for LiveAction object.", extra=extra) if publish and status != old_status: LiveAction.publish_status(liveaction_db) LOG.debug("Published status for LiveAction object.", extra=extra) return liveaction_db
def update_liveaction_status(status=None, result=None, context=None, end_timestamp=None, liveaction_id=None, runner_info=None, liveaction_db=None, publish=True): """ Update the status of the specified LiveAction to the value provided in new_status. The LiveAction may be specified using either liveaction_id, or as an liveaction_db instance. """ if (liveaction_id is None) and (liveaction_db is None): raise ValueError('Must specify an liveaction_id or an liveaction_db when ' 'calling update_LiveAction_status') if liveaction_db is None: liveaction_db = get_liveaction_by_id(liveaction_id) if status not in LIVEACTION_STATUSES: raise ValueError('Attempting to set status for LiveAction "%s" ' 'to unknown status string. Unknown status is "%s"', liveaction_db, status) # If liveaction_db status is set then we need to decrement the counter # because it is transitioning to a new state if liveaction_db.status: get_driver().dec_counter('action.executions.%s' % (liveaction_db.status)) # If status is provided then we need to increment the timer because the action # is transitioning into this new state if status: get_driver().inc_counter('action.executions.%s' % (status)) extra = {'liveaction_db': liveaction_db} LOG.debug('Updating ActionExection: "%s" with status="%s"', liveaction_db.id, status, extra=extra) # If liveaction is already canceled, then do not allow status to be updated. if liveaction_db.status == LIVEACTION_STATUS_CANCELED and status != LIVEACTION_STATUS_CANCELED: LOG.info('Unable to update ActionExecution "%s" with status="%s". ' 'ActionExecution is already canceled.', liveaction_db.id, status, extra=extra) return liveaction_db old_status = liveaction_db.status liveaction_db.status = status if result: liveaction_db.result = result if context: liveaction_db.context.update(context) if end_timestamp: liveaction_db.end_timestamp = end_timestamp if runner_info: liveaction_db.runner_info = runner_info liveaction_db = LiveAction.add_or_update(liveaction_db) LOG.debug('Updated status for LiveAction object.', extra=extra) if publish and status != old_status: LiveAction.publish_status(liveaction_db) LOG.debug('Published status for LiveAction object.', extra=extra) return liveaction_db