diff options
author | Dmitry Tantsur <dtantsur@protonmail.com> | 2020-06-17 13:24:10 +0200 |
---|---|---|
committer | Dmitry Tantsur <dtantsur@protonmail.com> | 2020-06-24 08:56:51 +0200 |
commit | 089b84e4cdee7b50ca854eec3c687ade33abb4ec (patch) | |
tree | 132d5486a554052ad967b1d136e0b563785722d4 | |
parent | 49ce9993e1a3c4f1f049f6833166f4c49c67dda7 (diff) | |
download | ironic-089b84e4cdee7b50ca854eec3c687ade33abb4ec.tar.gz |
Fix fast-track with the direct deploy interface
Several small fixes:
1) Make sure the deploy.deploy step returns DEPLOYWAIT after running
prepare_image otherwise the conductor wrongly assumes that the
deploy is done.
2) Handle the case when provision_state==DEPLOYWAIT when returning
from an asynchronous deploy step.
3) Do not assume that prepare_image is always the last command to run,
sometimes get_deploy_steps sneaks in.
4) Do not issue a deprecation warning when receiving "agent is busy"
on get_deploy_steps, this is normal for fast-track.
NOTE: the last change is missing from stable/train
Conflicts:
ironic/conductor/deployments.py
ironic/drivers/modules/agent_base.py
ironic/tests/unit/conductor/test_deployments.py
ironic/tests/unit/drivers/modules/test_agent_base_vendor.py
Change-Id: I19274c48bd36fca19961a7d78467ec8c29f85905
(cherry picked from commit f0803493de07ba5573cf0ab0e607e8c5113dcb81)
-rw-r--r-- | ironic/conductor/manager.py | 3 | ||||
-rw-r--r-- | ironic/drivers/modules/agent.py | 17 | ||||
-rw-r--r-- | ironic/tests/unit/drivers/modules/test_agent.py | 23 | ||||
-rw-r--r-- | releasenotes/notes/direct-fast-track-d0f43850b6e80751.yaml | 5 |
4 files changed, 36 insertions, 12 deletions
diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index be81483d7..adbfb7b44 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -3985,7 +3985,8 @@ def _do_next_deploy_step(task, step_index, conductor_id): LOG.info('Deploy step %(step)s on node %(node)s being ' 'executed asynchronously, waiting for driver.', {'node': node.uuid, 'step': step}) - task.process_event('wait') + if task.node.provision_state != states.DEPLOYWAIT: + task.process_event('wait') return elif result is not None: # NOTE(rloo): This is an internal/dev error; shouldn't happen. diff --git a/ironic/drivers/modules/agent.py b/ironic/drivers/modules/agent.py index 9e1a067a0..9c6f69368 100644 --- a/ironic/drivers/modules/agent.py +++ b/ironic/drivers/modules/agent.py @@ -184,17 +184,13 @@ class AgentDeployMixin(agent_base_vendor.AgentDeployMixin): if not commands: return False - last_command = commands[-1] - - if last_command['command_name'] != 'prepare_image': - # catches race condition where prepare_image is still processing - # so deploy hasn't started yet + try: + last_command = next(cmd for cmd in reversed(commands) + if cmd['command_name'] == 'prepare_image') + except StopIteration: return False - - if last_command['command_status'] != 'RUNNING': - return True - - return False + else: + return last_command['command_status'] != 'RUNNING' @METRICS.timer('AgentDeployMixin.continue_deploy') @task_manager.require_exclusive_lock @@ -462,6 +458,7 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface): # the state machine state going from DEPLOYWAIT -> DEPLOYING task.process_event('wait') self.continue_deploy(task) + return states.DEPLOYWAIT elif task.driver.storage.should_write_image(task): # Check if the driver has already performed a reboot in a previous # deploy step. diff --git a/ironic/tests/unit/drivers/modules/test_agent.py b/ironic/tests/unit/drivers/modules/test_agent.py index 15d5b675a..65fbc049c 100644 --- a/ironic/tests/unit/drivers/modules/test_agent.py +++ b/ironic/tests/unit/drivers/modules/test_agent.py @@ -377,7 +377,7 @@ class TestAgentDeploy(db_base.DbTestCase): self.node.save() with task_manager.acquire( self.context, self.node['uuid'], shared=False) as task: - self.driver.deploy(task) + self.assertEqual(states.DEPLOYWAIT, self.driver.deploy(task)) self.assertFalse(power_mock.called) self.assertFalse(mock_pxe_instance.called) task.node.refresh() @@ -1529,6 +1529,27 @@ class TestAgentDeploy(db_base.DbTestCase): 'command_status': 'RUNNING'}] self.assertFalse(task.driver.deploy.deploy_is_done(task)) + @mock.patch.object(agent_client.AgentClient, 'get_commands_status', + autospec=True) + def test_deploy_is_done_several_results(self, mock_get_cmd): + with task_manager.acquire(self.context, self.node.uuid) as task: + mock_get_cmd.return_value = [ + {'command_name': 'prepare_image', 'command_status': 'SUCCESS'}, + {'command_name': 'other_command', 'command_status': 'SUCCESS'}, + {'command_name': 'prepare_image', 'command_status': 'RUNNING'}, + ] + self.assertFalse(task.driver.deploy.deploy_is_done(task)) + + @mock.patch.object(agent_client.AgentClient, 'get_commands_status', + autospec=True) + def test_deploy_is_done_not_the_last(self, mock_get_cmd): + with task_manager.acquire(self.context, self.node.uuid) as task: + mock_get_cmd.return_value = [ + {'command_name': 'prepare_image', 'command_status': 'SUCCESS'}, + {'command_name': 'other_command', 'command_status': 'SUCCESS'}, + ] + self.assertTrue(task.driver.deploy.deploy_is_done(task)) + @mock.patch.object(manager_utils, 'restore_power_state_if_needed', autospec=True) @mock.patch.object(manager_utils, 'power_on_node_if_needed', diff --git a/releasenotes/notes/direct-fast-track-d0f43850b6e80751.yaml b/releasenotes/notes/direct-fast-track-d0f43850b6e80751.yaml new file mode 100644 index 000000000..fee9738a9 --- /dev/null +++ b/releasenotes/notes/direct-fast-track-d0f43850b6e80751.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixes fast-track deployments with the ``direct`` deploy interface that + used to hang previously. |