summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tantsur <dtantsur@protonmail.com>2020-06-17 13:24:10 +0200
committerDmitry Tantsur <dtantsur@protonmail.com>2020-06-24 08:56:51 +0200
commit089b84e4cdee7b50ca854eec3c687ade33abb4ec (patch)
tree132d5486a554052ad967b1d136e0b563785722d4
parent49ce9993e1a3c4f1f049f6833166f4c49c67dda7 (diff)
downloadironic-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.py3
-rw-r--r--ironic/drivers/modules/agent.py17
-rw-r--r--ironic/tests/unit/drivers/modules/test_agent.py23
-rw-r--r--releasenotes/notes/direct-fast-track-d0f43850b6e80751.yaml5
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.