예제 #1
0
    def test_chain_cancel_cascade_to_subworkflow(self):
        # A temp file is created during test setup. Ensure the temp file exists.
        # The test action chain will stall until this file is deleted. This gives
        # the unit test a moment to run any test related logic.
        path = self.temp_file_path
        self.assertTrue(os.path.exists(path))

        action = TEST_PACK + '.' + 'test_cancel_with_subworkflow'
        params = {'tempfile': path, 'message': 'foobar'}
        liveaction = LiveActionDB(action=action, parameters=params)
        liveaction, execution = action_service.request(liveaction)
        liveaction = LiveAction.get_by_id(str(liveaction.id))

        # Wait until the liveaction is running.
        liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_RUNNING)

        # Wait for subworkflow to register.
        execution = self._wait_for_children(execution)
        self.assertEqual(len(execution.children), 1)

        # Wait until the subworkflow is running.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_on_status(task1_live, action_constants.LIVEACTION_STATUS_RUNNING)

        # Request action chain to cancel.
        liveaction, execution = action_service.request_cancellation(liveaction, USERNAME)

        # Wait until the liveaction is canceling.
        liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_CANCELING)
        self.assertEqual(len(execution.children), 1)

        # Wait until the subworkflow is canceling.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_on_status(task1_live, action_constants.LIVEACTION_STATUS_CANCELING)

        # Delete the temporary file that the action chain is waiting on.
        os.remove(path)
        self.assertFalse(os.path.exists(path))

        # Wait until the liveaction is canceled.
        liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_CANCELED)
        self.assertEqual(len(execution.children), 1)

        # Wait until the subworkflow is canceled.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_on_status(task1_live, action_constants.LIVEACTION_STATUS_CANCELED)

        # Wait for non-blocking threads to complete. Ensure runner is not running.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result.
        self.assertIn('tasks', liveaction.result)
        self.assertEqual(len(liveaction.result['tasks']), 1)

        subworkflow = liveaction.result['tasks'][0]
        self.assertEqual(len(subworkflow['result']['tasks']), 1)
        self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_CANCELED)
예제 #2
0
    def test_crud_partial(self):
        # Create the DB record.
        obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_subtasks[0]))
        ActionExecution.add_or_update(ActionExecutionAPI.to_model(obj))
        model = ActionExecution.get_by_id(obj.id)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(model.trigger, {})
        self.assertDictEqual(model.trigger_type, {})
        self.assertDictEqual(model.trigger_instance, {})
        self.assertDictEqual(model.rule, {})
        self.assertDictEqual(model.action, self.fake_history_subtasks[0]['action'])
        self.assertDictEqual(model.runner, self.fake_history_subtasks[0]['runner'])
        doc = copy.deepcopy(self.fake_history_subtasks[0]['liveaction'])
        doc['start_timestamp'] = doc['start_timestamp']
        doc['end_timestamp'] = doc['end_timestamp']
        self.assertDictEqual(model.liveaction, doc)
        self.assertEqual(model.parent, self.fake_history_subtasks[0]['parent'])
        self.assertListEqual(model.children, [])

        # Update the DB record.
        children = [str(bson.ObjectId()), str(bson.ObjectId())]
        model.children = children
        ActionExecution.add_or_update(model)
        model = ActionExecution.get_by_id(obj.id)
        self.assertListEqual(model.children, children)

        # Delete the DB record.
        ActionExecution.delete(model)
        self.assertRaises(StackStormDBObjectNotFoundError, ActionExecution.get_by_id, obj.id)
예제 #3
0
    def test_crud_complete(self):
        # Create the DB record.
        obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_workflow))
        ActionExecution.add_or_update(ActionExecutionAPI.to_model(obj))
        model = ActionExecution.get_by_id(obj.id)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(model.trigger, self.fake_history_workflow['trigger'])
        self.assertDictEqual(model.trigger_type, self.fake_history_workflow['trigger_type'])
        self.assertDictEqual(model.trigger_instance, self.fake_history_workflow['trigger_instance'])
        self.assertDictEqual(model.rule, self.fake_history_workflow['rule'])
        self.assertDictEqual(model.action, self.fake_history_workflow['action'])
        self.assertDictEqual(model.runner, self.fake_history_workflow['runner'])
        doc = copy.deepcopy(self.fake_history_workflow['liveaction'])
        doc['start_timestamp'] = doc['start_timestamp']
        doc['end_timestamp'] = doc['end_timestamp']
        self.assertDictEqual(model.liveaction, doc)
        self.assertIsNone(getattr(model, 'parent', None))
        self.assertListEqual(model.children, self.fake_history_workflow['children'])

        # Update the DB record.
        children = [str(bson.ObjectId()), str(bson.ObjectId())]
        model.children = children
        ActionExecution.add_or_update(model)
        model = ActionExecution.get_by_id(obj.id)
        self.assertListEqual(model.children, children)

        # Delete the DB record.
        ActionExecution.delete(model)
        self.assertRaises(ValueError, ActionExecution.get_by_id, obj.id)
예제 #4
0
 def test_execution_creation_chains(self):
     childliveaction = self.MODELS['liveactions']['childliveaction.yaml']
     child_exec = executions_util.create_execution_object(childliveaction)
     parent_execution_id = childliveaction.context['parent']['execution_id']
     parent_execution = ActionExecution.get_by_id(parent_execution_id)
     child_execs = parent_execution.children
     self.assertTrue(str(child_exec.id) in child_execs)
예제 #5
0
    def tearDown(self):

        for name, execution in self.executions.items():
            ActionExecutionModelTest._delete([execution])
            try:
                retrieved = ActionExecution.get_by_id(execution.id)
            except StackStormDBObjectNotFoundError:
                retrieved = None
            self.assertIsNone(retrieved, 'managed to retrieve after failure.')
예제 #6
0
    def _wait_for_children(self, execution, interval=0.1, retries=100):
        # Wait until the execution has children.
        for i in range(0, retries):
            execution = ActionExecution.get_by_id(str(execution.id))
            if len(getattr(execution, 'children', [])) <= 0:
                eventlet.sleep(interval)
                continue

        return execution
예제 #7
0
    def test_cleanup_policy_delayed(self):
        self.reset()

        liveaction_db = self._create_liveaction_db()

        schedule_q_db = self.scheduler._create_execution_queue_item_db_from_liveaction(
            liveaction_db
        )

        schedule_q_db = ActionExecutionSchedulingQueue.add_or_update(schedule_q_db)

        # Manually update the liveaction to policy-delayed status.
        # Using action_service.update_status will throw an exception on the
        # deprecated action_constants.LIVEACTION_STATUS_POLICY_DELAYED.
        liveaction_db.status = 'policy-delayed'
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        execution_db = execution_service.update_execution(liveaction_db)

        # Check that the execution status is set to policy-delayed.
        liveaction_db = LiveAction.get_by_id(str(liveaction_db.id))
        self.assertEqual(liveaction_db.status, 'policy-delayed')

        execution_db = ActionExecution.get_by_id(str(execution_db.id))
        self.assertEqual(execution_db.status, 'policy-delayed')

        # Run the clean up logic.
        self.scheduling_queue._cleanup_policy_delayed()

        # Check that the execution status is reset to requested.
        liveaction_db = LiveAction.get_by_id(str(liveaction_db.id))
        self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_REQUESTED)

        execution_db = ActionExecution.get_by_id(str(execution_db.id))
        self.assertEqual(execution_db.status, action_constants.LIVEACTION_STATUS_REQUESTED)

        # The old entry should have been deleted. Since the execution is
        # reset to requested, there should be a new scheduling entry.
        new_schedule_q_db = self.scheduling_queue._get_next_execution()
        self.assertIsNotNone(new_schedule_q_db)
        self.assertNotEqual(str(schedule_q_db.id), str(new_schedule_q_db.id))
        self.assertEqual(schedule_q_db.action_execution_id, new_schedule_q_db.action_execution_id)
        self.assertEqual(schedule_q_db.liveaction_id, new_schedule_q_db.liveaction_id)
예제 #8
0
파일: executions.py 프로젝트: ruslantum/st2
def _get_parent_execution(child_liveaction_db):
    parent_context = child_liveaction_db.context.get('parent', None)

    if parent_context:
        parent_id = parent_context['execution_id']
        try:
            return ActionExecution.get_by_id(parent_id)
        except:
            LOG.exception('No valid execution object found in db for id: %s' % parent_id)
            return None
    return None
예제 #9
0
    def test_non_utf8_action_result_string(self):
        action_worker = actions_worker.get_worker()
        params = {"cmd": "python -c 'print \"\\x82\"'"}
        liveaction_db = self._get_liveaction_model(WorkerTestCase.local_action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        execution_db = executions.create_execution_object(liveaction_db)

        try:
            action_worker._run_action(liveaction_db)
        except InvalidStringData:
            liveaction_db = LiveAction.get_by_id(liveaction_db.id)
            self.assertEqual(liveaction_db.status, "failed")
            self.assertTrue("error" in liveaction_db.result)
            self.assertTrue("traceback" in liveaction_db.result)
            execution_db = ActionExecution.get_by_id(execution_db.id)
            self.assertEqual(liveaction_db.status, "failed")
예제 #10
0
파일: test_worker.py 프로젝트: nzlosh/st2
    def test_non_utf8_action_result_string(self):
        action_worker = actions_worker.get_worker()
        params = {
            'cmd': "python -c 'print \"\\x82\"'"
        }
        liveaction_db = self._get_liveaction_model(WorkerTestCase.local_action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        execution_db = executions.create_execution_object(liveaction_db)

        try:
            action_worker._run_action(liveaction_db)
        except InvalidStringData:
            liveaction_db = LiveAction.get_by_id(liveaction_db.id)
            self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_FAILED)
            self.assertTrue('error' in liveaction_db.result)
            self.assertTrue('traceback' in liveaction_db.result)
            execution_db = ActionExecution.get_by_id(execution_db.id)
            self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_FAILED)
예제 #11
0
    def setUp(self):

        self.executions = {}

        for name, execution in ACTIONEXECUTIONS.items():

            created = ActionExecutionDB()
            created.action = execution['action']
            created.status = execution['status']
            created.runner = execution['runner']
            created.liveaction = execution['liveaction']
            created.result = execution['result']

            saved = ActionExecutionModelTest._save_execution(created)
            retrieved = ActionExecution.get_by_id(saved.id)
            self.assertEqual(saved.action, retrieved.action,
                             'Same action was not returned.')

            self.executions[name] = retrieved
예제 #12
0
    def setUp(self):

        self.executions = {}

        for name, execution in ACTIONEXECUTIONS.items():

            created = ActionExecutionDB()
            created.action = execution['action']
            created.status = execution['status']
            created.runner = execution['runner']
            created.liveaction = execution['liveaction']
            created.result = execution['result']

            saved = ActionExecutionModelTest._save_execution(created)
            retrieved = ActionExecution.get_by_id(saved.id)
            self.assertEqual(saved.action, retrieved.action,
                             'Same action was not returned.')

            self.executions[name] = retrieved
예제 #13
0
    def test_non_utf8_action_result_string(self):
        action_worker = actions_worker.get_worker()
        params = {"cmd": "python -c 'print \"\\x82\"'"}
        liveaction_db = self._get_liveaction_model(
            WorkerTestCase.local_action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        execution_db = executions.create_execution_object(liveaction_db)

        try:
            action_worker._run_action(liveaction_db)
        except InvalidStringData:
            liveaction_db = LiveAction.get_by_id(liveaction_db.id)
            self.assertEqual(liveaction_db.status,
                             action_constants.LIVEACTION_STATUS_FAILED)
            self.assertIn("error", liveaction_db.result)
            self.assertIn("traceback", liveaction_db.result)
            execution_db = ActionExecution.get_by_id(execution_db.id)
            self.assertEqual(liveaction_db.status,
                             action_constants.LIVEACTION_STATUS_FAILED)
    def test_chain_pause_resume_cascade_to_parent_workflow(self):
        # A temp file is created during test setup. Ensure the temp file exists.
        # The test action chain will stall until this file is deleted. This gives
        # the unit test a moment to run any test related logic.
        path = self.temp_file_path
        self.assertTrue(os.path.exists(path))

        action = TEST_PACK + '.' + 'test_pause_resume_with_subworkflow'
        params = {'tempfile': path, 'message': 'foobar'}
        liveaction = LiveActionDB(action=action, parameters=params)
        liveaction, execution = action_service.request(liveaction)
        liveaction = LiveAction.get_by_id(str(liveaction.id))

        # Wait until the liveaction is running.
        liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_RUNNING)
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)

        # Wait for subworkflow to register.
        execution = self._wait_for_children(execution)
        self.assertEqual(len(execution.children), 1)

        # Wait until the subworkflow is running.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_RUNNING)
        self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_RUNNING)

        # Request subworkflow to pause.
        task1_live, task1_exec = action_service.request_pause(task1_live, USERNAME)

        # Wait until the subworkflow is pausing.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_PAUSING)
        extra_info = str(task1_live)
        self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_PAUSING, extra_info)

        # Delete the temporary file that the action chain is waiting on.
        os.remove(path)
        self.assertFalse(os.path.exists(path))

        # Wait until the subworkflow is paused.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_PAUSED)
        extra_info = str(task1_live)
        self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_PAUSED, extra_info)

        # Wait until the parent liveaction is paused.
        liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_PAUSED)
        extra_info = str(liveaction)
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_PAUSED, extra_info)
        self.assertEqual(len(execution.children), 1)

        # Wait for non-blocking threads to complete. Ensure runner is not running.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result.
        self.assertIn('tasks', liveaction.result)
        self.assertEqual(len(liveaction.result['tasks']), 1)

        subworkflow = liveaction.result['tasks'][0]
        self.assertEqual(len(subworkflow['result']['tasks']), 1)
        self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_PAUSED)

        # Request subworkflow to resume.
        task1_live, task1_exec = action_service.request_resume(task1_live, USERNAME)

        # Wait until the subworkflow is paused.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)

        # The parent workflow will stay paused.
        liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_PAUSED)
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_PAUSED)

        # Wait for non-blocking threads to complete.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result of the parent, which should stay the same
        # because only the subworkflow was resumed.
        self.assertIn('tasks', liveaction.result)
        self.assertEqual(len(liveaction.result['tasks']), 1)

        subworkflow = liveaction.result['tasks'][0]
        self.assertEqual(len(subworkflow['result']['tasks']), 1)
        self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_PAUSED)

        # Request parent workflow to resume.
        liveaction, execution = action_service.request_resume(liveaction, USERNAME)

        # Wait until the liveaction is completed.
        liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)

        # Wait for non-blocking threads to complete.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result.
        self.assertIn('tasks', liveaction.result)
        self.assertEqual(len(liveaction.result['tasks']), 2)

        subworkflow = liveaction.result['tasks'][0]
        self.assertEqual(len(subworkflow['result']['tasks']), 2)
        self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_SUCCEEDED)
예제 #15
0
def is_execution_canceled(execution_id):
    try:
        execution = ActionExecution.get_by_id(execution_id)
        return execution.status == LIVEACTION_STATUS_CANCELED
    except:
        return False  # XXX: What to do here?
    def test_chain_pause_resume_cascade_to_parent_workflow(self):
        # A temp file is created during test setup. Ensure the temp file exists.
        # The test action chain will stall until this file is deleted. This gives
        # the unit test a moment to run any test related logic.
        path = self.temp_file_path
        self.assertTrue(os.path.exists(path))

        action = TEST_PACK + "." + "test_pause_resume_with_subworkflow"
        params = {"tempfile": path, "message": "foobar"}
        liveaction = LiveActionDB(action=action, parameters=params)
        liveaction, execution = action_service.request(liveaction)
        liveaction = LiveAction.get_by_id(str(liveaction.id))

        # Wait until the liveaction is running.
        liveaction = self._wait_for_status(
            liveaction, action_constants.LIVEACTION_STATUS_RUNNING)
        self.assertEqual(liveaction.status,
                         action_constants.LIVEACTION_STATUS_RUNNING)

        # Wait for subworkflow to register.
        execution = self._wait_for_children(execution)
        self.assertEqual(len(execution.children), 1)

        # Wait until the subworkflow is running.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"])
        task1_live = self._wait_for_status(
            task1_live, action_constants.LIVEACTION_STATUS_RUNNING)
        self.assertEqual(task1_live.status,
                         action_constants.LIVEACTION_STATUS_RUNNING)

        # Request subworkflow to pause.
        task1_live, task1_exec = action_service.request_pause(
            task1_live, USERNAME)

        # Wait until the subworkflow is pausing.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"])
        task1_live = self._wait_for_status(
            task1_live, action_constants.LIVEACTION_STATUS_PAUSING)
        extra_info = str(task1_live)
        self.assertEqual(task1_live.status,
                         action_constants.LIVEACTION_STATUS_PAUSING,
                         extra_info)

        # Delete the temporary file that the action chain is waiting on.
        os.remove(path)
        self.assertFalse(os.path.exists(path))

        # Wait until the subworkflow is paused.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"])
        task1_live = self._wait_for_status(
            task1_live, action_constants.LIVEACTION_STATUS_PAUSED)
        extra_info = str(task1_live)
        self.assertEqual(task1_live.status,
                         action_constants.LIVEACTION_STATUS_PAUSED, extra_info)

        # Wait until the parent liveaction is paused.
        liveaction = self._wait_for_status(
            liveaction, action_constants.LIVEACTION_STATUS_PAUSED)
        extra_info = str(liveaction)
        self.assertEqual(liveaction.status,
                         action_constants.LIVEACTION_STATUS_PAUSED, extra_info)
        self.assertEqual(len(execution.children), 1)

        # Wait for non-blocking threads to complete. Ensure runner is not running.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result.
        self.assertIn("tasks", liveaction.result)
        self.assertEqual(len(liveaction.result["tasks"]), 1)

        subworkflow = liveaction.result["tasks"][0]
        self.assertEqual(len(subworkflow["result"]["tasks"]), 1)
        self.assertEqual(subworkflow["state"],
                         action_constants.LIVEACTION_STATUS_PAUSED)

        # Request subworkflow to resume.
        task1_live, task1_exec = action_service.request_resume(
            task1_live, USERNAME)

        # Wait until the subworkflow is paused.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"])
        task1_live = self._wait_for_status(
            task1_live, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(task1_live.status,
                         action_constants.LIVEACTION_STATUS_SUCCEEDED)

        # The parent workflow will stay paused.
        liveaction = self._wait_for_status(
            liveaction, action_constants.LIVEACTION_STATUS_PAUSED)
        self.assertEqual(liveaction.status,
                         action_constants.LIVEACTION_STATUS_PAUSED)

        # Wait for non-blocking threads to complete.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result of the parent, which should stay the same
        # because only the subworkflow was resumed.
        self.assertIn("tasks", liveaction.result)
        self.assertEqual(len(liveaction.result["tasks"]), 1)

        subworkflow = liveaction.result["tasks"][0]
        self.assertEqual(len(subworkflow["result"]["tasks"]), 1)
        self.assertEqual(subworkflow["state"],
                         action_constants.LIVEACTION_STATUS_PAUSED)

        # Request parent workflow to resume.
        liveaction, execution = action_service.request_resume(
            liveaction, USERNAME)

        # Wait until the liveaction is completed.
        liveaction = self._wait_for_status(
            liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(liveaction.status,
                         action_constants.LIVEACTION_STATUS_SUCCEEDED)

        # Wait for non-blocking threads to complete.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result.
        self.assertIn("tasks", liveaction.result)
        self.assertEqual(len(liveaction.result["tasks"]), 2)

        subworkflow = liveaction.result["tasks"][0]
        self.assertEqual(len(subworkflow["result"]["tasks"]), 2)
        self.assertEqual(subworkflow["state"],
                         action_constants.LIVEACTION_STATUS_SUCCEEDED)
예제 #17
0
    def test_chain_cancel_cascade_to_parent_workflow(self):
        # A temp file is created during test setup. Ensure the temp file exists.
        # The test action chain will stall until this file is deleted. This gives
        # the unit test a moment to run any test related logic.
        path = self.temp_file_path
        self.assertTrue(os.path.exists(path))

        action = TEST_PACK + '.' + 'test_cancel_with_subworkflow'
        params = {'tempfile': path, 'message': 'foobar'}
        liveaction = LiveActionDB(action=action, parameters=params)
        liveaction, execution = action_service.request(liveaction)
        liveaction = LiveAction.get_by_id(str(liveaction.id))

        # Wait until the liveaction is running.
        liveaction = self._wait_on_status(
            liveaction, action_constants.LIVEACTION_STATUS_RUNNING)

        # Wait for subworkflow to register.
        execution = self._wait_for_children(execution)
        self.assertEqual(len(execution.children), 1)

        # Wait until the subworkflow is running.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_on_status(
            task1_live, action_constants.LIVEACTION_STATUS_RUNNING)

        # Request subworkflow to cancel.
        task1_live, task1_exec = action_service.request_cancellation(
            task1_live, USERNAME)

        # Wait until the subworkflow is canceling.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_on_status(
            task1_live, action_constants.LIVEACTION_STATUS_CANCELING)

        # Delete the temporary file that the action chain is waiting on.
        os.remove(path)
        self.assertFalse(os.path.exists(path))

        # Wait until the subworkflow is canceled.
        task1_exec = ActionExecution.get_by_id(execution.children[0])
        task1_live = LiveAction.get_by_id(task1_exec.liveaction['id'])
        task1_live = self._wait_on_status(
            task1_live, action_constants.LIVEACTION_STATUS_CANCELED)

        # Wait until the parent liveaction is canceled.
        liveaction = self._wait_on_status(
            liveaction, action_constants.LIVEACTION_STATUS_CANCELED)
        self.assertEqual(len(execution.children), 1)

        # Wait for non-blocking threads to complete. Ensure runner is not running.
        MockLiveActionPublisherNonBlocking.wait_all()

        # Check liveaction result.
        self.assertIn('tasks', liveaction.result)
        self.assertEqual(len(liveaction.result['tasks']), 1)

        subworkflow = liveaction.result['tasks'][0]
        self.assertEqual(len(subworkflow['result']['tasks']), 1)
        self.assertEqual(subworkflow['state'],
                         action_constants.LIVEACTION_STATUS_CANCELED)
    def test_migrate_executions(self):
        ActionExecutionDB._meta["allow_inheritance"] = True
        LiveActionDB._meta["allow_inheritance"] = True

        class ActionExecutionDB_OldFieldType(ActionExecutionDB):
            result = stormbase.EscapedDynamicField(default={})

        class LiveActionDB_OldFieldType(LiveActionDB):
            result = stormbase.EscapedDynamicField(default={})

        execution_dbs = ActionExecution.query(
            __raw__={"result": {
                "$not": {
                    "$type": "binData",
                },
            }})
        self.assertEqual(len(execution_dbs), 0)
        execution_dbs = ActionExecution.query(__raw__={
            "result": {
                "$type": "object",
            },
        })
        self.assertEqual(len(execution_dbs), 0)

        # 1. Insert data in old format
        liveaction_1_db = LiveActionDB_OldFieldType()
        liveaction_1_db.action = "foo.bar"
        liveaction_1_db.status = action_constants.LIVEACTION_STATUS_FAILED
        liveaction_1_db.result = MOCK_RESULT_1
        liveaction_1_db.start_timestamp = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc)
        liveaction_1_db = LiveAction.add_or_update(liveaction_1_db,
                                                   publish=False)

        execution_1_db = ActionExecutionDB_OldFieldType()
        execution_1_db.action = {"a": 1}
        execution_1_db.runner = {"a": 1}
        execution_1_db.liveaction = {"id": liveaction_1_db.id}
        execution_1_db.status = action_constants.LIVEACTION_STATUS_FAILED
        execution_1_db.result = MOCK_RESULT_1
        execution_1_db.start_timestamp = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc)

        execution_1_db = ActionExecution.add_or_update(execution_1_db,
                                                       publish=False)

        # This execution is not in a final state yet so it should not be migrated
        liveaction_2_db = LiveActionDB_OldFieldType()
        liveaction_2_db.action = "foo.bar2"
        liveaction_2_db.status = action_constants.LIVEACTION_STATUS_RUNNING
        liveaction_2_db.result = MOCK_RESULT_2
        liveaction_2_db.start_timestamp = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc)

        liveaction_2_db = LiveAction.add_or_update(liveaction_2_db,
                                                   publish=False)

        execution_2_db = ActionExecutionDB_OldFieldType()
        execution_2_db.action = {"a": 2}
        execution_2_db.runner = {"a": 2}
        execution_2_db.liveaction = {"id": liveaction_2_db.id}
        execution_2_db.status = action_constants.LIVEACTION_STATUS_RUNNING
        execution_2_db.result = MOCK_RESULT_2
        execution_2_db.start_timestamp = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc)

        execution_2_db = ActionExecution.add_or_update(execution_2_db,
                                                       publish=False)

        # This object is older than the default threshold so it should not be migrated
        execution_3_db = ActionExecutionDB_OldFieldType()
        execution_3_db.action = {"a": 2}
        execution_3_db.runner = {"a": 2}
        execution_3_db.liveaction = {"id": liveaction_2_db.id}
        execution_3_db.status = action_constants.LIVEACTION_STATUS_SUCCEEDED
        execution_3_db.result = MOCK_RESULT_1
        execution_3_db.start_timestamp = datetime.datetime.utcfromtimestamp(
            0).replace(tzinfo=datetime.timezone.utc)

        execution_3_db = ActionExecution.add_or_update(execution_3_db,
                                                       publish=False)

        # Verify data has been inserted in old format
        execution_dbs = ActionExecution.query(__raw__={
            "result": {
                "$type": "object",
            },
        })
        self.assertEqual(len(execution_dbs), 3)
        execution_dbs = ActionExecution.query(
            __raw__={"result": {
                "$not": {
                    "$type": "binData",
                },
            }})
        self.assertEqual(len(execution_dbs), 3)
        execution_dbs = ActionExecution.query(__raw__={
            "result": {
                "$type": "binData",
            },
        })
        self.assertEqual(len(execution_dbs), 0)

        liveaction_dbs = LiveAction.query(__raw__={
            "result": {
                "$type": "object",
            },
        })
        self.assertEqual(len(liveaction_dbs), 2)
        liveaction_dbs = LiveAction.query(
            __raw__={"result": {
                "$not": {
                    "$type": "binData",
                },
            }})
        self.assertEqual(len(liveaction_dbs), 2)
        liveaction_dbs = LiveAction.query(__raw__={
            "result": {
                "$type": "binData",
            },
        })
        self.assertEqual(len(liveaction_dbs), 0)

        # Update inserted documents and remove special _cls field added by mongoengine. We need to
        # do that here due to how mongoengine works with subclasses.
        ActionExecution.query(__raw__={
            "result": {
                "$type": "object",
            },
        }).update(set___cls="ActionExecutionDB")

        LiveAction.query(__raw__={
            "result": {
                "$type": "object",
            },
        }).update(set___cls="LiveActionDB")

        # 2. Run migration
        start_dt = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc) - datetime.timedelta(hours=2)
        end_dt = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc)
        migration_module.migrate_executions(start_dt=start_dt, end_dt=end_dt)

        # 3. Verify data has been migrated - only 1 item should have been migrated since it's in a
        # completed state
        execution_dbs = ActionExecution.query(__raw__={
            "result": {
                "$type": "object",
            },
        })
        self.assertEqual(len(execution_dbs), 2)
        execution_dbs = ActionExecution.query(__raw__={
            "result": {
                "$type": "binData",
            },
        })
        self.assertEqual(len(execution_dbs), 1)

        execution_db_1_retrieved = ActionExecution.get_by_id(execution_1_db.id)
        self.assertEqual(execution_db_1_retrieved.result, MOCK_RESULT_1)

        execution_db_2_retrieved = ActionExecution.get_by_id(execution_2_db.id)
        self.assertEqual(execution_db_2_retrieved.result, MOCK_RESULT_2)

        liveaction_db_1_retrieved = LiveAction.get_by_id(liveaction_1_db.id)
        self.assertEqual(liveaction_db_1_retrieved.result, MOCK_RESULT_1)

        liveaction_db_2_retrieved = LiveAction.get_by_id(liveaction_2_db.id)
        self.assertEqual(liveaction_db_2_retrieved.result, MOCK_RESULT_2)
예제 #19
0
 def _get_rerun_reference(self, context):
     execution_id = context.get('re-run', {}).get('ref')
     return ActionExecution.get_by_id(
         execution_id) if execution_id else None
예제 #20
0
파일: base.py 프로젝트: nzlosh/st2
 def _get_rerun_reference(self, context):
     execution_id = context.get('re-run', {}).get('ref')
     return ActionExecution.get_by_id(execution_id) if execution_id else None