def test_task_execution_write_conflict(self): initial = wf_db_models.TaskExecutionDB() initial.workflow_execution = uuid.uuid4().hex initial.task_name = "t1" initial.task_id = "t1" initial.task_route = 0 initial.task_spec = {"tasks": {"t1": "some task"}} initial.delay = 180 initial.status = "requested" initial.context = {"var1": "foobar"} # Prep record created = wf_db_access.TaskExecution.add_or_update(initial) self.assertEqual(initial.rev, 1) doc_id = created.id # Get two separate instances of the document. retrieved1 = wf_db_access.TaskExecution.get_by_id(doc_id) retrieved2 = wf_db_access.TaskExecution.get_by_id(doc_id) # Test update on instance 1, expect success status = "running" retrieved1 = wf_db_access.TaskExecution.update(retrieved1, status=status) updated = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertNotEqual(created.rev, updated.rev) self.assertEqual(retrieved1.rev, updated.rev) self.assertEqual(updated.workflow_execution, retrieved1.workflow_execution) self.assertEqual(updated.task_name, retrieved1.task_name) self.assertEqual(updated.task_id, retrieved1.task_id) self.assertEqual(updated.task_route, retrieved1.task_route) self.assertDictEqual(updated.task_spec, retrieved1.task_spec) self.assertEqual(updated.delay, retrieved1.delay) self.assertEqual(updated.itemized, retrieved1.itemized) self.assertEqual(updated.status, retrieved1.status) self.assertIsNotNone(updated.start_timestamp) self.assertIsNone(updated.end_timestamp) self.assertDictEqual(updated.context, retrieved1.context) # Test update on instance 2, expect race error self.assertRaises( db_exc.StackStormDBObjectWriteConflictError, wf_db_access.TaskExecution.update, retrieved2, status="pausing", ) # Test delete created.delete() self.assertRaises( db_exc.StackStormDBObjectNotFoundError, wf_db_access.TaskExecution.get_by_id, doc_id, )
def test_task_execution_write_conflict(self): initial = wf_db_models.TaskExecutionDB() initial.workflow_execution = uuid.uuid4().hex initial.task_name = 't1' initial.task_id = 't1' initial.task_spec = {'tasks': {'t1': 'some task'}} initial.status = 'requested' initial.initial_context = {'var1': 'foobar'} # Prep record created = wf_db_access.TaskExecution.add_or_update(initial) self.assertEqual(initial.rev, 1) doc_id = created.id # Get two separate instances of the document. retrieved1 = wf_db_access.TaskExecution.get_by_id(doc_id) retrieved2 = wf_db_access.TaskExecution.get_by_id(doc_id) # Test update on instance 1, expect success status = 'running' retrieved1 = wf_db_access.TaskExecution.update(retrieved1, status=status) updated = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertNotEqual(created.rev, updated.rev) self.assertEqual(retrieved1.rev, updated.rev) self.assertEqual(updated.workflow_execution, retrieved1.workflow_execution) self.assertEqual(updated.task_name, retrieved1.task_name) self.assertEqual(updated.task_id, retrieved1.task_id) self.assertDictEqual(updated.task_spec, retrieved1.task_spec) self.assertEqual(updated.status, retrieved1.status) self.assertIsNotNone(updated.start_timestamp) self.assertIsNone(updated.end_timestamp) self.assertDictEqual(updated.initial_context, retrieved1.initial_context) # Test update on instance 2, expect race error self.assertRaises(db_exc.StackStormDBObjectWriteConflictError, wf_db_access.TaskExecution.update, retrieved2, status='pausing') # Test delete created.delete() self.assertRaises(db_exc.StackStormDBObjectNotFoundError, wf_db_access.TaskExecution.get_by_id, doc_id)
def request_task_execution(wf_ex_db, task_id, task_spec, task_ctx, st2_ctx): wf_ac_ex_id = wf_ex_db.action_execution LOG.info('[%s] Processing task execution request for "%s".', wf_ac_ex_id, task_id) # Create a record for task execution. task_ex_db = wf_db_models.TaskExecutionDB( workflow_execution=str(wf_ex_db.id), task_name=task_spec.name or task_id, task_id=task_id, task_spec=task_spec.serialize(), context=task_ctx, status=states.REQUESTED) # Insert new record into the database. task_ex_db = wf_db_access.TaskExecution.insert(task_ex_db, publish=False) task_ex_id = str(task_ex_db.id) LOG.info('[%s] Task execution "%s" created for task "%s".', wf_ac_ex_id, task_ex_id, task_id) try: # Return here if no action is specified in task spec. if task_spec.action is None: # Set the task execution to running. task_ex_db.status = states.RUNNING task_ex_db = wf_db_access.TaskExecution.update(task_ex_db, publish=False) # Fast forward task execution to completion. update_task_execution(str(task_ex_db.id), states.SUCCEEDED) update_task_flow(str(task_ex_db.id), publish=False) # Refresh and return the task execution return wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) # Identify the action to execute. action_db = action_utils.get_action_by_ref(ref=task_spec.action) if not action_db: error = 'Unable to find action "%s".' % task_spec.action raise ac_exc.InvalidActionReferencedException(error) # Identify the runner for the action. runner_type_db = action_utils.get_runnertype_by_name( action_db.runner_type['name']) # Set context for the action execution. ac_ex_ctx = { 'parent': st2_ctx, 'orquesta': { 'workflow_execution_id': str(wf_ex_db.id), 'task_execution_id': str(task_ex_db.id), 'task_name': task_spec.name or task_id, 'task_id': task_id } } # Render action execution parameters and setup action execution object. ac_ex_params = param_utils.render_live_params( runner_type_db.runner_parameters or {}, action_db.parameters or {}, getattr(task_spec, 'input', None) or {}, ac_ex_ctx) lv_ac_db = lv_db_models.LiveActionDB(action=task_spec.action, workflow_execution=str( wf_ex_db.id), task_execution=str(task_ex_db.id), context=ac_ex_ctx, parameters=ac_ex_params) # Set the task execution to running first otherwise a race can occur # where the action execution finishes first and the completion handler # conflicts with this status update. task_ex_db.status = states.RUNNING task_ex_db = wf_db_access.TaskExecution.update(task_ex_db, publish=False) # Request action execution. lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) msg = '[%s] Action execution "%s" requested for task "%s".' LOG.info(msg, wf_ac_ex_id, str(ac_ex_db.id), task_id) except Exception as e: LOG.exception('[%s] Failed task execution for task "%s".', wf_ac_ex_id, task_id) result = { 'errors': [{ 'message': str(e), 'task_id': task_ex_db.task_id }] } update_task_execution(str(task_ex_db.id), states.FAILED, result) raise e return task_ex_db
def request_task_execution(wf_ex_db, st2_ctx, task_ex_req): wf_ac_ex_id = wf_ex_db.action_execution task_id = task_ex_req['id'] task_route = task_ex_req['route'] task_spec = task_ex_req['spec'] task_ctx = task_ex_req['ctx'] task_actions = task_ex_req['actions'] task_delay = task_ex_req.get('delay') msg = '[%s] Processing task execution request for task "%s", route "%s".' LOG.info(msg, wf_ac_ex_id, task_id, str(task_route)) # Use existing task execution when task is with items and still running. task_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id), task_id=task_id, task_route=task_route, order_by=['-start_timestamp']) if (len(task_ex_dbs) > 0 and task_ex_dbs[0].itemized and task_ex_dbs[0].status == ac_const.LIVEACTION_STATUS_RUNNING): task_ex_db = task_ex_dbs[0] task_ex_id = str(task_ex_db.id) msg = '[%s] Task execution "%s" retrieved for task "%s", route "%s".' LOG.info(msg, wf_ac_ex_id, task_ex_id, task_id, str(task_route)) else: # Create a record for task execution. task_ex_db = wf_db_models.TaskExecutionDB( workflow_execution=str(wf_ex_db.id), task_name=task_spec.name or task_id, task_id=task_id, task_route=task_route, task_spec=task_spec.serialize(), delay=task_delay, itemized=task_spec.has_items(), items_count=task_ex_req.get('items_count'), items_concurrency=task_ex_req.get('concurrency'), context=task_ctx, status=statuses.REQUESTED) # Prepare the result format for itemized task execution. if task_ex_db.itemized: task_ex_db.result = {'items': [None] * task_ex_db.items_count} # Insert new record into the database. task_ex_db = wf_db_access.TaskExecution.insert(task_ex_db, publish=False) task_ex_id = str(task_ex_db.id) msg = '[%s] Task execution "%s" created for task "%s", route "%s".' LOG.info(msg, wf_ac_ex_id, task_ex_id, task_id, str(task_route)) try: # Return here if no action is specified in task spec. if task_spec.action is None: msg = '[%s] Task "%s", route "%s", is action less and succeed by default.' LOG.info(msg, wf_ac_ex_id, task_id, str(task_route)) # Set the task execution to running. task_ex_db.status = statuses.RUNNING task_ex_db = wf_db_access.TaskExecution.update(task_ex_db, publish=False) # Fast forward task execution to completion. update_task_execution(str(task_ex_db.id), statuses.SUCCEEDED) update_task_state(str(task_ex_db.id), statuses.SUCCEEDED, publish=False) # Refresh and return the task execution return wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) # Return here for task with items but the items list is empty. if task_ex_db.itemized and task_ex_db.items_count == 0: msg = '[%s] Task "%s", route "%s", has no items and succeed by default.' LOG.info(msg, wf_ac_ex_id, task_id, str(task_route)) # Set the task execution to running. task_ex_db.status = statuses.RUNNING task_ex_db = wf_db_access.TaskExecution.update(task_ex_db, publish=False) # Fast forward task execution to completion. update_task_execution(str(task_ex_db.id), statuses.SUCCEEDED) update_task_state(str(task_ex_db.id), statuses.SUCCEEDED, publish=False) # Refresh and return the task execution return wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) # Request action execution for each actions in the task request. for ac_ex_req in task_actions: ac_ex_delay = eval_action_execution_delay(task_ex_req, ac_ex_req, task_ex_db.itemized) request_action_execution(wf_ex_db, task_ex_db, st2_ctx, ac_ex_req, delay=ac_ex_delay) task_ex_db = wf_db_access.TaskExecution.get_by_id( str(task_ex_db.id)) except Exception as e: msg = '[%s] Failed action execution(s) for task "%s", route "%s". %s' LOG.exception(msg, wf_ac_ex_id, task_id, str(task_route), six.text_type(e)) message = '%s: %s' % (type(e).__name__, six.text_type(e)) error = { 'type': 'error', 'message': message, 'task_id': task_id, 'route': task_route } update_task_execution(str(task_ex_db.id), statuses.FAILED, {'errors': [error]}) raise e return task_ex_db
def mock_task_records(self, parent, task_id, task_route=0, completed=True, expired=False, log=True): if not completed and expired: raise ValueError( "Task must be set completed=True if expired=True.") status = (ac_const.LIVEACTION_STATUS_SUCCEEDED if completed else ac_const.LIVEACTION_STATUS_RUNNING) parent_wf_ex_db, parent_ac_ex_db = parent[0], parent[2] # Identify end timestamp gc_max_idle = cfg.CONF.workflow_engine.gc_max_idle_sec utc_now_dt = date_utils.get_datetime_utc_now() expiry_dt = utc_now_dt - datetime.timedelta(seconds=gc_max_idle + 10) end_timestamp = expiry_dt if expired else utc_now_dt # Assign metadata. action_ref = "core.local" runner = "local-shell-cmd" user = "******" # Create the TaskExecutionDB record first since the ID needs to be # included in the LiveActionDB and ActionExecutionDB records. tk_ex_db = wf_db_models.TaskExecutionDB( workflow_execution=str(parent_wf_ex_db.id), task_id=task_id, task_route=0, status=status, start_timestamp=parent_wf_ex_db.start_timestamp, ) if status in ac_const.LIVEACTION_COMPLETED_STATES: tk_ex_db.end_timestamp = end_timestamp if expired else utc_now_dt tk_ex_db = wf_db_access.TaskExecution.insert(tk_ex_db, publish=False) # Build context for LiveActionDB and ActionExecutionDB. context = { "user": user, "orquesta": { "task_id": tk_ex_db.task_id, "task_name": tk_ex_db.task_id, "workflow_execution_id": str(parent_wf_ex_db.id), "task_execution_id": str(tk_ex_db.id), "task_route": tk_ex_db.task_route, }, "parent": { "user": user, "execution_id": str(parent_ac_ex_db.id) }, } # Create the LiveActionDB record. lv_ac_db = lv_db_models.LiveActionDB( workflow_execution=str(parent_wf_ex_db.id), task_execution=str(tk_ex_db.id), action=action_ref, action_is_workflow=False, context=context, status=status, start_timestamp=tk_ex_db.start_timestamp, end_timestamp=tk_ex_db.end_timestamp, ) lv_ac_db = lv_db_access.LiveAction.insert(lv_ac_db, publish=False) # Create the ActionExecutionDB record. ac_ex_db = ex_db_models.ActionExecutionDB( workflow_execution=str(parent_wf_ex_db.id), task_execution=str(tk_ex_db.id), action={ "runner_type": runner, "ref": action_ref }, runner={"name": runner}, liveaction={"id": str(lv_ac_db.id)}, context=context, status=status, start_timestamp=tk_ex_db.start_timestamp, end_timestamp=tk_ex_db.end_timestamp, ) if log: ac_ex_db.log = [{ "status": "running", "timestamp": tk_ex_db.start_timestamp }] if log and status in ac_const.LIVEACTION_COMPLETED_STATES: ac_ex_db.log.append({ "status": status, "timestamp": tk_ex_db.end_timestamp }) ac_ex_db = ex_db_access.ActionExecution.insert(ac_ex_db, publish=False) return tk_ex_db, lv_ac_db, ac_ex_db
def test_task_execution_crud(self): initial = wf_db_models.TaskExecutionDB() initial.workflow_execution = uuid.uuid4().hex initial.task_name = 't1' initial.task_id = 't1' initial.task_spec = {'tasks': {'t1': 'some task'}} initial.status = 'requested' initial.initial_context = {'var1': 'foobar'} # Test create created = wf_db_access.TaskExecution.add_or_update(initial) self.assertEqual(initial.rev, 1) doc_id = created.id # Test read retrieved = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertEqual(created.workflow_execution, retrieved.workflow_execution) self.assertEqual(created.task_name, retrieved.task_name) self.assertEqual(created.task_id, retrieved.task_id) self.assertDictEqual(created.task_spec, retrieved.task_spec) self.assertEqual(created.status, retrieved.status) self.assertIsNotNone(created.start_timestamp) self.assertIsNone(created.end_timestamp) self.assertDictEqual(created.initial_context, retrieved.initial_context) # Test update status = 'running' retrieved = wf_db_access.TaskExecution.update(retrieved, status=status) updated = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertNotEqual(created.rev, updated.rev) self.assertEqual(retrieved.rev, updated.rev) self.assertEqual(updated.workflow_execution, retrieved.workflow_execution) self.assertEqual(updated.task_name, retrieved.task_name) self.assertEqual(updated.task_id, retrieved.task_id) self.assertDictEqual(updated.task_spec, retrieved.task_spec) self.assertEqual(updated.status, retrieved.status) self.assertIsNotNone(updated.start_timestamp) self.assertIsNone(updated.end_timestamp) self.assertDictEqual(updated.initial_context, retrieved.initial_context) # Test add or update retrieved.result = {'output': 'fubar'} retrieved.status = 'succeeded' retrieved.end_timestamp = date_utils.get_datetime_utc_now() retrieved = wf_db_access.TaskExecution.add_or_update(retrieved) updated = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertNotEqual(created.rev, updated.rev) self.assertEqual(retrieved.rev, updated.rev) self.assertEqual(updated.workflow_execution, retrieved.workflow_execution) self.assertEqual(updated.task_name, retrieved.task_name) self.assertEqual(updated.task_id, retrieved.task_id) self.assertDictEqual(updated.task_spec, retrieved.task_spec) self.assertEqual(updated.status, retrieved.status) self.assertIsNotNone(updated.start_timestamp) self.assertIsNotNone(updated.end_timestamp) self.assertDictEqual(updated.initial_context, retrieved.initial_context) self.assertDictEqual(updated.result, retrieved.result) # Test delete created.delete() self.assertRaises(db_exc.StackStormDBObjectNotFoundError, wf_db_access.TaskExecution.get_by_id, doc_id)
def mock_task_records(self, parent, task_id, task_route=0, completed=True, expired=False, log=True): if not completed and expired: raise ValueError( 'Task must be set completed=True if expired=True.') status = (ac_const.LIVEACTION_STATUS_SUCCEEDED if completed else ac_const.LIVEACTION_STATUS_RUNNING) parent_wf_ex_db, parent_ac_ex_db = parent[0], parent[2] # Identify end timestamp gc_max_idle = cfg.CONF.workflow_engine.gc_max_idle_sec utc_now_dt = date_utils.get_datetime_utc_now() expiry_dt = utc_now_dt - datetime.timedelta(seconds=gc_max_idle + 10) end_timestamp = expiry_dt if expired else utc_now_dt # Assign metadata. action_ref = 'core.local' runner = 'local-shell-cmd' user = '******' # Create the TaskExecutionDB record first since the ID needs to be # included in the LiveActionDB and ActionExecutionDB records. tk_ex_db = wf_db_models.TaskExecutionDB( workflow_execution=str(parent_wf_ex_db.id), task_id=task_id, task_route=0, status=status, start_timestamp=parent_wf_ex_db.start_timestamp) if status in ac_const.LIVEACTION_COMPLETED_STATES: tk_ex_db.end_timestamp = end_timestamp if expired else utc_now_dt tk_ex_db = wf_db_access.TaskExecution.insert(tk_ex_db, publish=False) # Build context for LiveActionDB and ActionExecutionDB. context = { 'user': user, 'orquesta': { 'task_id': tk_ex_db.task_id, 'task_name': tk_ex_db.task_id, 'workflow_execution_id': str(parent_wf_ex_db.id), 'task_execution_id': str(tk_ex_db.id), 'task_route': tk_ex_db.task_route }, 'parent': { 'user': user, 'execution_id': str(parent_ac_ex_db.id) } } # Create the LiveActionDB record. lv_ac_db = lv_db_models.LiveActionDB( workflow_execution=str(parent_wf_ex_db.id), task_execution=str(tk_ex_db.id), action=action_ref, action_is_workflow=False, context=context, status=status, start_timestamp=tk_ex_db.start_timestamp, end_timestamp=tk_ex_db.end_timestamp) lv_ac_db = lv_db_access.LiveAction.insert(lv_ac_db, publish=False) # Create the ActionExecutionDB record. ac_ex_db = ex_db_models.ActionExecutionDB( workflow_execution=str(parent_wf_ex_db.id), task_execution=str(tk_ex_db.id), action={ 'runner_type': runner, 'ref': action_ref }, runner={'name': runner}, liveaction={'id': str(lv_ac_db.id)}, context=context, status=status, start_timestamp=tk_ex_db.start_timestamp, end_timestamp=tk_ex_db.end_timestamp) if log: ac_ex_db.log = [{ 'status': 'running', 'timestamp': tk_ex_db.start_timestamp }] if log and status in ac_const.LIVEACTION_COMPLETED_STATES: ac_ex_db.log.append({ 'status': status, 'timestamp': tk_ex_db.end_timestamp }) ac_ex_db = ex_db_access.ActionExecution.insert(ac_ex_db, publish=False) return tk_ex_db, lv_ac_db, ac_ex_db
def test_task_execution_crud(self): initial = wf_db_models.TaskExecutionDB() initial.workflow_execution = uuid.uuid4().hex initial.task_name = "t1" initial.task_id = "t1" initial.task_route = 0 initial.task_spec = {"tasks": {"t1": "some task"}} initial.delay = 180 initial.status = "requested" initial.context = {"var1": "foobar"} # Test create created = wf_db_access.TaskExecution.add_or_update(initial) self.assertEqual(initial.rev, 1) doc_id = created.id # Test read retrieved = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertEqual(created.workflow_execution, retrieved.workflow_execution) self.assertEqual(created.task_name, retrieved.task_name) self.assertEqual(created.task_id, retrieved.task_id) self.assertEqual(created.task_route, retrieved.task_route) self.assertDictEqual(created.task_spec, retrieved.task_spec) self.assertEqual(created.delay, retrieved.delay) self.assertFalse(created.itemized) self.assertEqual(created.status, retrieved.status) self.assertIsNotNone(created.start_timestamp) self.assertIsNone(created.end_timestamp) self.assertDictEqual(created.context, retrieved.context) # Test update status = "running" retrieved = wf_db_access.TaskExecution.update(retrieved, status=status) updated = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertNotEqual(created.rev, updated.rev) self.assertEqual(retrieved.rev, updated.rev) self.assertEqual(updated.workflow_execution, retrieved.workflow_execution) self.assertEqual(updated.task_name, retrieved.task_name) self.assertEqual(updated.task_id, retrieved.task_id) self.assertEqual(updated.task_route, retrieved.task_route) self.assertDictEqual(updated.task_spec, retrieved.task_spec) self.assertEqual(updated.delay, retrieved.delay) self.assertEqual(updated.itemized, retrieved.itemized) self.assertEqual(updated.status, retrieved.status) self.assertIsNotNone(updated.start_timestamp) self.assertIsNone(updated.end_timestamp) self.assertDictEqual(updated.context, retrieved.context) # Test add or update retrieved.result = {"output": "fubar"} retrieved.status = "succeeded" retrieved.end_timestamp = date_utils.get_datetime_utc_now() retrieved = wf_db_access.TaskExecution.add_or_update(retrieved) updated = wf_db_access.TaskExecution.get_by_id(doc_id) self.assertNotEqual(created.rev, updated.rev) self.assertEqual(retrieved.rev, updated.rev) self.assertEqual(updated.workflow_execution, retrieved.workflow_execution) self.assertEqual(updated.task_name, retrieved.task_name) self.assertEqual(updated.task_id, retrieved.task_id) self.assertEqual(updated.task_route, retrieved.task_route) self.assertDictEqual(updated.task_spec, retrieved.task_spec) self.assertEqual(updated.delay, retrieved.delay) self.assertEqual(updated.itemized, retrieved.itemized) self.assertEqual(updated.status, retrieved.status) self.assertIsNotNone(updated.start_timestamp) self.assertIsNotNone(updated.end_timestamp) self.assertDictEqual(updated.context, retrieved.context) self.assertDictEqual(updated.result, retrieved.result) # Test delete created.delete() self.assertRaises( db_exc.StackStormDBObjectNotFoundError, wf_db_access.TaskExecution.get_by_id, doc_id, )
def request_task_execution(wf_ex_db, st2_ctx, task_req): wf_ac_ex_id = wf_ex_db.action_execution task_id = task_req['id'] task_spec = task_req['spec'] task_ctx = task_req['ctx'] task_actions = task_req['actions'] LOG.info('[%s] Processing task execution request for "%s".', wf_ac_ex_id, task_id) # Use existing task execution when task is with items and still running. task_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id), task_id=task_id, order_by=['-start_timestamp']) if (len(task_ex_dbs) > 0 and task_ex_dbs[0].itemized and task_ex_dbs[0].status == ac_const.LIVEACTION_STATUS_RUNNING): task_ex_db = task_ex_dbs[0] task_ex_id = str(task_ex_db.id) msg = '[%s] Task execution "%s" retrieved for task "%s".' LOG.info(msg, wf_ac_ex_id, task_ex_id, task_id) else: # Create a record for task execution. task_ex_db = wf_db_models.TaskExecutionDB( workflow_execution=str(wf_ex_db.id), task_name=task_spec.name or task_id, task_id=task_id, task_spec=task_spec.serialize(), itemized=task_spec.has_items(), context=task_ctx, status=states.REQUESTED) # Prepare the result format for itemized task execution. if task_ex_db.itemized: task_ex_db.result = {'items': [None] * task_req['items_count']} # Insert new record into the database. task_ex_db = wf_db_access.TaskExecution.insert(task_ex_db, publish=False) task_ex_id = str(task_ex_db.id) msg = '[%s] Task execution "%s" created for task "%s".' LOG.info(msg, wf_ac_ex_id, task_ex_id, task_id) try: # Return here if no action is specified in task spec. if task_spec.action is None: LOG.info('[%s] Task "%s" is action less and succeed by default.', wf_ac_ex_id, task_id) # Set the task execution to running. task_ex_db.status = states.RUNNING task_ex_db = wf_db_access.TaskExecution.update(task_ex_db, publish=False) # Fast forward task execution to completion. update_task_execution(str(task_ex_db.id), states.SUCCEEDED) update_task_flow(str(task_ex_db.id), states.SUCCEEDED, publish=False) # Refresh and return the task execution return wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) # Request action execution for each actions in the task request. for action in task_actions: request_action_execution(wf_ex_db, task_ex_db, st2_ctx, action) task_ex_db = wf_db_access.TaskExecution.get_by_id( str(task_ex_db.id)) except Exception as e: msg = '[%s] Failed action execution(s) for task "%s". %s' LOG.exception(msg, wf_ac_ex_id, task_id, str(e)) result = { 'errors': [{ 'message': str(e), 'task_id': task_ex_db.task_id }] } update_task_execution(str(task_ex_db.id), states.FAILED, result) raise e return task_ex_db