summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-03-21 09:39:39 +0000
committerGerrit Code Review <review@openstack.org>2016-03-21 09:39:39 +0000
commit57955083471cab657ce023d13f597cb35e1adc3d (patch)
tree98f21f9acb2ff4a9af93d89adfb75ab8755082d5
parentea238dcffa2a415c2ac40ee0f42977b1bfc0b1a1 (diff)
parentaa4d3fa0220450517bebd621b6db0f8ca1fba0ca (diff)
downloadironic-57955083471cab657ce023d13f597cb35e1adc3d.tar.gz
Merge "Make sure target state is cleared on stable states"
-rw-r--r--ironic/common/states.py10
-rw-r--r--ironic/conductor/task_manager.py9
-rw-r--r--ironic/tests/unit/conductor/test_manager.py2
-rw-r--r--ironic/tests/unit/conductor/test_task_manager.py22
-rw-r--r--releasenotes/notes/clear-target-stable-states-4545602d7aed9898.yaml5
5 files changed, 41 insertions, 7 deletions
diff --git a/ironic/common/states.py b/ironic/common/states.py
index 721cbc4e3..09c4aff85 100644
--- a/ironic/common/states.py
+++ b/ironic/common/states.py
@@ -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)
diff --git a/ironic/conductor/task_manager.py b/ironic/conductor/task_manager.py
index a520816e3..a136c27e3 100644
--- a/ironic/conductor/task_manager.py
+++ b/ironic/conductor/task_manager.py
@@ -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:
diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py
index 75eb0f40f..48cf4c038 100644
--- a/ironic/tests/unit/conductor/test_manager.py
+++ b/ironic/tests/unit/conductor/test_manager.py
@@ -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)
diff --git a/ironic/tests/unit/conductor/test_task_manager.py b/ironic/tests/unit/conductor/test_task_manager.py
index 758edf3f3..6c6bac1d4 100644
--- a/ironic/tests/unit/conductor/test_task_manager.py
+++ b/ironic/tests/unit/conductor/test_task_manager.py
@@ -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):
diff --git a/releasenotes/notes/clear-target-stable-states-4545602d7aed9898.yaml b/releasenotes/notes/clear-target-stable-states-4545602d7aed9898.yaml
new file mode 100644
index 000000000..e5bac700d
--- /dev/null
+++ b/releasenotes/notes/clear-target-stable-states-4545602d7aed9898.yaml
@@ -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.