Merge "option to rollback action_plan when it fails"
This commit is contained in:
commit
25a0b184a1
@ -25,8 +25,11 @@ from taskflow import task as flow_task
|
||||
|
||||
from watcher.applier.workflow_engine import base
|
||||
from watcher.common import exception
|
||||
from watcher import conf
|
||||
from watcher import objects
|
||||
|
||||
CONF = conf.CONF
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
@ -127,9 +130,11 @@ class DefaultWorkFlowEngine(base.BaseWorkFlowEngine):
|
||||
|
||||
class TaskFlowActionContainer(base.BaseTaskFlowActionContainer):
|
||||
def __init__(self, db_action, engine):
|
||||
name = "action_type:{0} uuid:{1}".format(db_action.action_type,
|
||||
db_action.uuid)
|
||||
super(TaskFlowActionContainer, self).__init__(name, db_action, engine)
|
||||
self.name = "action_type:{0} uuid:{1}".format(db_action.action_type,
|
||||
db_action.uuid)
|
||||
super(TaskFlowActionContainer, self).__init__(self.name,
|
||||
db_action,
|
||||
engine)
|
||||
|
||||
def do_pre_execute(self):
|
||||
db_action = self.engine.notify(self._db_action,
|
||||
@ -158,6 +163,12 @@ class TaskFlowActionContainer(base.BaseTaskFlowActionContainer):
|
||||
self.action.post_condition()
|
||||
|
||||
def do_revert(self, *args, **kwargs):
|
||||
# NOTE: Not rollback action plan
|
||||
if not CONF.watcher_applier.rollback_when_actionplan_failed:
|
||||
LOG.info("Failed actionplan rollback option is turned off, and "
|
||||
"the following action will be skipped: %s", self.name)
|
||||
return
|
||||
|
||||
LOG.warning("Revert action: %s", self.name)
|
||||
try:
|
||||
# TODO(jed): do we need to update the states in case of failure?
|
||||
|
@ -43,11 +43,20 @@ APPLIER_MANAGER_OPTS = [
|
||||
help='Select the engine to use to execute the workflow'),
|
||||
]
|
||||
|
||||
APPLIER_OPTS = [
|
||||
cfg.BoolOpt('rollback_when_actionplan_failed',
|
||||
default=False,
|
||||
help='If set True, the failed actionplan will rollback '
|
||||
'when executing. Defaule value is False.'),
|
||||
]
|
||||
|
||||
|
||||
def register_opts(conf):
|
||||
conf.register_group(watcher_applier)
|
||||
conf.register_opts(APPLIER_MANAGER_OPTS, group=watcher_applier)
|
||||
conf.register_opts(APPLIER_OPTS, group=watcher_applier)
|
||||
|
||||
|
||||
def list_opts():
|
||||
return [(watcher_applier, APPLIER_MANAGER_OPTS)]
|
||||
return [(watcher_applier, APPLIER_MANAGER_OPTS),
|
||||
(watcher_applier, APPLIER_OPTS)]
|
||||
|
@ -19,6 +19,8 @@
|
||||
import eventlet
|
||||
from unittest import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from watcher.applier.workflow_engine import default as tflow
|
||||
from watcher.common import clients
|
||||
from watcher.common import nova_helper
|
||||
@ -111,3 +113,52 @@ class TestTaskFlowActionContainer(base.DbTestCase):
|
||||
mock_eventlet_spawn.return_value = et
|
||||
action_container.execute()
|
||||
et.kill.assert_called_with()
|
||||
|
||||
@mock.patch('watcher.applier.workflow_engine.default.LOG')
|
||||
def test_execute_without_rollback(self, mock_log):
|
||||
action_plan = obj_utils.create_test_action_plan(
|
||||
self.context, audit_id=self.audit.id,
|
||||
strategy_id=self.strategy.id,
|
||||
state=objects.action_plan.State.ONGOING)
|
||||
|
||||
action = obj_utils.create_test_action(
|
||||
self.context, action_plan_id=action_plan.id,
|
||||
state=objects.action.State.FAILED,
|
||||
action_type='nop',
|
||||
input_parameters={'message': 'hello World'})
|
||||
action_container = tflow.TaskFlowActionContainer(
|
||||
db_action=action,
|
||||
engine=self.engine)
|
||||
|
||||
cfg.CONF.set_override("rollback_when_actionplan_failed", False,
|
||||
group="watcher_applier")
|
||||
action_name = "action_type:{0} uuid:{1}".format(action.action_type,
|
||||
action.uuid)
|
||||
expected_log = ('Failed actionplan rollback option is turned off, '
|
||||
'and the following action will be skipped: %s')
|
||||
action_container.revert()
|
||||
mock_log.info.assert_called_once_with(expected_log, action_name)
|
||||
|
||||
@mock.patch('watcher.applier.workflow_engine.default.LOG')
|
||||
def test_execute_with_rollback(self, mock_log):
|
||||
action_plan = obj_utils.create_test_action_plan(
|
||||
self.context, audit_id=self.audit.id,
|
||||
strategy_id=self.strategy.id,
|
||||
state=objects.action_plan.State.ONGOING)
|
||||
|
||||
action = obj_utils.create_test_action(
|
||||
self.context, action_plan_id=action_plan.id,
|
||||
state=objects.action.State.FAILED,
|
||||
action_type='nop',
|
||||
input_parameters={'message': 'hello World'})
|
||||
action_container = tflow.TaskFlowActionContainer(
|
||||
db_action=action,
|
||||
engine=self.engine)
|
||||
|
||||
cfg.CONF.set_override("rollback_when_actionplan_failed", True,
|
||||
group="watcher_applier")
|
||||
action_name = "action_type:{0} uuid:{1}".format(action.action_type,
|
||||
action.uuid)
|
||||
expected_log = 'Revert action: %s'
|
||||
action_container.revert()
|
||||
mock_log.warning.assert_called_once_with(expected_log, action_name)
|
||||
|
Loading…
Reference in New Issue
Block a user