Merge "option to rollback action_plan when it fails"

This commit is contained in:
Zuul 2020-08-18 07:55:59 +00:00 committed by Gerrit Code Review
commit 25a0b184a1
3 changed files with 75 additions and 4 deletions

View File

@ -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?

View File

@ -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)]

View File

@ -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)