Make sure target state is cleared on stable states

When a node moves to a stable provisioning state and there's no extra
processing to be done (callback) we have to make sure that the
target_provision_state is cleared (set to None) indicating that the node
is not transitioning to any other state.

Closes-Bug: #1557497
Change-Id: Id4f05ed3c6acbeda07a726049e2857fcb96338db
This commit is contained in:
Lucas Alvares Gomes 2016-03-16 16:37:54 +00:00
parent db1029ab1b
commit aa4d3fa022
5 changed files with 41 additions and 7 deletions

View File

@ -176,6 +176,9 @@ UPDATE_ALLOWED_STATES = (DEPLOYFAIL, INSPECTING, INSPECTFAIL, CLEANFAIL, ERROR,
DELETE_ALLOWED_STATES = (AVAILABLE, NOSTATE, MANAGEABLE, ENROLL)
"""States in which node deletion is allowed."""
STABLE_STATES = (ENROLL, MANAGEABLE, AVAILABLE, ACTIVE, ERROR)
"""States that will not transition unless receiving a request."""
##############
# Power states
@ -212,11 +215,8 @@ watchers['on_enter'] = on_enter
machine = fsm.FSM()
# Add stable states
machine.add_state(ENROLL, stable=True, **watchers)
machine.add_state(MANAGEABLE, stable=True, **watchers)
machine.add_state(AVAILABLE, stable=True, **watchers)
machine.add_state(ACTIVE, stable=True, **watchers)
machine.add_state(ERROR, stable=True, **watchers)
for state in STABLE_STATES:
machine.add_state(state, stable=True, **watchers)
# Add verifying state
machine.add_state(VERIFYING, target=MANAGEABLE, **watchers)

View File

@ -382,7 +382,14 @@ class TaskManager(object):
self.node.target_provision_state)
self.node.provision_state = self.fsm.current_state
self.node.target_provision_state = self.fsm.target_state
# NOTE(lucasagomes): If there's no extra processing
# (callback) and we've moved to a stable state, make sure the
# target_provision_state is cleared
if not callback and self.fsm.is_stable(self.node.provision_state):
self.node.target_provision_state = states.NOSTATE
else:
self.node.target_provision_state = self.fsm.target_state
# set up the async worker
if callback:

View File

@ -1120,7 +1120,7 @@ class DoNodeDeployTearDownTestCase(mgr_utils.ServiceSetUpMixin,
self.service._do_node_tear_down, task)
node.refresh()
self.assertEqual(states.ERROR, node.provision_state)
self.assertEqual(states.AVAILABLE, node.target_provision_state)
self.assertEqual(states.NOSTATE, node.target_provision_state)
self.assertIsNotNone(node.last_error)
# Assert instance_info was erased
self.assertEqual({}, node.instance_info)

View File

@ -625,6 +625,28 @@ class TaskManagerStateModelTestCases(tests_base.TestCase):
self.assertNotEqual(target_provision_state,
self.node.target_provision_state)
def test_process_event_callback_stable_state(self):
callback = mock.Mock()
for state in states.STABLE_STATES:
self.node.provision_state = state
self.node.target_provision_state = 'target'
self.task.process_event = task_manager.TaskManager.process_event
self.task.process_event(self.task, 'fake', callback=callback)
# assert the target state is set when callback is passed
self.assertNotEqual(states.NOSTATE,
self.task.node.target_provision_state)
def test_process_event_no_callback_stable_state(self):
for state in states.STABLE_STATES:
self.node.provision_state = state
self.node.target_provision_state = 'target'
self.task.process_event = task_manager.TaskManager.process_event
self.task.process_event(self.task, 'fake')
# assert the target state was cleared when moving to a
# stable state
self.assertEqual(states.NOSTATE,
self.task.node.target_provision_state)
@task_manager.require_exclusive_lock
def _req_excl_lock_method(*args, **kwargs):

View File

@ -0,0 +1,5 @@
---
fixes:
- Ensure node's target_provision_state is cleared when the node
is moved to a stable state, indicating that the state transition
is done.