Merge "Refresh fsm in task when a shared lock is upgraded"
This commit is contained in:
@@ -189,8 +189,7 @@ UPDATE_ALLOWED_STATES = (DEPLOYFAIL, INSPECTING, INSPECTFAIL, CLEANFAIL, ERROR,
|
|||||||
VERIFYING, ADOPTFAIL)
|
VERIFYING, ADOPTFAIL)
|
||||||
"""Transitional states in which we allow updating a node."""
|
"""Transitional states in which we allow updating a node."""
|
||||||
|
|
||||||
DELETE_ALLOWED_STATES = (AVAILABLE, NOSTATE, MANAGEABLE, ENROLL,
|
DELETE_ALLOWED_STATES = (AVAILABLE, MANAGEABLE, ENROLL, ADOPTFAIL)
|
||||||
ADOPTFAIL)
|
|
||||||
"""States in which node deletion is allowed."""
|
"""States in which node deletion is allowed."""
|
||||||
|
|
||||||
STABLE_STATES = (ENROLL, MANAGEABLE, AVAILABLE, ACTIVE, ERROR)
|
STABLE_STATES = (ENROLL, MANAGEABLE, AVAILABLE, ACTIVE, ERROR)
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ class TaskManager(object):
|
|||||||
self._on_error_method = None
|
self._on_error_method = None
|
||||||
|
|
||||||
self.context = context
|
self.context = context
|
||||||
self.node = None
|
self._node = None
|
||||||
self.node_id = node_id
|
self.node_id = node_id
|
||||||
self.shared = shared
|
self.shared = shared
|
||||||
|
|
||||||
@@ -218,19 +218,21 @@ class TaskManager(object):
|
|||||||
self.driver = driver_factory.build_driver_for_task(
|
self.driver = driver_factory.build_driver_for_task(
|
||||||
self, driver_name=driver_name)
|
self, driver_name=driver_name)
|
||||||
|
|
||||||
# NOTE(deva): this handles the Juno-era NOSTATE state
|
|
||||||
# and should be deleted after Kilo is released
|
|
||||||
if self.node.provision_state is states.NOSTATE:
|
|
||||||
self.node.provision_state = states.AVAILABLE
|
|
||||||
self.node.save()
|
|
||||||
|
|
||||||
self.fsm.initialize(start_state=self.node.provision_state,
|
|
||||||
target_state=self.node.target_provision_state)
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
self.release_resources()
|
self.release_resources()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def node(self):
|
||||||
|
return self._node
|
||||||
|
|
||||||
|
@node.setter
|
||||||
|
def node(self, node):
|
||||||
|
self._node = node
|
||||||
|
if node is not None:
|
||||||
|
self.fsm.initialize(start_state=self.node.provision_state,
|
||||||
|
target_state=self.node.target_provision_state)
|
||||||
|
|
||||||
def _lock(self):
|
def _lock(self):
|
||||||
self._debug_timer.restart()
|
self._debug_timer.restart()
|
||||||
|
|
||||||
|
|||||||
@@ -763,27 +763,6 @@ class ServiceDoNodeDeployTestCase(mgr_utils.ServiceSetUpMixin,
|
|||||||
mock_iwdi):
|
mock_iwdi):
|
||||||
self._test_do_node_deploy_validate_fail(mock_validate, mock_iwdi)
|
self._test_do_node_deploy_validate_fail(mock_validate, mock_iwdi)
|
||||||
|
|
||||||
@mock.patch('ironic.conductor.task_manager.TaskManager.process_event')
|
|
||||||
def test_deploy_with_nostate_converts_to_available(self, mock_pe,
|
|
||||||
mock_iwdi):
|
|
||||||
# expressly create a node using the Juno-era NOSTATE state
|
|
||||||
# and assert that it does not result in an error, and that the state
|
|
||||||
# is converted to the new AVAILABLE state.
|
|
||||||
# Mock the process_event call, because the transitions from
|
|
||||||
# AVAILABLE are tested thoroughly elsewhere
|
|
||||||
# NOTE(deva): This test can be deleted after Kilo is released
|
|
||||||
mock_iwdi.return_value = False
|
|
||||||
self._start_service()
|
|
||||||
node = obj_utils.create_test_node(self.context, driver='fake',
|
|
||||||
provision_state=states.NOSTATE)
|
|
||||||
self.assertEqual(states.NOSTATE, node.provision_state)
|
|
||||||
self.service.do_node_deploy(self.context, node.uuid)
|
|
||||||
self.assertTrue(mock_pe.called)
|
|
||||||
node.refresh()
|
|
||||||
self.assertEqual(states.AVAILABLE, node.provision_state)
|
|
||||||
mock_iwdi.assert_called_once_with(self.context, node.instance_info)
|
|
||||||
self.assertFalse(node.driver_internal_info['is_whole_disk_image'])
|
|
||||||
|
|
||||||
def test_do_node_deploy_partial_ok(self, mock_iwdi):
|
def test_do_node_deploy_partial_ok(self, mock_iwdi):
|
||||||
mock_iwdi.return_value = False
|
mock_iwdi.return_value = False
|
||||||
self._start_service()
|
self._start_service()
|
||||||
|
|||||||
@@ -396,6 +396,28 @@ class TaskManagerTestCase(tests_db_base.DbTestCase):
|
|||||||
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
get_ports_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
|
||||||
|
|
||||||
|
def test_upgrade_lock_refreshes_fsm(self, get_portgroups_mock,
|
||||||
|
get_ports_mock, build_driver_mock,
|
||||||
|
reserve_mock, release_mock,
|
||||||
|
node_get_mock):
|
||||||
|
reserve_mock.return_value = self.node
|
||||||
|
node_get_mock.return_value = self.node
|
||||||
|
with task_manager.acquire(self.context, 'fake-node-id',
|
||||||
|
shared=True) as task1:
|
||||||
|
self.assertEqual(states.AVAILABLE, task1.node.provision_state)
|
||||||
|
|
||||||
|
with task_manager.acquire(self.context, 'fake-node-id',
|
||||||
|
shared=False) as task2:
|
||||||
|
# move the node to manageable
|
||||||
|
task2.process_event('manage')
|
||||||
|
self.assertEqual(states.MANAGEABLE, task1.node.provision_state)
|
||||||
|
|
||||||
|
# now upgrade our shared task and try to go to cleaning
|
||||||
|
# this will explode if task1's FSM doesn't get refreshed
|
||||||
|
task1.upgrade_lock()
|
||||||
|
task1.process_event('provide')
|
||||||
|
self.assertEqual(states.CLEANING, task1.node.provision_state)
|
||||||
|
|
||||||
def test_spawn_after(
|
def test_spawn_after(
|
||||||
self, get_portgroups_mock, get_ports_mock, build_driver_mock,
|
self, get_portgroups_mock, get_ports_mock, build_driver_mock,
|
||||||
reserve_mock, release_mock, node_get_mock):
|
reserve_mock, release_mock, node_get_mock):
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ def get_test_node(**kw):
|
|||||||
'conductor_affinity': kw.get('conductor_affinity', None),
|
'conductor_affinity': kw.get('conductor_affinity', None),
|
||||||
'power_state': kw.get('power_state', states.NOSTATE),
|
'power_state': kw.get('power_state', states.NOSTATE),
|
||||||
'target_power_state': kw.get('target_power_state', states.NOSTATE),
|
'target_power_state': kw.get('target_power_state', states.NOSTATE),
|
||||||
'provision_state': kw.get('provision_state', states.NOSTATE),
|
'provision_state': kw.get('provision_state', states.AVAILABLE),
|
||||||
'target_provision_state': kw.get('target_provision_state',
|
'target_provision_state': kw.get('target_provision_state',
|
||||||
states.NOSTATE),
|
states.NOSTATE),
|
||||||
'provision_updated_at': kw.get('provision_updated_at'),
|
'provision_updated_at': kw.get('provision_updated_at'),
|
||||||
|
|||||||
Reference in New Issue
Block a user