summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ironic_python_agent/extensions/base.py11
-rw-r--r--ironic_python_agent/hardware.py2
-rw-r--r--ironic_python_agent/tests/unit/extensions/test_base.py11
-rw-r--r--releasenotes/notes/prepare-image-49744276cef719d5.yaml5
4 files changed, 28 insertions, 1 deletions
diff --git a/ironic_python_agent/extensions/base.py b/ironic_python_agent/extensions/base.py
index 93adfe93..23e47c46 100644
--- a/ironic_python_agent/extensions/base.py
+++ b/ironic_python_agent/extensions/base.py
@@ -79,6 +79,17 @@ class BaseCommandResult(encoding.SerializableComparable):
""":returns: result of completed command."""
return self
+ def wait(self):
+ """Join the result and extract its value.
+
+ Raises if the command failed.
+ """
+ self.join()
+ if self.command_error is not None:
+ raise self.command_error
+ else:
+ return self.command_result
+
class SyncCommandResult(BaseCommandResult):
"""A result from a command that executes synchronously."""
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index 3724effb..f8107b55 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -2139,7 +2139,7 @@ class GenericHardwareManager(HardwareManager):
ext = ext_base.get_extension('standby')
cmd = ext.prepare_image(image_info=image_info, configdrive=configdrive)
# The result is asynchronous, wait here.
- cmd.join()
+ return cmd.wait()
def generate_tls_certificate(self, ip_address):
"""Generate a TLS certificate for the IP address."""
diff --git a/ironic_python_agent/tests/unit/extensions/test_base.py b/ironic_python_agent/tests/unit/extensions/test_base.py
index f609e580..2bc4c75b 100644
--- a/ironic_python_agent/tests/unit/extensions/test_base.py
+++ b/ironic_python_agent/tests/unit/extensions/test_base.py
@@ -149,6 +149,12 @@ class TestExtensionDecorators(test_base.IronicAgentTest):
result.command_result)
self.agent.force_heartbeat.assert_called_once_with()
+ def test_wait_async_command_success(self):
+ result = self.extension.execute('fake_async_command', param='v1')
+ self.assertIsInstance(result, base.AsyncCommandResult)
+ result = result.wait()
+ self.assertEqual({'result': 'fake_async_command: v1'}, result)
+
def test_async_command_success_without_agent(self):
extension = FakeExtension(agent=None)
result = extension.execute('fake_async_command', param='v1')
@@ -182,6 +188,11 @@ class TestExtensionDecorators(test_base.IronicAgentTest):
self.assertIsNone(result.command_result)
self.agent.force_heartbeat.assert_called_once_with()
+ def test_wait_async_command_execution_failure(self):
+ result = self.extension.execute('fake_async_command', param='v2')
+ self.assertIsInstance(result, base.AsyncCommandResult)
+ self.assertRaises(ExecutionError, result.wait)
+
def test_async_command_name(self):
self.assertEqual(
'other_async_name',
diff --git a/releasenotes/notes/prepare-image-49744276cef719d5.yaml b/releasenotes/notes/prepare-image-49744276cef719d5.yaml
new file mode 100644
index 00000000..88e0d6d5
--- /dev/null
+++ b/releasenotes/notes/prepare-image-49744276cef719d5.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Fixes the ``write_image`` deploy step to actually check and return any
+ errors during its execution.