Пример #1
0
    def test_state_db_created_for_polling_async_actions(self):
        runner_container = get_runner_container()

        params = {"actionstr": "foo", "actionint": 20, "async_test": True}

        liveaction_db = self._get_liveaction_model(
            RunnerContainerTest.polling_async_action_db, params)

        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        # Assert that execution ran without exceptions.
        with mock.patch(
                "st2actions.container.base.get_runner",
                mock.Mock(return_value=polling_async_runner.get_runner()),
        ):
            runner_container.dispatch(liveaction_db)
        states = ActionExecutionState.get_all()
        found = [
            state for state in states if state.execution_id == liveaction_db.id
        ]

        self.assertTrue(len(found) > 0, "There should be a state db object.")
        self.assertTrue(
            len(found) == 1, "There should only be one state db object.")
        self.assertIsNotNone(found[0].query_context)
        self.assertIsNotNone(found[0].query_module)
Пример #2
0
 def test_execution_creation_action_triggered_by_rule(self):
     # Wait for the action execution to complete and then confirm outcome.
     trigger_type = self.MODELS['triggertypes']['triggertype2.yaml']
     trigger = self.MODELS['triggers']['trigger2.yaml']
     trigger_instance = self.MODELS['triggerinstances']['trigger_instance_1.yaml']
     test_liveaction = self.FIXTURES['liveactions']['liveaction3.yaml']
     rule = self.MODELS['rules']['rule3.yaml']
     # Setup LiveAction to point to right rule and trigger_instance.
     # XXX: We need support for dynamic fixtures.
     test_liveaction['context']['rule']['id'] = str(rule.id)
     test_liveaction['context']['trigger_instance']['id'] = str(trigger_instance.id)
     test_liveaction_api = LiveActionAPI(**test_liveaction)
     test_liveaction = LiveAction.add_or_update(LiveActionAPI.to_model(test_liveaction_api))
     liveaction = LiveAction.get(context__trigger_instance__id=str(trigger_instance.id))
     self.assertIsNotNone(liveaction)
     self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_REQUESTED)
     executions_util.create_execution_object(liveaction)
     execution = self._get_action_execution(liveaction__id=str(liveaction.id),
                                            raise_exception=True)
     self.assertDictEqual(execution.trigger, vars(TriggerAPI.from_model(trigger)))
     self.assertDictEqual(execution.trigger_type, vars(TriggerTypeAPI.from_model(trigger_type)))
     self.assertDictEqual(execution.trigger_instance,
                          vars(TriggerInstanceAPI.from_model(trigger_instance)))
     self.assertDictEqual(execution.rule, vars(RuleAPI.from_model(rule)))
     action = action_utils.get_action_by_ref(liveaction.action)
     self.assertDictEqual(execution.action, vars(ActionAPI.from_model(action)))
     runner = RunnerType.get_by_name(action.runner_type['name'])
     self.assertDictEqual(execution.runner, vars(RunnerTypeAPI.from_model(runner)))
     liveaction = LiveAction.get_by_id(str(liveaction.id))
     self.assertEquals(execution.liveaction['id'], str(liveaction.id))
Пример #3
0
 def test_execution_creation_manual_action_run(self):
     liveaction = self.MODELS['liveactions']['liveaction1.yaml']
     pre_creation_timestamp = date_utils.get_datetime_utc_now()
     executions_util.create_execution_object(liveaction)
     post_creation_timestamp = date_utils.get_datetime_utc_now()
     execution = self._get_action_execution(liveaction__id=str(
         liveaction.id),
                                            raise_exception=True)
     self.assertDictEqual(execution.trigger, {})
     self.assertDictEqual(execution.trigger_type, {})
     self.assertDictEqual(execution.trigger_instance, {})
     self.assertDictEqual(execution.rule, {})
     action = action_utils.get_action_by_ref('core.local')
     self.assertDictEqual(execution.action,
                          vars(ActionAPI.from_model(action)))
     runner = RunnerType.get_by_name(action.runner_type['name'])
     self.assertDictEqual(execution.runner,
                          vars(RunnerTypeAPI.from_model(runner)))
     liveaction = LiveAction.get_by_id(str(liveaction.id))
     self.assertEquals(execution.liveaction['id'], str(liveaction.id))
     self.assertEquals(len(execution.log), 1)
     self.assertEquals(execution.log[0]['status'], liveaction.status)
     self.assertGreater(execution.log[0]['timestamp'],
                        pre_creation_timestamp)
     self.assertLess(execution.log[0]['timestamp'], post_creation_timestamp)
Пример #4
0
    def test_state_db_created_for_polling_async_actions(self):
        runner_container = get_runner_container()

        params = {
            'actionstr': 'foo',
            'actionint': 20,
            'async_test': True
        }

        liveaction_db = self._get_liveaction_model(
            RunnerContainerTest.polling_async_action_db,
            params
        )

        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        # Assert that execution ran without exceptions.
        runner_container.dispatch(liveaction_db)
        states = ActionExecutionState.get_all()
        found = [state for state in states if state.execution_id == liveaction_db.id]

        self.assertTrue(len(found) > 0, 'There should be a state db object.')
        self.assertTrue(len(found) == 1, 'There should only be one state db object.')
        self.assertTrue(found[0].query_context is not None)
        self.assertTrue(found[0].query_module is not None)
Пример #5
0
 def test_abandon_executions_on_complete(self):
     liveaction_db = self.MODELS['liveactions']['successful_liveaction.yaml']
     executions_util.create_execution_object(liveaction_db)
     expected_msg = 'LiveAction %s already in a completed state %s\.' % \
                    (str(liveaction_db.id), liveaction_db.status)
     self.assertRaisesRegexp(ValueError, expected_msg,
                             executions_util.abandon_execution_if_incomplete,
                             liveaction_id=str(liveaction_db.id))
Пример #6
0
 def test_execution_creation_with_web_url(self):
     liveaction = self.MODELS['liveactions']['liveaction1.yaml']
     executions_util.create_execution_object(liveaction)
     execution = self._get_action_execution(liveaction__id=str(liveaction.id),
                                            raise_exception=True)
     self.assertIsNotNone(execution.web_url)
     execution_id = str(execution.id)
     self.assertIn(('history/%s/general' % execution_id), execution.web_url)
Пример #7
0
 def test_abandon_executions_on_complete(self):
     liveaction_db = self.MODELS['liveactions']['successful_liveaction.yaml']
     executions_util.create_execution_object(liveaction_db)
     expected_msg = 'LiveAction %s already in a completed state %s\.' % \
                    (str(liveaction_db.id), liveaction_db.status)
     self.assertRaisesRegexp(ValueError, expected_msg,
                             executions_util.abandon_execution_if_incomplete,
                             liveaction_id=str(liveaction_db.id))
Пример #8
0
 def test_execution_creation_with_web_url(self):
     liveaction = self.MODELS['liveactions']['liveaction1.yaml']
     executions_util.create_execution_object(liveaction)
     execution = self._get_action_execution(liveaction__id=str(liveaction.id),
                                            raise_exception=True)
     self.assertTrue(execution.web_url is not None)
     execution_id = str(execution.id)
     self.assertTrue(('history/%s/general' % execution_id) in execution.web_url)
Пример #9
0
    def _create_liveaction_db(self, status=action_constants.LIVEACTION_STATUS_REQUESTED):
        action_ref = 'wolfpack.action-1'
        parameters = {'actionstr': 'fu'}
        liveaction_db = LiveActionDB(action=action_ref, parameters=parameters, status=status)

        liveaction_db = LiveAction.add_or_update(liveaction_db)
        execution_service.create_execution_object(liveaction_db, publish=False)

        return liveaction_db
Пример #10
0
 def _create_inquiry(self, ttl, timestamp):
     action_db = self.models['actions']['ask.yaml']
     liveaction_db = LiveActionDB()
     liveaction_db.status = action_constants.LIVEACTION_STATUS_PENDING
     liveaction_db.start_timestamp = timestamp
     liveaction_db.action = ResourceReference(name=action_db.name, pack=action_db.pack).ref
     liveaction_db.result = {'ttl': ttl}
     liveaction_db = LiveAction.add_or_update(liveaction_db)
     executions.create_execution_object(liveaction_db)
Пример #11
0
 def _create_inquiry(self, ttl, timestamp):
     action_db = self.models['actions']['ask.yaml']
     liveaction_db = LiveActionDB()
     liveaction_db.status = action_constants.LIVEACTION_STATUS_PENDING
     liveaction_db.start_timestamp = timestamp
     liveaction_db.action = ResourceReference(name=action_db.name, pack=action_db.pack).ref
     liveaction_db.result = {'ttl': ttl}
     liveaction_db = LiveAction.add_or_update(liveaction_db)
     executions.create_execution_object(liveaction_db)
Пример #12
0
    def test_abandon_executions(self):
        liveaction_db = self.MODELS['liveactions']['liveaction1.yaml']
        executions_util.create_execution_object(liveaction_db)
        execution_db = executions_util.abandon_execution_if_incomplete(
            liveaction_id=str(liveaction_db.id))

        self.assertEquals(execution_db.status, 'abandoned')

        runners_utils.invoke_post_run.assert_called_once()
Пример #13
0
    def _create_liveaction_db(self, status=action_constants.LIVEACTION_STATUS_REQUESTED):
        action_ref = 'wolfpack.action-1'
        parameters = {'actionstr': 'fu'}
        liveaction_db = LiveActionDB(action=action_ref, parameters=parameters, status=status)

        liveaction_db = LiveAction.add_or_update(liveaction_db)
        execution_service.create_execution_object(liveaction_db, publish=False)

        return liveaction_db
Пример #14
0
    def test_abandon_executions(self):
        liveaction_db = self.MODELS['liveactions']['liveaction1.yaml']
        executions_util.create_execution_object(liveaction_db)
        execution_db = executions_util.abandon_execution_if_incomplete(
            liveaction_id=str(liveaction_db.id))

        self.assertEquals(execution_db.status, 'abandoned')

        runners_utils.invoke_post_run.assert_called_once()
Пример #15
0
    def test_created_temporary_auth_token_is_correctly_scoped_to_user_who_ran_the_action(
            self):
        params = {
            'actionstr': 'bar',
            'mock_status': action_constants.LIVEACTION_STATUS_SUCCEEDED
        }

        global global_runner
        global_runner = None

        def mock_get_runner(*args, **kwargs):
            global global_runner
            runner = original_get_runner(*args, **kwargs)
            global_runner = runner
            return runner

        # user joe_1

        runner_container = get_runner_container()
        original_get_runner = runner_container._get_runner

        liveaction_db = self._get_failingaction_exec_db_model(params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        liveaction_db.context = {'user': '******'}
        executions.create_execution_object(liveaction_db)

        runner_container._get_runner = mock_get_runner

        self.assertEqual(getattr(global_runner, 'auth_token', None), None)
        runner_container.dispatch(liveaction_db)
        self.assertEqual(global_runner.auth_token.user, 'user_joe_1')
        self.assertEqual(global_runner.auth_token.metadata['service'],
                         'actions_container')

        runner_container._get_runner = original_get_runner

        # user mark_1
        global_runner = None
        runner_container = get_runner_container()
        original_get_runner = runner_container._get_runner

        liveaction_db = self._get_failingaction_exec_db_model(params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        liveaction_db.context = {'user': '******'}
        executions.create_execution_object(liveaction_db)
        original_get_runner = runner_container._get_runner

        runner_container._get_runner = mock_get_runner

        self.assertEqual(getattr(global_runner, 'auth_token', None), None)
        runner_container.dispatch(liveaction_db)
        self.assertEqual(global_runner.auth_token.user, 'user_mark_2')
        self.assertEqual(global_runner.auth_token.metadata['service'],
                         'actions_container')
Пример #16
0
 def test_dispatch_runner_failure(self):
     runner_container = get_runner_container()
     params = {"actionstr": "bar"}
     liveaction_db = self._get_failingaction_exec_db_model(params)
     liveaction_db = LiveAction.add_or_update(liveaction_db)
     executions.create_execution_object(liveaction_db)
     runner_container.dispatch(liveaction_db)
     # pickup updated liveaction_db
     liveaction_db = LiveAction.get_by_id(liveaction_db.id)
     self.assertTrue("message" in liveaction_db.result)
     self.assertTrue("traceback" in liveaction_db.result)
Пример #17
0
 def test_dispatch_runner_failure(self):
     runner_container = get_runner_container()
     params = {'actionstr': 'bar'}
     liveaction_db = self._get_failingaction_exec_db_model(params)
     liveaction_db = LiveAction.add_or_update(liveaction_db)
     executions.create_execution_object(liveaction_db)
     runner_container.dispatch(liveaction_db)
     # pickup updated liveaction_db
     liveaction_db = LiveAction.get_by_id(liveaction_db.id)
     self.assertTrue('error' in liveaction_db.result)
     self.assertTrue('traceback' in liveaction_db.result)
Пример #18
0
    def test_worker_shutdown(self):
        cfg.CONF.set_override(name="graceful_shutdown",
                              override=False,
                              group="actionrunner")
        action_worker = actions_worker.get_worker()
        temp_file = None

        # Create a temporary file that is deleted when the file is closed and then set up an
        # action to wait for this file to be deleted. This allows this test to run the action
        # over a separate thread, run the shutdown sequence on the main thread, and then let
        # the local runner to exit gracefully and allow _run_action to finish execution.
        with tempfile.NamedTemporaryFile() as fp:
            temp_file = fp.name
            self.assertIsNotNone(temp_file)
            self.assertTrue(os.path.isfile(temp_file))

            # Launch the action execution in a separate thread.
            params = {
                "cmd": "while [ -e '%s' ]; do sleep 0.1; done" % temp_file
            }
            liveaction_db = self._get_liveaction_model(
                WorkerTestCase.local_action_db, params)
            liveaction_db = LiveAction.add_or_update(liveaction_db)
            executions.create_execution_object(liveaction_db)
            runner_thread = eventlet.spawn(action_worker._run_action,
                                           liveaction_db)

            # Wait for the worker up to 10s to add the liveaction to _running_liveactions.
            for i in range(0, int(10 / 0.1)):
                eventlet.sleep(0.1)
                if len(action_worker._running_liveactions) > 0:
                    break

            self.assertEqual(len(action_worker._running_liveactions), 1)

            # Shutdown the worker to trigger the abandon process.
            action_worker.shutdown()
            liveaction_db = LiveAction.get_by_id(liveaction_db.id)

            # Verify that _running_liveactions is empty and the liveaction is abandoned.
            self.assertEqual(len(action_worker._running_liveactions), 0)
            self.assertEqual(
                liveaction_db.status,
                action_constants.LIVEACTION_STATUS_ABANDONED,
                str(liveaction_db),
            )

        # Make sure the temporary file has been deleted.
        self.assertFalse(os.path.isfile(temp_file))

        # Wait for the local runner to complete. This will activate the finally block in
        # _run_action but will not result in KeyError because the discard method is used to
        # to remove the liveaction from _running_liveactions.
        runner_thread.wait()
Пример #19
0
    def test_dispatch_non_utf8_result(self):
        runner_container = get_runner_container()
        params = {"cmd": "python -c 'print \"\\x82\"'"}
        liveaction_db = self._get_liveaction_model(RunnerContainerTest.local_action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        try:
            runner_container.dispatch(liveaction_db)
            self.fail("Mongo won't handle non UTF-8 strings. Should have failed.")
        except InvalidStringData:
            pass
Пример #20
0
    def setUp(self):
        super(RunnersUtilityTests, self).setUp()

        loader = fixturesloader.FixturesLoader()

        self.models = loader.save_fixtures_to_db(fixtures_pack=FIXTURES_PACK,
                                                 fixtures_dict=TEST_FIXTURES)

        self.liveaction_db = self.models['liveactions']['liveaction1.yaml']
        exe_svc.create_execution_object(self.liveaction_db)
        self.action_db = action_db_utils.get_action_by_ref(
            self.liveaction_db.action)
Пример #21
0
 def test_dispatch_override_default_action_params(self):
     runner_container = get_runner_container()
     params = {"actionstr": "foo", "actionint": 20}
     liveaction_db = self._get_action_exec_db_model(RunnerContainerTest.action_db, params)
     liveaction_db = LiveAction.add_or_update(liveaction_db)
     executions.create_execution_object(liveaction_db)
     # Assert that execution ran successfully.
     runner_container.dispatch(liveaction_db)
     liveaction_db = LiveAction.get_by_id(liveaction_db.id)
     result = liveaction_db.result
     self.assertTrue(result.get("action_params").get("actionint") == 20)
     self.assertTrue(result.get("action_params").get("actionstr") == "foo")
Пример #22
0
 def test_dispatch_override_default_action_params(self):
     runner_container = get_runner_container()
     params = {'actionstr': 'foo', 'actionint': 20}
     liveaction_db = self._get_liveaction_model(
         RunnerContainerTest.action_db, params)
     liveaction_db = LiveAction.add_or_update(liveaction_db)
     executions.create_execution_object(liveaction_db)
     # Assert that execution ran successfully.
     runner_container.dispatch(liveaction_db)
     liveaction_db = LiveAction.get_by_id(liveaction_db.id)
     result = liveaction_db.result
     self.assertTrue(result.get('action_params').get('actionint') == 20)
     self.assertTrue(result.get('action_params').get('actionstr') == 'foo')
Пример #23
0
 def test_execution_update(self):
     liveaction = self.MODELS['liveactions']['liveaction1.yaml']
     executions_util.create_execution_object(liveaction)
     liveaction.status = 'running'
     pre_update_timestamp = date_utils.get_datetime_utc_now()
     executions_util.update_execution(liveaction)
     post_update_timestamp = date_utils.get_datetime_utc_now()
     execution = self._get_action_execution(liveaction__id=str(liveaction.id),
                                            raise_exception=True)
     self.assertEquals(len(execution.log), 2)
     self.assertEquals(execution.log[1]['status'], liveaction.status)
     self.assertGreater(execution.log[1]['timestamp'], pre_update_timestamp)
     self.assertLess(execution.log[1]['timestamp'], post_update_timestamp)
Пример #24
0
 def test_execution_update(self):
     liveaction = self.MODELS['liveactions']['liveaction1.yaml']
     executions_util.create_execution_object(liveaction)
     liveaction.status = 'running'
     pre_update_timestamp = date_utils.get_datetime_utc_now()
     executions_util.update_execution(liveaction)
     post_update_timestamp = date_utils.get_datetime_utc_now()
     execution = self._get_action_execution(liveaction__id=str(liveaction.id),
                                            raise_exception=True)
     self.assertEqual(len(execution.log), 2)
     self.assertEqual(execution.log[1]['status'], liveaction.status)
     self.assertGreater(execution.log[1]['timestamp'], pre_update_timestamp)
     self.assertLess(execution.log[1]['timestamp'], post_update_timestamp)
Пример #25
0
    def setUp(self):
        super(RunnersUtilityTests, self).setUp()

        loader = fixturesloader.FixturesLoader()

        self.models = loader.save_fixtures_to_db(
            fixtures_pack=FIXTURES_PACK,
            fixtures_dict=TEST_FIXTURES
        )

        self.liveaction_db = self.models['liveactions']['liveaction1.yaml']
        exe_svc.create_execution_object(self.liveaction_db)
        self.action_db = action_db_utils.get_action_by_ref(self.liveaction_db.action)
Пример #26
0
    def test_created_temporary_auth_token_is_correctly_scoped_to_user_who_ran_the_action(self):
        params = {
            'actionstr': 'bar',
            'mock_status': action_constants.LIVEACTION_STATUS_SUCCEEDED
        }

        global global_runner
        global_runner = None

        def mock_get_runner(*args, **kwargs):
            global global_runner
            runner = original_get_runner(*args, **kwargs)
            global_runner = runner
            return runner

        # user joe_1

        runner_container = get_runner_container()
        original_get_runner = runner_container._get_runner

        liveaction_db = self._get_failingaction_exec_db_model(params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        liveaction_db.context = {'user': '******'}
        executions.create_execution_object(liveaction_db)

        runner_container._get_runner = mock_get_runner

        self.assertEqual(getattr(global_runner, 'auth_token', None), None)
        runner_container.dispatch(liveaction_db)
        self.assertEqual(global_runner.auth_token.user, 'user_joe_1')
        self.assertEqual(global_runner.auth_token.metadata['service'], 'actions_container')

        runner_container._get_runner = original_get_runner

        # user mark_1
        global_runner = None
        runner_container = get_runner_container()
        original_get_runner = runner_container._get_runner

        liveaction_db = self._get_failingaction_exec_db_model(params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        liveaction_db.context = {'user': '******'}
        executions.create_execution_object(liveaction_db)
        original_get_runner = runner_container._get_runner

        runner_container._get_runner = mock_get_runner

        self.assertEqual(getattr(global_runner, 'auth_token', None), None)
        runner_container.dispatch(liveaction_db)
        self.assertEqual(global_runner.auth_token.user, 'user_mark_2')
        self.assertEqual(global_runner.auth_token.metadata['service'], 'actions_container')
Пример #27
0
    def test_dispatch_unsupported_status(self):
        runner_container = get_runner_container()
        params = {'actionstr': 'bar'}
        liveaction_db = self._get_liveaction_model(
            RunnerContainerTest.action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        # Manually set the liveaction_db to some unsupported status.
        liveaction_db.status = action_constants.LIVEACTION_STATUS_CANCELED

        # Assert exception is raised on dispatch.
        self.assertRaises(ActionRunnerDispatchError, runner_container.dispatch,
                          liveaction_db)
Пример #28
0
 def test_skip_execution_update(self):
     liveaction = self.MODELS["liveactions"]["successful_liveaction.yaml"]
     executions_util.create_execution_object(liveaction)
     pre_update_status = liveaction.status
     liveaction.status = "running"
     executions_util.update_execution(liveaction)
     execution = self._get_action_execution(liveaction__id=str(
         liveaction.id),
                                            raise_exception=True)
     self.assertEqual(len(execution.log), 1)
     # Check status is not updated if it's already in completed state.
     self.assertEqual(pre_update_status,
                      action_constants.LIVEACTION_STATUS_SUCCEEDED)
     self.assertEqual(execution.log[0]["status"], pre_update_status)
Пример #29
0
    def test_dispatch_non_utf8_result(self):
        runner_container = get_runner_container()
        params = {'cmd': "python -c 'print \"\\x82\"'"}
        liveaction_db = self._get_liveaction_model(
            RunnerContainerTest.local_action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        try:
            runner_container.dispatch(liveaction_db)
            self.fail(
                'Mongo won\'t handle non UTF-8 strings. Should have failed.')
        except InvalidStringData:
            pass
Пример #30
0
 def test_execution_creation_manual_action_run(self):
     liveaction = self.MODELS['liveactions']['liveaction1.yaml']
     executions_util.create_execution_object(liveaction)
     execution = self._get_action_execution(liveaction__id=str(liveaction.id),
                                            raise_exception=True)
     self.assertDictEqual(execution.trigger, {})
     self.assertDictEqual(execution.trigger_type, {})
     self.assertDictEqual(execution.trigger_instance, {})
     self.assertDictEqual(execution.rule, {})
     action = action_utils.get_action_by_ref('core.local')
     self.assertDictEqual(execution.action, vars(ActionAPI.from_model(action)))
     runner = RunnerType.get_by_name(action.runner_type['name'])
     self.assertDictEqual(execution.runner, vars(RunnerTypeAPI.from_model(runner)))
     liveaction = LiveAction.get_by_id(str(liveaction.id))
     self.assertEquals(execution.liveaction['id'], str(liveaction.id))
Пример #31
0
    def _create_liveaction_db(
            self, status=action_constants.LIVEACTION_STATUS_REQUESTED):
        action_db = action_utils.get_action_by_ref('core.noop')

        liveaction_db = LiveActionDB(
            action=action_db.ref,
            parameters=None,
            start_timestamp=date_utils.get_datetime_utc_now(),
            status=status)

        liveaction_db = action.LiveAction.add_or_update(liveaction_db,
                                                        publish=False)
        executions.create_execution_object(liveaction_db)

        return liveaction_db
Пример #32
0
    def test_dispatch_unsupported_status(self):
        runner_container = get_runner_container()
        params = {'actionstr': 'bar'}
        liveaction_db = self._get_liveaction_model(RunnerContainerTest.action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        # Manually set the liveaction_db to some unsupported status.
        liveaction_db.status = action_constants.LIVEACTION_STATUS_CANCELED

        # Assert exception is raised on dispatch.
        self.assertRaises(
            ActionRunnerDispatchError,
            runner_container.dispatch,
            liveaction_db
        )
Пример #33
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.assertIn(str(child_exec.id), child_execs)
Пример #34
0
    def test_delayed_executions_recovery_before_timeout(self):
        # Create a live action that's delayed but has not passed the timeout.
        liveaction = LiveActionDB(action='wolfpack.action-1',
                                  parameters={'actionstr': 'foo'},
                                  start_timestamp=date_utils.get_datetime_utc_now(),
                                  status=action_constants.LIVEACTION_STATUS_DELAYED)

        liveaction = LiveAction.add_or_update(liveaction, publish=False)
        executions.create_execution_object(liveaction, publish=False)

        # Run the rescheduling routine.
        scheduler.recover_delayed_executions()

        # The live action is expected to stay "delayed".
        liveaction = LiveAction.get_by_id(str(liveaction.id))
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_DELAYED)
Пример #35
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)
Пример #36
0
    def test_delayed_executions_recovery_before_timeout(self):
        # Create a live action that's delayed but has not passed the timeout.
        liveaction = LiveActionDB(action='wolfpack.action-1',
                                  parameters={'actionstr': 'foo'},
                                  start_timestamp=date_utils.get_datetime_utc_now(),
                                  status=action_constants.LIVEACTION_STATUS_DELAYED)

        liveaction = LiveAction.add_or_update(liveaction, publish=False)
        executions.create_execution_object(liveaction, publish=False)

        # Run the rescheduling routine.
        scheduler.recover_delayed_executions()

        # The live action is expected to stay "delayed".
        liveaction = LiveAction.get_by_id(str(liveaction.id))
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_DELAYED)
Пример #37
0
    def test_abandon_executions_on_complete(self):
        liveaction_db = self.MODELS["liveactions"]["successful_liveaction.yaml"]
        executions_util.create_execution_object(liveaction_db)
        expected_msg = r"LiveAction %s already in a completed state %s\." % (
            str(liveaction_db.id),
            liveaction_db.status,
        )

        self.assertRaisesRegexp(
            ValueError,
            expected_msg,
            executions_util.abandon_execution_if_incomplete,
            liveaction_id=str(liveaction_db.id),
        )

        runners_utils.invoke_post_run.assert_not_called()
Пример #38
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)
Пример #39
0
    def test_state_db_creation_async_actions(self):
        runner_container = get_runner_container()
        params = {"actionstr": "foo", "actionint": 20, "async_test": True}
        liveaction_db = self._get_action_exec_db_model(RunnerContainerTest.async_action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)
        # Assert that execution ran without exceptions.
        runner_container.dispatch(liveaction_db)
        states = ActionExecutionState.get_all()

        found = None
        for state in states:
            if state.execution_id == liveaction_db.id:
                found = state
        self.assertTrue(found is not None, "There should be a state db object.")
        self.assertTrue(found.query_context is not None)
        self.assertTrue(found.query_module is not None)
Пример #40
0
    def test_dispatch(self):
        runner_container = get_runner_container()
        params = {"actionstr": "bar"}
        liveaction_db = self._get_action_exec_db_model(RunnerContainerTest.action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)
        # Assert that execution ran successfully.
        runner_container.dispatch(liveaction_db)
        liveaction_db = LiveAction.get_by_id(liveaction_db.id)
        result = liveaction_db.result
        self.assertTrue(result.get("action_params").get("actionint") == 10)
        self.assertTrue(result.get("action_params").get("actionstr") == "bar")

        # Assert that context is written correctly.
        context = {"user": "******", "third_party_system": {"ref_id": "1234"}}

        self.assertDictEqual(liveaction_db.context, context)
Пример #41
0
    def test_dispatch(self):
        runner_container = get_runner_container()
        params = {"actionstr": "bar"}
        liveaction_db = self._get_liveaction_model(
            RunnerContainerTest.action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)
        # Assert that execution ran successfully.
        runner_container.dispatch(liveaction_db)
        liveaction_db = LiveAction.get_by_id(liveaction_db.id)
        result = liveaction_db.result
        self.assertTrue(result.get("action_params").get("actionint") == 10)
        self.assertTrue(result.get("action_params").get("actionstr") == "bar")

        # Assert that context is written correctly.
        context = {"user": "******", "third_party_system": {"ref_id": "1234"}}

        self.assertDictEqual(liveaction_db.context, context)
Пример #42
0
    def test_dispatch(self):
        runner_container = get_runner_container()
        params = {'actionstr': 'bar'}
        liveaction_db = self._get_liveaction_model(
            RunnerContainerTest.action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)
        # Assert that execution ran successfully.
        runner_container.dispatch(liveaction_db)
        liveaction_db = LiveAction.get_by_id(liveaction_db.id)
        result = liveaction_db.result
        self.assertTrue(result.get('action_params').get('actionint') == 10)
        self.assertTrue(result.get('action_params').get('actionstr') == 'bar')

        # Assert that context is written correctly.
        context = {'user': '******', 'third_party_system': {'ref_id': '1234'}}

        self.assertDictEqual(liveaction_db.context, context)
Пример #43
0
    def test_worker_shutdown(self):
        action_worker = actions_worker.get_worker()
        temp_file = None

        # Create a temporary file that is deleted when the file is closed and then set up an
        # action to wait for this file to be deleted. This allows this test to run the action
        # over a separate thread, run the shutdown sequence on the main thread, and then let
        # the local runner to exit gracefully and allow _run_action to finish execution.
        with tempfile.NamedTemporaryFile() as fp:
            temp_file = fp.name
            self.assertIsNotNone(temp_file)
            self.assertTrue(os.path.isfile(temp_file))

            # Launch the action execution in a separate thread.
            params = {'cmd': 'while [ -e \'%s\' ]; do sleep 0.1; done' % temp_file}
            liveaction_db = self._get_liveaction_model(WorkerTestCase.local_action_db, params)
            liveaction_db = LiveAction.add_or_update(liveaction_db)
            executions.create_execution_object(liveaction_db)
            runner_thread = eventlet.spawn(action_worker._run_action, liveaction_db)

            # Wait for the worker up to 10s to add the liveaction to _running_liveactions.
            for i in range(0, int(10 / 0.1)):
                eventlet.sleep(0.1)
                if len(action_worker._running_liveactions) > 0:
                    break

            self.assertEqual(len(action_worker._running_liveactions), 1)

            # Shutdown the worker to trigger the abandon process.
            action_worker.shutdown()
            liveaction_db = LiveAction.get_by_id(liveaction_db.id)

            # Verify that _running_liveactions is empty and the liveaction is abandoned.
            self.assertEqual(len(action_worker._running_liveactions), 0)
            self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_ABANDONED,
                             str(liveaction_db))

        # Make sure the temporary file has been deleted.
        self.assertFalse(os.path.isfile(temp_file))

        # Wait for the local runner to complete. This will activate the finally block in
        # _run_action but will not result in KeyError because the discard method is used to
        # to remove the liveaction from _running_liveactions.
        runner_thread.wait()
Пример #44
0
 def test_execution_creation_chains(self):
     """
     Test children and parent relationship is established.
     """
     childliveaction = self.MODELS['liveactions']['childliveaction.json']
     child_exec = executions_util.create_execution_object(childliveaction)
     parent_exection = self._get_action_execution(
         liveaction__id=childliveaction.context.get('parent', ''))
     child_execs = parent_exection.children
     self.assertTrue(str(child_exec.id) in child_execs)
Пример #45
0
 def test_execution_creation_chains(self):
     """
     Test children and parent relationship is established.
     """
     childliveaction = self.MODELS['liveactions']['childliveaction.yaml']
     child_exec = executions_util.create_execution_object(childliveaction)
     parent_exection = self._get_action_execution(
         liveaction__id=childliveaction.context.get('parent', ''))
     child_execs = parent_exection.children
     self.assertTrue(str(child_exec.id) in child_execs)
Пример #46
0
    def test_delayed_executions_recovery(self):
        # Create a live action that's already delayed pass the allowed timeout.
        dt_now = date_utils.get_datetime_utc_now()
        dt_delta = datetime.timedelta(seconds=cfg.CONF.scheduler.delayed_execution_recovery)
        dt_timeout = dt_now - dt_delta

        liveaction = LiveActionDB(action='wolfpack.action-1',
                                  parameters={'actionstr': 'foo'},
                                  start_timestamp=dt_timeout,
                                  status=action_constants.LIVEACTION_STATUS_DELAYED)

        liveaction = LiveAction.add_or_update(liveaction, publish=False)
        executions.create_execution_object(liveaction, publish=False)

        # Run the rescheduling routine.
        scheduler.recover_delayed_executions()

        # The live action is expected to complete.
        liveaction = LiveAction.get_by_id(str(liveaction.id))
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
Пример #47
0
    def test_state_db_not_created_for_async_actions(self):
        runner_container = get_runner_container()

        params = {"actionstr": "foo", "actionint": 20, "async_test": True}

        liveaction_db = self._get_liveaction_model(
            RunnerContainerTest.async_action_db, params)

        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        # Assert that execution ran without exceptions.
        runner_container.dispatch(liveaction_db)
        states = ActionExecutionState.get_all()
        found = [
            state for state in states if state.execution_id == liveaction_db.id
        ]

        self.assertTrue(
            len(found) == 0, "There should not be a state db object.")
Пример #48
0
    def test_delayed_executions_recovery(self):
        # Create a live action that's already delayed pass the allowed timeout.
        dt_now = date_utils.get_datetime_utc_now()
        dt_delta = datetime.timedelta(seconds=cfg.CONF.scheduler.delayed_execution_recovery)
        dt_timeout = dt_now - dt_delta

        liveaction = LiveActionDB(action='wolfpack.action-1',
                                  parameters={'actionstr': 'foo'},
                                  start_timestamp=dt_timeout,
                                  status=action_constants.LIVEACTION_STATUS_DELAYED)

        liveaction = LiveAction.add_or_update(liveaction, publish=False)
        executions.create_execution_object(liveaction, publish=False)

        # Run the rescheduling routine.
        scheduler.recover_delayed_executions()

        # The live action is expected to complete.
        liveaction = LiveAction.get_by_id(str(liveaction.id))
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
Пример #49
0
    def _create_nested_executions(self, depth=2):
        """Utility function for easily creating nested LiveAction and ActionExecutions for testing

        returns (childmost_liveaction_db, parentmost_liveaction_db)
        """

        if depth <= 0:
            raise Exception("Please provide a depth > 0")

        root_liveaction_db = LiveActionDB()
        root_liveaction_db.status = action_constants.LIVEACTION_STATUS_PAUSED
        root_liveaction_db.action = ACTION_WORKFLOW_REF
        root_liveaction_db = LiveAction.add_or_update(root_liveaction_db)
        root_ex = executions.create_execution_object(root_liveaction_db)

        last_id = root_ex['id']

        # Create children to the specified depth
        for i in range(depth):

            # Childmost liveaction should use ACTION_REF, everything else
            # should use ACTION_WORKFLOW_REF
            if i == depth:
                action = ACTION_REF
            else:
                action = ACTION_WORKFLOW_REF

            child_liveaction_db = LiveActionDB()
            child_liveaction_db.status = action_constants.LIVEACTION_STATUS_PAUSED
            child_liveaction_db.action = action
            child_liveaction_db.context = {
                "parent": {
                    "execution_id": last_id
                }
            }
            child_liveaction_db = LiveAction.add_or_update(child_liveaction_db)
            parent_ex = executions.create_execution_object(child_liveaction_db)
            last_id = parent_ex.id

        # Return the last-created child as well as the root
        return (child_liveaction_db, root_liveaction_db)
Пример #50
0
 def test_execution_creation_manual_action_run(self):
     liveaction = self.MODELS['liveactions']['liveaction1.yaml']
     pre_creation_timestamp = date_utils.get_datetime_utc_now()
     executions_util.create_execution_object(liveaction)
     post_creation_timestamp = date_utils.get_datetime_utc_now()
     execution = self._get_action_execution(liveaction__id=str(liveaction.id),
                                            raise_exception=True)
     self.assertDictEqual(execution.trigger, {})
     self.assertDictEqual(execution.trigger_type, {})
     self.assertDictEqual(execution.trigger_instance, {})
     self.assertDictEqual(execution.rule, {})
     action = action_utils.get_action_by_ref('core.local')
     self.assertDictEqual(execution.action, vars(ActionAPI.from_model(action)))
     runner = RunnerType.get_by_name(action.runner_type['name'])
     self.assertDictEqual(execution.runner, vars(RunnerTypeAPI.from_model(runner)))
     liveaction = LiveAction.get_by_id(str(liveaction.id))
     self.assertEquals(execution.liveaction['id'], str(liveaction.id))
     self.assertEquals(len(execution.log), 1)
     self.assertEquals(execution.log[0]['status'], liveaction.status)
     self.assertGreater(execution.log[0]['timestamp'], pre_creation_timestamp)
     self.assertLess(execution.log[0]['timestamp'], post_creation_timestamp)
Пример #51
0
    def test_dispatch(self):
        runner_container = get_runner_container()
        params = {
            'actionstr': 'bar'
        }
        liveaction_db = self._get_action_exec_db_model(RunnerContainerTest.action_db, params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)
        # Assert that execution ran successfully.
        runner_container.dispatch(liveaction_db)
        liveaction_db = LiveAction.get_by_id(liveaction_db.id)
        result = liveaction_db.result
        self.assertTrue(result.get('action_params').get('actionint') == 10)
        self.assertTrue(result.get('action_params').get('actionstr') == 'bar')

        # Assert that context is written correctly.
        context = {
            'user': '******',
            'third_party_system': {
                'ref_id': '1234'
            }
        }

        self.assertDictEqual(liveaction_db.context, context)
Пример #52
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")
Пример #53
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.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)
Пример #54
0
    def test_post_run_is_always_called_after_run(self):
        # 1. post_run should be called on success, failure, etc.
        runner_container = get_runner_container()
        params = {
            'actionstr': 'bar',
            'mock_status': action_constants.LIVEACTION_STATUS_SUCCEEDED
        }
        liveaction_db = self._get_failingaction_exec_db_model(params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        global global_runner
        global_runner = None
        original_get_runner = runner_container._get_runner

        def mock_get_runner(*args, **kwargs):
            global global_runner
            runner = original_get_runner(*args, **kwargs)
            global_runner = runner
            return runner
        runner_container._get_runner = mock_get_runner

        # Note: We can't assert here that post_run hasn't been called yet because runner instance
        # is only instantiated later inside dispatch method
        runner_container.dispatch(liveaction_db)
        self.assertTrue(global_runner.post_run_called)

        # 2. Verify post_run is called if run() throws
        runner_container = get_runner_container()
        params = {
            'actionstr': 'bar',
            'raise': True
        }
        liveaction_db = self._get_failingaction_exec_db_model(params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        global_runner = None
        original_get_runner = runner_container._get_runner

        def mock_get_runner(*args, **kwargs):
            global global_runner
            runner = original_get_runner(*args, **kwargs)
            global_runner = runner
            return runner
        runner_container._get_runner = mock_get_runner

        # Note: We can't assert here that post_run hasn't been called yet because runner instance
        # is only instantiated later inside dispatch method
        runner_container.dispatch(liveaction_db)
        self.assertTrue(global_runner.post_run_called)

        # 2. Verify post_run is also called if _delete_auth_token throws
        runner_container = get_runner_container()
        runner_container._delete_auth_token = mock.Mock(side_effect=ValueError('throw'))
        params = {
            'actionstr': 'bar',
            'mock_status': action_constants.LIVEACTION_STATUS_SUCCEEDED
        }
        liveaction_db = self._get_failingaction_exec_db_model(params)
        liveaction_db = LiveAction.add_or_update(liveaction_db)
        executions.create_execution_object(liveaction_db)

        global_runner = None
        original_get_runner = runner_container._get_runner

        def mock_get_runner(*args, **kwargs):
            global global_runner
            runner = original_get_runner(*args, **kwargs)
            global_runner = runner
            return runner
        runner_container._get_runner = mock_get_runner

        # Note: We can't assert here that post_run hasn't been called yet because runner instance
        # is only instantiated later inside dispatch method
        runner_container.dispatch(liveaction_db)
        self.assertTrue(global_runner.post_run_called)
Пример #55
0
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
Пример #56
0
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
Пример #57
0
def create_request(liveaction, action_db=None, runnertype_db=None):
    """
    Create an action execution.

    :param action_db: Action model to operate one. If not provided, one is retrieved from the
                      database using values from "liveaction".
    :type action_db: :class:`ActionDB`

    :param runnertype_db: Runner model to operate one. If not provided, one is retrieved from the
                          database using values from "liveaction".
    :type runnertype_db: :class:`RunnerTypeDB`

    :return: (liveaction, execution)
    :rtype: tuple
    """
    # We import this here to avoid conflicts w/ runners that might import this
    # file since the runners don't have the config context by default.
    from st2common.metrics.base import get_driver

    # 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.
    parent_context = executions.get_parent_context(liveaction) or {}
    parent_user = parent_context.get('user', None)

    if parent_user:
        liveaction.context['user'] = parent_user

    # Validate action
    if not action_db:
        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)

    if not runnertype_db:
        runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name'])

    if not hasattr(liveaction, 'parameters'):
        liveaction.parameters = dict()

    # For consistency add pack to the context here in addition to RunnerContainer.dispatch() method
    liveaction.context['pack'] = action_db.pack

    # Validate action parameters.
    schema = util_schema.get_schema_for_action_parameters(action_db, runnertype_db)
    validator = util_schema.get_validator()
    util_schema.validate(liveaction.parameters, schema, validator, use_default=True,
                         allow_default_none=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 not _is_notify_empty(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()

    # Set the "action_is_workflow" attribute
    liveaction.action_is_workflow = action_db.is_workflow()

    # 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 db_exc.StackStormDBObjectNotFoundError as e:
        _cleanup_liveaction(liveaction)
        raise trace_exc.TraceNotFoundException(six.text_type(e))

    execution = executions.create_execution_object(liveaction=liveaction, action_db=action_db,
                                                   runnertype_db=runnertype_db, publish=False)

    if trace_db:
        trace_service.add_or_update_given_trace_db(
            trace_db=trace_db,
            action_executions=[
                trace_service.get_trace_component_for_action_execution(execution, liveaction)
            ])

    get_driver().inc_counter('action.executions.%s' % (liveaction.status))

    return liveaction, execution