コード例 #1
0
 def test_update_failed_replace_not_found(self):
     wf = self._create_resource('workflow',
                                workflow_template_update_replace)
     t = template_format.parse(workflow_template_update_replace_failed)
     rsrc_defns = template.Template(t).resource_definitions(self.stack)
     new_wf = rsrc_defns['workflow']
     self.mistral.workflows.update.side_effect = Exception('boom!')
     self.assertRaises(exception.ResourceFailure,
                       scheduler.TaskRunner(wf.update, new_wf))
     self.assertEqual((wf.UPDATE, wf.FAILED), wf.state)
     self.mistral.workflows.get.side_effect = [
         mistral_base.APIException(error_code=404)
     ]
     self.assertRaises(resource.UpdateReplace,
                       scheduler.TaskRunner(wf.update, new_wf))
コード例 #2
0
    def update(self, id, state=None, output=None):
        self._ensure_not_empty(id=id)

        if not (state or output):
            raise base.APIException(
                400,
                "Please provide either state or output for action execution.")

        data = {}
        if state:
            data['state'] = state

        if output:
            data['output'] = output

        return self._update('/action_executions/%s' % id, data)
コード例 #3
0
ファイル: test_clients.py プロジェクト: wxy8961230/heat
class TestIsNotFound(common.HeatTestCase):

    scenarios = [
        ('aodh_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='aodh',
             exception=lambda: aodh_exc.NotFound('not found'),
         )),
        ('aodh_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='aodh',
             exception=lambda: aodh_exc.OverLimit('over'),
         )),
        ('aodh_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='aodh',
             exception=lambda: aodh_exc.Conflict('conflict'),
         )),
        ('cinder_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='cinder',
             exception=lambda: cinder_exc.NotFound(code=404),
         )),
        ('cinder_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='cinder',
              exception=lambda: Exception())),
        ('cinder_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='cinder',
             exception=lambda: cinder_exc.OverLimit(code=413),
         )),
        ('cinder_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='cinder',
             exception=lambda: cinder_exc.ClientException(code=409,
                                                          message='conflict'),
         )),
        ('glance_not_found_1',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='glance',
             exception=lambda: client_exception.EntityMatchNotFound(),
         )),
        ('glance_not_found_2',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='glance',
             exception=lambda: glance_exc.HTTPNotFound(),
         )),
        ('glance_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='glance',
              exception=lambda: Exception())),
        ('glance_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='glance',
             exception=lambda: glance_exc.HTTPOverLimit(details='over'),
         )),
        ('glance_conflict_1',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='glance',
             exception=lambda: glance_exc.Conflict(),
         )),
        ('heat_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='heat',
             exception=lambda: heat_exc.HTTPNotFound(message='gone'),
         )),
        ('heat_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='heat',
              exception=lambda: Exception())),
        ('heat_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='heat',
             exception=lambda: heat_exc.HTTPOverLimit(message='over'),
         )),
        ('heat_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='heat',
             exception=lambda: heat_exc.HTTPConflict(),
         )),
        ('keystone_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='keystone',
             exception=lambda: keystone_exc.NotFound(details='gone'),
         )),
        ('keystone_entity_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='keystone',
             exception=lambda: exception.EntityNotFound(),
         )),
        ('keystone_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='keystone',
              exception=lambda: Exception())),
        ('keystone_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='keystone',
             exception=lambda: keystone_exc.RequestEntityTooLarge(details=
                                                                  'over'),
         )),
        ('keystone_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='keystone',
             exception=lambda: keystone_exc.Conflict(message='Conflict'),
         )),
        ('neutron_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='neutron',
             exception=lambda: neutron_exc.NotFound,
         )),
        ('neutron_network_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='neutron',
             exception=lambda: neutron_exc.NetworkNotFoundClient(),
         )),
        ('neutron_port_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='neutron',
             exception=lambda: neutron_exc.PortNotFoundClient(),
         )),
        ('neutron_status_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='neutron',
             exception=lambda: neutron_exc.NeutronClientException(status_code=
                                                                  404),
         )),
        ('neutron_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='neutron',
              exception=lambda: Exception())),
        ('neutron_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='neutron',
             exception=lambda: neutron_exc.NeutronClientException(status_code=
                                                                  413),
         )),
        ('neutron_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='neutron',
             exception=lambda: neutron_exc.Conflict(),
         )),
        ('nova_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             is_unprocessable_entity=False,
             plugin='nova',
             exception=lambda: fakes_nova.fake_exception(),
         )),
        ('nova_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              is_unprocessable_entity=False,
              plugin='nova',
              exception=lambda: Exception())),
        ('nova_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             is_unprocessable_entity=False,
             plugin='nova',
             exception=lambda: fakes_nova.fake_exception(413),
         )),
        ('nova_unprocessable_entity',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             is_unprocessable_entity=True,
             plugin='nova',
             exception=lambda: fakes_nova.fake_exception(422),
         )),
        ('nova_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             is_unprocessable_entity=False,
             plugin='nova',
             exception=lambda: fakes_nova.fake_exception(409),
         )),
        ('openstack_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             is_unprocessable_entity=False,
             plugin='openstack',
             exception=lambda: exceptions.ResourceNotFound,
         )),
        ('swift_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='swift',
             exception=lambda: swift_exc.ClientException(msg='gone',
                                                         http_status=404),
         )),
        ('swift_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='swift',
              exception=lambda: Exception())),
        ('swift_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='swift',
             exception=lambda: swift_exc.ClientException(msg='ouch',
                                                         http_status=413),
         )),
        ('swift_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='swift',
             exception=lambda: swift_exc.ClientException(msg='conflict',
                                                         http_status=409),
         )),
        ('trove_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='trove',
             exception=lambda: troveclient.exceptions.NotFound(message='gone'),
         )),
        ('trove_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='trove',
              exception=lambda: Exception())),
        ('trove_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='trove',
             exception=lambda: troveclient.exceptions.RequestEntityTooLarge(
                 message='over'),
         )),
        ('trove_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='trove',
             exception=lambda: troveclient.exceptions.Conflict(message=
                                                               'Conflict'),
         )),
        ('sahara_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='sahara',
             exception=lambda: sahara_base.APIException(error_message='gone1',
                                                        error_code=404),
         )),
        ('sahara_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='sahara',
              exception=lambda: Exception())),
        ('sahara_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='sahara',
             exception=lambda: sahara_base.APIException(error_message='over1',
                                                        error_code=413),
         )),
        ('sahara_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='sahara',
             exception=lambda: sahara_base.APIException(
                 error_message='conflict1', error_code=409),
         )),
        ('zaqar_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='zaqar',
             exception=lambda: zaqar_exc.ResourceNotFound(),
         )),
        ('manila_not_found',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=False,
             plugin='manila',
             exception=lambda: manila_exc.NotFound(),
         )),
        ('manila_exception',
         dict(is_not_found=False,
              is_over_limit=False,
              is_client_exception=False,
              is_conflict=False,
              plugin='manila',
              exception=lambda: Exception())),
        ('manila_overlimit',
         dict(
             is_not_found=False,
             is_over_limit=True,
             is_client_exception=True,
             is_conflict=False,
             plugin='manila',
             exception=lambda: manila_exc.RequestEntityTooLarge(),
         )),
        ('manila_conflict',
         dict(
             is_not_found=False,
             is_over_limit=False,
             is_client_exception=True,
             is_conflict=True,
             plugin='manila',
             exception=lambda: manila_exc.Conflict(),
         )),
        ('mistral_not_found1',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=False,
             is_conflict=False,
             plugin='mistral',
             exception=lambda: mistral_base.APIException(404),
         )),
        ('mistral_not_found2',
         dict(
             is_not_found=True,
             is_over_limit=False,
             is_client_exception=False,
             is_conflict=False,
             plugin='mistral',
             exception=lambda: keystone_exc.NotFound(),
         )),
    ]

    def test_is_not_found(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)
        try:
            raise self.exception()
        except Exception as e:
            if self.is_not_found != client_plugin.is_not_found(e):
                raise

    def test_ignore_not_found(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)
        try:
            exp = self.exception()
            exp_class = exp.__class__
            raise exp
        except Exception as e:
            if self.is_not_found:
                client_plugin.ignore_not_found(e)
            else:
                self.assertRaises(exp_class, client_plugin.ignore_not_found, e)

    def test_ignore_not_found_context_manager(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)

        exp = self.exception()
        exp_class = exp.__class__

        def try_raise():
            with client_plugin.ignore_not_found:
                raise exp

        if self.is_not_found:
            try_raise()
        else:
            self.assertRaises(exp_class, try_raise)

    def test_ignore_conflict_and_not_found(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)
        try:
            exp = self.exception()
            exp_class = exp.__class__
            raise exp
        except Exception as e:
            if self.is_conflict or self.is_not_found:
                client_plugin.ignore_conflict_and_not_found(e)
            else:
                self.assertRaises(exp_class,
                                  client_plugin.ignore_conflict_and_not_found,
                                  e)

    def test_ignore_conflict_and_not_found_context_manager(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)

        exp = self.exception()
        exp_class = exp.__class__

        def try_raise():
            with client_plugin.ignore_conflict_and_not_found:
                raise exp

        if self.is_conflict or self.is_not_found:
            try_raise()
        else:
            self.assertRaises(exp_class, try_raise)

    def test_is_over_limit(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)
        try:
            raise self.exception()
        except Exception as e:
            if self.is_over_limit != client_plugin.is_over_limit(e):
                raise

    def test_is_client_exception(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)
        try:
            raise self.exception()
        except Exception as e:
            ice = self.is_client_exception
            actual = client_plugin.is_client_exception(e)
            if ice != actual:
                raise

    def test_is_conflict(self):
        con = mock.Mock()
        c = clients.Clients(con)
        client_plugin = c.client_plugin(self.plugin)
        try:
            raise self.exception()
        except Exception as e:
            if self.is_conflict != client_plugin.is_conflict(e):
                raise

    def test_is_unprocessable_entity(self):
        con = mock.Mock()
        c = clients.Clients(con)
        # only 'nova' client plugin need to check this exception
        if self.plugin == 'nova':
            client_plugin = c.client_plugin(self.plugin)
            try:
                raise self.exception()
            except Exception as e:
                iue = self.is_unprocessable_entity
                if iue != client_plugin.is_unprocessable_entity(e):
                    raise
コード例 #4
0
class MistralQuerierTest(DbTestCase):
    @classmethod
    def setUpClass(cls):
        super(MistralQuerierTest, cls).setUpClass()

        # Override the retry configuration here otherwise st2tests.config.parse_args
        # in DbTestCase.setUpClass will reset these overrides.
        cfg.CONF.set_override('retry_exp_msec', 100, group='mistral')
        cfg.CONF.set_override('retry_exp_max_msec', 200, group='mistral')
        cfg.CONF.set_override('retry_stop_max_msec', 200, group='mistral')

        # Register query module.
        cls.query_module = get_query_module('mistral-v2')

    def setUp(self):
        super(MistralQuerierTest, self).setUp()
        self.querier = self.query_module.get_instance()

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_running_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_succeeded_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'SUCCESS', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_succeeded_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'SUCCESS', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_succeeded_tasks_completed_child_running(
            self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'SUCCESS', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_failed_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'ERROR', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_failed_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'ERROR', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_waiting(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_WAITING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_PAUSED,
                           MOCK_CHILD_ACTIONEXECUTION_PAUSED
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_paused(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_PAUSED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_running_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_canceling_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_running_tasks_waiting(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'RUNNING', MOCK_WF_TASKS_WAITING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_cancelled_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'CANCELLED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_PAUSED,
                           MOCK_CHILD_ACTIONEXECUTION_PAUSED
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_completed_child_running(
            self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_PAUSED,
                           MOCK_CHILD_ACTIONEXECUTION_PAUSED
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_paused(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_PAUSED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_pausing_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_paused_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_paused_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'PAUSED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_resuming_exec_paused_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RESUMING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_resuming_exec_running_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_resuming_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_resuming_exec_paused_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'PAUSED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_resuming_exec_canceled_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'CANCELLED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    def test_get_workflow_result(self):
        result = self.querier._get_workflow_result(uuid.uuid4().hex,
                                                   uuid.uuid4().hex)

        expected = {
            'k1': 'v1',
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        self.assertDictEqual(expected, result)

    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    def test_get_workflow_tasks(self):
        tasks = self.querier._get_workflow_tasks(uuid.uuid4().hex,
                                                 uuid.uuid4().hex)

        expected = copy.deepcopy(MOCK_WF_EX_TASKS_DATA)
        for task in expected:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        for i in range(0, len(tasks)):
            self.assertDictEqual(expected[i], tasks[i])

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(
            return_value=MOCK_LIVEACTION_RUNNING_WITH_STREAMING_RESULT))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=[MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(tasks.TaskManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS[1]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_with_last_query_time(self):
        last_query_time = time.time() - 3

        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT,
                                              last_query_time=last_query_time)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(side_effect=db_exc.StackStormDBObjectNotFoundError()))
    def test_query_liveaction_not_found(self):
        self.assertRaises(db_exc.StackStormDBObjectNotFoundError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(
            side_effect=[requests.exceptions.ConnectionError(), MOCK_WF_EX]))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_get_workflow_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        calls = [
            call(MOCK_QRY_CONTEXT['mistral']['execution_id'])
            for i in range(0, 2)
        ]
        executions.ExecutionManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_get_workflow_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        calls = [
            call(MOCK_QRY_CONTEXT['mistral']['execution_id'])
            for i in range(0, 2)
        ]
        executions.ExecutionManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(side_effect=mistralclient_base.APIException(
            error_code=404, error_message='Workflow not found.')))
    def test_query_get_workflow_not_found(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)
        self.assertEqual('Workflow not found.', result)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(
        tasks.TaskManager, 'list',
        mock.MagicMock(side_effect=[
            requests.exceptions.ConnectionError(), MOCK_WF_EX_TASKS
        ]))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_list_workflow_tasks_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        mock_call = call(
            workflow_execution_id=MOCK_QRY_CONTEXT['mistral']['execution_id'])
        calls = [mock_call for i in range(0, 2)]
        tasks.TaskManager.list.assert_has_calls(calls)

        calls = [call(MOCK_WF_EX_TASKS[0].id), call(MOCK_WF_EX_TASKS[1].id)]
        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(tasks.TaskManager, 'get',
                       mock.MagicMock(side_effect=[
                           requests.exceptions.ConnectionError(),
                           MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]
                       ]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_get_workflow_tasks_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        calls = [
            call(MOCK_WF_EX_TASKS[0].id),
            call(MOCK_WF_EX_TASKS[0].id),
            call(MOCK_WF_EX_TASKS[1].id)
        ]

        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(
        tasks.TaskManager, 'list',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_list_workflow_tasks_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        mock_call = call(
            workflow_execution_id=MOCK_QRY_CONTEXT['mistral']['execution_id'])
        calls = [mock_call for i in range(0, 2)]
        tasks.TaskManager.list.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_get_workflow_tasks_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        calls = [call(MOCK_WF_EX_TASKS[0].id), call(MOCK_WF_EX_TASKS[0].id)]

        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=mistralclient_base.APIException(
            error_code=404, error_message='Task not found.')))
    def test_query_get_workflow_tasks_not_found(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)
        self.assertEqual('Task not found.', result)

    def test_query_missing_context(self):
        self.assertRaises(Exception, self.querier.query, uuid.uuid4().hex, {})

    def test_query_missing_mistral_execution_id(self):
        self.assertRaises(Exception, self.querier.query,
                          uuid.uuid4().hex, {'mistral': {}})

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(
            return_value=
            MOCK_LIVEACTION_RUNNING_WITH_OUTDATED_INCOMPLETE_TASKS_STREAMING_RESULT
        ))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_INCOMPLETE_TASKS)
                       )
    @mock.patch.object(tasks.TaskManager, 'get',
                       mock.MagicMock(side_effect=MOCK_WF_EX_INCOMPLETE_TASKS))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_with_outdated_tasks_in_liveaction_result(self):
        last_query_time = time.time() + 3

        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT,
                                              last_query_time=last_query_time)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_INCOMPLETE_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(
            return_value=
            MOCK_LIVEACTION_RUNNING_WITH_UP_TO_DATE_INCOMPLETE_TASKS_STREAMING_RESULT
        ))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_INCOMPLETE_TASKS)
                       )
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(return_value=MOCK_WF_EX_INCOMPLETE_TASKS[1]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_with_up_to_date_tasks_in_liveaction_result(self):
        last_query_time = time.time() + 3

        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT,
                                              last_query_time=last_query_time)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_INCOMPLETE_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_REQUESTED,
                           MOCK_CHILD_ACTIONEXECUTION_REQUESTED
                       ]))
    def test_orphaned_execution_child_in_requested_state(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)
コード例 #5
0
class MistralQuerierTest(DbTestCase):
    @classmethod
    def setUpClass(cls):
        super(MistralQuerierTest, cls).setUpClass()

        # Override the retry configuration here otherwise st2tests.config.parse_args
        # in DbTestCase.setUpClass will reset these overrides.
        cfg.CONF.set_override('retry_exp_msec', 100, group='mistral')
        cfg.CONF.set_override('retry_exp_max_msec', 200, group='mistral')
        cfg.CONF.set_override('retry_stop_max_msec', 200, group='mistral')

        # Register query module.
        cls.query_module = loader.register_query_module('mistral_v2')

    def setUp(self):
        super(MistralQuerierTest, self).setUp()
        self.querier = self.query_module.get_instance()

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_running_tasks_running(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'RUNNING', MOCK_WF_TASKS_RUNNING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_running_tasks_completed(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)
        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_succeeded_tasks_completed(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'SUCCESS', MOCK_WF_TASKS_SUCCEEDED)
        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_succeeded_tasks_running(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'SUCCESS', MOCK_WF_TASKS_RUNNING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_errored_tasks_completed(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'ERROR', MOCK_WF_TASKS_SUCCEEDED)
        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_errored_tasks_running(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'ERROR', MOCK_WF_TASKS_RUNNING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=True))
    def test_determine_status_wf_canceled_tasks_completed(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'CANCELLED', MOCK_WF_TASKS_SUCCEEDED)
        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=True))
    def test_determine_status_wf_canceled_tasks_running(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'CANCELLED', MOCK_WF_TASKS_RUNNING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=True))
    def test_determine_status_wf_canceled_tasks_waiting(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'CANCELLED', MOCK_WF_TASKS_WAITING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=True))
    def test_determine_status_wf_canceled_exec_running_tasks_completed(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)
        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=True))
    def test_determine_status_wf_canceled_exec_running_tasks_running(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'RUNNING', MOCK_WF_TASKS_RUNNING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=True))
    def test_determine_status_wf_canceled_exec_running_tasks_waiting(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'RUNNING', MOCK_WF_TASKS_WAITING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_running_exec_paused_tasks_completed(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)
        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_determine_status_wf_running_exec_cancelled_tasks_running(self):
        wf_id = uuid.uuid4().hex
        status = self.querier._determine_execution_status(
            wf_id, 'CANCELLED', MOCK_WF_TASKS_RUNNING)
        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    def test_get_workflow_result(self):
        result = self.querier._get_workflow_result(uuid.uuid4().hex)

        expected = {
            'k1': 'v1',
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        self.assertDictEqual(expected, result)

    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    def test_get_workflow_tasks(self):
        tasks = self.querier._get_workflow_tasks(uuid.uuid4().hex)

        expected = copy.deepcopy(MOCK_WF_EX_TASKS_DATA)
        for task in expected:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        for i in range(0, len(tasks)):
            self.assertDictEqual(expected[i], tasks[i])

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_query(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(
            side_effect=[requests.exceptions.ConnectionError(), MOCK_WF_EX]))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_query_get_workflow_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        calls = [
            call(MOCK_QRY_CONTEXT['mistral']['execution_id'])
            for i in range(0, 2)
        ]
        executions.ExecutionManager.get.assert_has_calls(calls)

    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_get_workflow_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        calls = [
            call(MOCK_QRY_CONTEXT['mistral']['execution_id'])
            for i in range(0, 2)
        ]
        executions.ExecutionManager.get.assert_has_calls(calls)

    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(side_effect=mistralclient_base.APIException(
            error_code=404, error_message='Workflow not found.')))
    def test_query_get_workflow_not_found(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)
        self.assertEqual('Workflow not found.', result)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(
        tasks.TaskManager, 'list',
        mock.MagicMock(side_effect=[
            requests.exceptions.ConnectionError(), MOCK_WF_EX_TASKS
        ]))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_query_list_workflow_tasks_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        mock_call = call(
            workflow_execution_id=MOCK_QRY_CONTEXT['mistral']['execution_id'])
        calls = [mock_call for i in range(0, 2)]
        tasks.TaskManager.list.assert_has_calls(calls)

        calls = [call(MOCK_WF_EX_TASKS[0].id), call(MOCK_WF_EX_TASKS[1].id)]
        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(tasks.TaskManager, 'get',
                       mock.MagicMock(side_effect=[
                           requests.exceptions.ConnectionError(),
                           MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]
                       ]))
    @mock.patch.object(action_service, 'is_action_canceled_or_canceling',
                       mock.MagicMock(return_value=False))
    def test_query_get_workflow_tasks_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        calls = [
            call(MOCK_WF_EX_TASKS[0].id),
            call(MOCK_WF_EX_TASKS[0].id),
            call(MOCK_WF_EX_TASKS[1].id)
        ]

        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(
        tasks.TaskManager, 'list',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_list_workflow_tasks_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        mock_call = call(
            workflow_execution_id=MOCK_QRY_CONTEXT['mistral']['execution_id'])
        calls = [mock_call for i in range(0, 2)]
        tasks.TaskManager.list.assert_has_calls(calls)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_get_workflow_tasks_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        calls = [call(MOCK_WF_EX_TASKS[0].id), call(MOCK_WF_EX_TASKS[0].id)]

        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=mistralclient_base.APIException(
            error_code=404, error_message='Task not found.')))
    def test_query_get_workflow_tasks_not_found(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)
        self.assertEqual('Task not found.', result)

    def test_query_missing_context(self):
        self.assertRaises(Exception, self.querier.query, uuid.uuid4().hex, {})

    def test_query_missing_mistral_execution_id(self):
        self.assertRaises(Exception, self.querier.query,
                          uuid.uuid4().hex, {'mistral': {}})