From 5814914aeffdf6c92096b67aa78fb10e497d8ff1 Mon Sep 17 00:00:00 2001 From: Hidekazu Nakamura Date: Wed, 27 Sep 2017 16:37:35 +0900 Subject: [PATCH] Fix action plan state change when action failed Since default workflow engine action container do_execute method does not raise exception when action failed, workflow engine action container execute method never raise exception and action plan state becomes always SUCCEEDED. This patch fixes default workflow engine action container do_execute method to raise exception when action does not return True. Change-Id: I7eeef69dbdfb5d40e3cf0b1004cbfe199a16bf7b Closes-Bug: #1719793 --- watcher/applier/workflow_engine/default.py | 6 ++++-- watcher/common/exception.py | 4 ++++ .../applier/workflow_engine/test_default_workflow_engine.py | 5 +++-- .../workflow_engine/test_taskflow_action_container.py | 5 ++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/watcher/applier/workflow_engine/default.py b/watcher/applier/workflow_engine/default.py index 8c4950c16..157cb9848 100644 --- a/watcher/applier/workflow_engine/default.py +++ b/watcher/applier/workflow_engine/default.py @@ -127,8 +127,10 @@ class TaskFlowActionContainer(base.BaseTaskFlowActionContainer): return self.engine.notify(self._db_action, objects.action.State.SUCCEEDED) else: - return self.engine.notify(self._db_action, - objects.action.State.FAILED) + self.engine.notify(self._db_action, + objects.action.State.FAILED) + raise exception.ActionExecutionFailure( + action_id=self._db_action.uuid) def do_post_execute(self): LOG.debug("Post-condition action: %s", self.name) diff --git a/watcher/common/exception.py b/watcher/common/exception.py index dabfae897..3eb36b251 100644 --- a/watcher/common/exception.py +++ b/watcher/common/exception.py @@ -435,6 +435,10 @@ class ActionDescriptionNotFound(ResourceNotFound): msg_fmt = _("The action description %(action_id)s cannot be found.") +class ActionExecutionFailure(WatcherException): + msg_fmt = _("The action %(action_id)s execution failed.") + + # Model class ComputeResourceNotFound(WatcherException): diff --git a/watcher/tests/applier/workflow_engine/test_default_workflow_engine.py b/watcher/tests/applier/workflow_engine/test_default_workflow_engine.py index fdf902c0b..b4f10041b 100644 --- a/watcher/tests/applier/workflow_engine/test_default_workflow_engine.py +++ b/watcher/tests/applier/workflow_engine/test_default_workflow_engine.py @@ -51,7 +51,7 @@ class FakeAction(abase.BaseAction): pass def execute(self): - raise ExpectedException() + return False def get_description(self): return "fake action, just for test" @@ -311,7 +311,8 @@ class TestDefaultWorkFlowEngine(base.DbTestCase): exc = self.assertRaises(exception.WorkflowExecutionException, self.engine.execute, actions) - self.assertIsInstance(exc.kwargs['error'], ExpectedException) + self.assertIsInstance(exc.kwargs['error'], + exception.ActionExecutionFailure) self.check_action_state(actions[0], objects.action.State.FAILED) @mock.patch.object(objects.ActionPlan, "get_by_uuid") diff --git a/watcher/tests/applier/workflow_engine/test_taskflow_action_container.py b/watcher/tests/applier/workflow_engine/test_taskflow_action_container.py index 4139abbd7..e591a6b06 100644 --- a/watcher/tests/applier/workflow_engine/test_taskflow_action_container.py +++ b/watcher/tests/applier/workflow_engine/test_taskflow_action_container.py @@ -21,6 +21,7 @@ import mock from watcher.applier.workflow_engine import default as tflow from watcher.common import clients +from watcher.common import exception from watcher.common import nova_helper from watcher import objects from watcher.tests.db import base @@ -79,7 +80,9 @@ class TestTaskFlowActionContainer(base.DbTestCase): action_container = tflow.TaskFlowActionContainer( db_action=action, engine=self.engine) - action_container.execute() + + self.assertRaises(exception.ActionExecutionFailure, + action_container.execute, action_id=action.uuid) self.assertTrue(action.state, objects.action.State.FAILED)