From 0d59e25cf8ae3e531fcca46b20907014a9a92f09 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Thu, 23 Nov 2023 14:36:44 +1300 Subject: [PATCH] Use per-node external_http_url for boot ISO When the per-node external_http_url feature was introduced by c197a2d8b24e2fa4c5e7901e448da1b0c93fcd26, it only applied to a config floppy. This fix ensures that it is also used for the boot ISO, both when it is generated locally (by _prepare_iso_image()) or just cached locally (by prepare_remote_image()). Change-Id: Ic241da6845b4d97fd29888e28cc1d9ee34e182c1 Closes-Bug: #2044314 --- ironic/drivers/modules/image_utils.py | 6 +- .../unit/drivers/modules/test_image_utils.py | 55 ++++++++++++++++++- ...so-external_http_url-c5e3fa9ae4960dd6.yaml | 5 ++ 3 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/node-iso-external_http_url-c5e3fa9ae4960dd6.yaml diff --git a/ironic/drivers/modules/image_utils.py b/ironic/drivers/modules/image_utils.py index e3479a2602..5ce4303514 100644 --- a/ironic/drivers/modules/image_utils.py +++ b/ironic/drivers/modules/image_utils.py @@ -374,7 +374,8 @@ def prepare_remote_image(task, image_url, file_name='boot.iso', tmp_file = os.path.join(temp_dir, file_name) cache.fetch_image(image_url, tmp_file, ctx=task.context, force_raw=False) - return img_handler.publish_image(tmp_file, file_name) + node_http_url = task.node.driver_info.get("external_http_url") + return img_handler.publish_image(tmp_file, file_name, node_http_url) def cleanup_remote_image(task, file_name): @@ -478,8 +479,9 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href, boot_mode=boot_mode, inject_files=inject_files) + node_http_url = task.node.driver_info.get("external_http_url") image_url = img_handler.publish_image( - boot_iso_tmp_file, iso_object_name) + boot_iso_tmp_file, iso_object_name, node_http_url) LOG.debug("Created ISO %(name)s in object store for node %(node)s, " "exposed as temporary URL " diff --git a/ironic/tests/unit/drivers/modules/test_image_utils.py b/ironic/tests/unit/drivers/modules/test_image_utils.py index ad6bbcebe9..912b5c55d4 100644 --- a/ironic/tests/unit/drivers/modules/test_image_utils.py +++ b/ironic/tests/unit/drivers/modules/test_image_utils.py @@ -401,7 +401,7 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase): object_name = 'boot-%s.iso' % task.node.uuid mock_publish_image.assert_called_once_with( - mock.ANY, mock.ANY, object_name) + mock.ANY, mock.ANY, object_name, None) mock_create_boot_iso.assert_called_once_with( mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', @@ -431,6 +431,38 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase): root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', inject_files=None) + @mock.patch.object(image_utils.ImageHandler, 'publish_image', + autospec=True) + @mock.patch.object(images, 'create_boot_iso', autospec=True) + def test__prepare_iso_image_with_node_external_http_url( + self, mock_create_boot_iso, mock_publish_image): + self.config(default_boot_mode='uefi', group='deploy') + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + override_url = 'https://node.external/' + task.node.driver_info.update(external_http_url=override_url) + + expected_url = 'https://node.external/c.f?e=f' + mock_publish_image.return_value = expected_url + + url = image_utils._prepare_iso_image( + task, 'http://kernel/img', 'http://ramdisk/img', + 'http://bootloader/img', root_uuid=task.node.uuid) + + object_name = 'boot-%s.iso' % task.node.uuid + + mock_publish_image.assert_called_once_with( + mock.ANY, mock.ANY, object_name, override_url) + + mock_create_boot_iso.assert_called_once_with( + mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', + boot_mode='uefi', esp_image_href='http://bootloader/img', + kernel_params='nofb vga=normal', + root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', + inject_files=None) + + self.assertEqual(expected_url, url) + @mock.patch.object(image_utils.ImageHandler, 'publish_image', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True) @@ -451,7 +483,7 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase): object_name = 'boot-%s.iso' % task.node.uuid mock_publish_image.assert_called_once_with( - mock.ANY, mock.ANY, object_name) + mock.ANY, mock.ANY, object_name, None) mock_create_boot_iso.assert_called_once_with( mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', @@ -939,6 +971,25 @@ cafile = /etc/ironic-python-agent/ironic.crt mock_cache.return_value.fetch_image.assert_called_once_with( base_image_url, mock.ANY, ctx=task.context, force_raw=False) + @mock.patch.object(image_utils.ImageHandler, 'publish_image', + autospec=True) + @mock.patch.object(image_utils, 'ISOImageCache', autospec=True) + def test_prepare_remote_image_local_external_http_url(self, + mock_cache, + mock_publish_image): + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + override_url = 'https://node.external/' + task.node.driver_info.update(external_http_url=override_url) + + base_image_url = 'http://bearmetal.net/boot.iso' + url = image_utils.prepare_remote_image(task, base_image_url) + self.assertEqual(mock_publish_image.return_value, url) + mock_cache.return_value.fetch_image.assert_called_once_with( + base_image_url, mock.ANY, ctx=task.context, force_raw=False) + mock_publish_image.assert_called_once_with( + mock.ANY, mock.ANY, mock.ANY, override_url) + @mock.patch.object(image_utils.ImageHandler, 'publish_image', autospec=True) def test_prepare_remote_image_custom_cache(self, mock_publish_image): diff --git a/releasenotes/notes/node-iso-external_http_url-c5e3fa9ae4960dd6.yaml b/releasenotes/notes/node-iso-external_http_url-c5e3fa9ae4960dd6.yaml new file mode 100644 index 0000000000..6b52aa3347 --- /dev/null +++ b/releasenotes/notes/node-iso-external_http_url-c5e3fa9ae4960dd6.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + The per-node ``external_http_url`` setting in the driver info is now used + for a boot ISO. Previously this setting was only used for a config floppy.