Inject a randomized publisher id

To serve as a mechanism to allow an interlocking device identification
this patch injects a publisher id value into ISO images *and* the kernel
command line for any software running from the ISO image to match
the ISO in use to the location of data housed locally from within the
image.

Related-Bug: 2032377
Change-Id: I9b74ec977fabc0a7f8ed6f113595a3f1624f6ee6
This commit is contained in:
Julia Kreger 2024-04-03 12:56:57 -07:00
parent 6437a2e794
commit fb850e7f00
5 changed files with 166 additions and 62 deletions

View File

@ -175,7 +175,8 @@ def _label(files_info):
def create_isolinux_image_for_bios( def create_isolinux_image_for_bios(
output_file, kernel, ramdisk, kernel_params=None, inject_files=None): output_file, kernel, ramdisk, kernel_params=None, inject_files=None,
publisher_id=None):
"""Creates an isolinux image on the specified file. """Creates an isolinux image on the specified file.
Copies the provided kernel, ramdisk to a directory, generates the isolinux Copies the provided kernel, ramdisk to a directory, generates the isolinux
@ -191,6 +192,8 @@ def create_isolinux_image_for_bios(
as the kernel cmdline. as the kernel cmdline.
:param inject_files: Mapping of local source file paths to their location :param inject_files: Mapping of local source file paths to their location
on the final ISO image. on the final ISO image.
:param publisher_id: A value to set as the publisher identifier string
in the ISO image to be generated.
:raises: ImageCreationFailed, if image creation failed while copying files :raises: ImageCreationFailed, if image creation failed while copying files
or while running command to generate iso. or while running command to generate iso.
""" """
@ -237,9 +240,12 @@ def create_isolinux_image_for_bios(
isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG) isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG)
utils.write_to_file(isolinux_cfg, cfg) utils.write_to_file(isolinux_cfg, cfg)
# Set a publisher ID value to a string.
pub_id = str(publisher_id)
try: try:
utils.execute('mkisofs', '-r', '-V', _label(files_info), utils.execute('mkisofs', '-r', '-V', _label(files_info),
'-J', '-l', '-no-emul-boot', '-J', '-l', '-publisher', pub_id, '-no-emul-boot',
'-boot-load-size', '4', '-boot-info-table', '-boot-load-size', '4', '-boot-info-table',
'-b', ISOLINUX_BIN, '-o', output_file, tmpdir) '-b', ISOLINUX_BIN, '-o', output_file, tmpdir)
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
@ -249,7 +255,7 @@ def create_isolinux_image_for_bios(
def create_esp_image_for_uefi( def create_esp_image_for_uefi(
output_file, kernel, ramdisk, deploy_iso=None, esp_image=None, output_file, kernel, ramdisk, deploy_iso=None, esp_image=None,
kernel_params=None, inject_files=None): kernel_params=None, inject_files=None, publisher_id=None):
"""Creates an ESP image on the specified file. """Creates an ESP image on the specified file.
Copies the provided kernel, ramdisk and EFI system partition image (ESP) to Copies the provided kernel, ramdisk and EFI system partition image (ESP) to
@ -271,6 +277,8 @@ def create_esp_image_for_uefi(
as the kernel cmdline. as the kernel cmdline.
:param inject_files: Mapping of local source file paths to their location :param inject_files: Mapping of local source file paths to their location
on the final ISO image. on the final ISO image.
:param publisher_id: A value to set as the publisher identifier string
in the ISO image to be generated.
:raises: ImageCreationFailed, if image creation failed while copying files :raises: ImageCreationFailed, if image creation failed while copying files
or while running command to generate iso. or while running command to generate iso.
""" """
@ -337,10 +345,18 @@ def create_esp_image_for_uefi(
utils.write_to_file(grub_cfg, grub_conf) utils.write_to_file(grub_cfg, grub_conf)
# Create the boot_iso. # Create the boot_iso.
if publisher_id:
args = ('mkisofs', '-r', '-V', _label(files_info),
'-l', '-publisher', publisher_id, '-e', e_img_rel_path,
'-no-emul-boot', '-o', output_file,
tmpdir)
else:
args = ('mkisofs', '-r', '-V', _label(files_info),
'-l', '-e', e_img_rel_path,
'-no-emul-boot', '-o', output_file,
tmpdir)
try: try:
utils.execute('mkisofs', '-r', '-V', _label(files_info), utils.execute(*args)
'-l', '-e', e_img_rel_path, '-no-emul-boot',
'-o', output_file, tmpdir)
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
LOG.exception("Creating ISO image failed.") LOG.exception("Creating ISO image failed.")
@ -498,7 +514,7 @@ def get_temp_url_for_glance_image(context, image_uuid):
def create_boot_iso(context, output_filename, kernel_href, def create_boot_iso(context, output_filename, kernel_href,
ramdisk_href, deploy_iso_href=None, esp_image_href=None, ramdisk_href, deploy_iso_href=None, esp_image_href=None,
root_uuid=None, kernel_params=None, boot_mode=None, root_uuid=None, kernel_params=None, boot_mode=None,
inject_files=None): inject_files=None, publisher_id=None):
"""Creates a bootable ISO image for a node. """Creates a bootable ISO image for a node.
Given the hrefs for kernel, ramdisk, root partition's UUID and Given the hrefs for kernel, ramdisk, root partition's UUID and
@ -524,6 +540,8 @@ def create_boot_iso(context, output_filename, kernel_href,
:boot_mode: the boot mode in which the deploy is to happen. :boot_mode: the boot mode in which the deploy is to happen.
:param inject_files: Mapping of local source file paths to their location :param inject_files: Mapping of local source file paths to their location
on the final ISO image. on the final ISO image.
:param publisher_id: A value to set as the publisher identifier string
in the ISO image to be generated.
:raises: ImageCreationFailed, if creating boot ISO failed. :raises: ImageCreationFailed, if creating boot ISO failed.
""" """
with utils.tempdir() as tmpdir: with utils.tempdir() as tmpdir:
@ -560,12 +578,14 @@ def create_boot_iso(context, output_filename, kernel_href,
create_esp_image_for_uefi( create_esp_image_for_uefi(
output_filename, kernel_path, ramdisk_path, output_filename, kernel_path, ramdisk_path,
deploy_iso=deploy_iso_path, esp_image=esp_image_path, deploy_iso=deploy_iso_path, esp_image=esp_image_path,
kernel_params=params, inject_files=inject_files) kernel_params=params, inject_files=inject_files,
publisher_id=publisher_id)
else: else:
create_isolinux_image_for_bios( create_isolinux_image_for_bios(
output_filename, kernel_path, ramdisk_path, output_filename, kernel_path, ramdisk_path,
kernel_params=params, inject_files=inject_files) kernel_params=params, inject_files=inject_files,
publisher_id=publisher_id)
IMAGE_TYPE_PARTITION = 'partition' IMAGE_TYPE_PARTITION = 'partition'

View File

@ -23,6 +23,7 @@ import tempfile
from urllib import parse as urlparse from urllib import parse as urlparse
from oslo_log import log from oslo_log import log
from oslo_utils import uuidutils
from ironic.common import exception from ironic.common import exception
from ironic.common.glance_service import service_utils from ironic.common.glance_service import service_utils
@ -446,6 +447,9 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href,
img_handler = ImageHandler(task.node.driver) img_handler = ImageHandler(task.node.driver)
if not is_ramdisk_boot:
publisher_id = uuidutils.generate_uuid()
with tempfile.TemporaryDirectory(dir=CONF.tempdir) as boot_file_dir: with tempfile.TemporaryDirectory(dir=CONF.tempdir) as boot_file_dir:
boot_iso_tmp_file = os.path.join(boot_file_dir, 'boot.iso') boot_iso_tmp_file = os.path.join(boot_file_dir, 'boot.iso')
@ -456,6 +460,9 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href,
kernel_params = driver_utils.get_kernel_append_params( kernel_params = driver_utils.get_kernel_append_params(
task.node, default=img_handler.kernel_params) task.node, default=img_handler.kernel_params)
if not is_ramdisk_boot:
kernel_params += " ir_pub_id=%s" % publisher_id
if params: if params:
kernel_params = ' '.join( kernel_params = ' '.join(
(kernel_params, ' '.join( (kernel_params, ' '.join(
@ -472,14 +479,27 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href,
'ramdisk_href': ramdisk_href, 'ramdisk_href': ramdisk_href,
'bootloader_href': bootloader_href, 'bootloader_href': bootloader_href,
'params': kernel_params}) 'params': kernel_params})
images.create_boot_iso(
task.context, boot_iso_tmp_file, if is_ramdisk_boot:
kernel_href, ramdisk_href, images.create_boot_iso(
esp_image_href=bootloader_href, task.context, boot_iso_tmp_file,
root_uuid=root_uuid, kernel_href, ramdisk_href,
kernel_params=kernel_params, esp_image_href=bootloader_href,
boot_mode=boot_mode, root_uuid=root_uuid,
inject_files=inject_files) kernel_params=kernel_params,
boot_mode=boot_mode,
inject_files=inject_files)
else:
images.create_boot_iso(
task.context, boot_iso_tmp_file,
kernel_href, ramdisk_href,
esp_image_href=bootloader_href,
root_uuid=root_uuid,
kernel_params=kernel_params,
boot_mode=boot_mode,
inject_files=inject_files,
publisher_id=publisher_id)
node_http_url = task.node.driver_info.get("external_http_url") node_http_url = task.node.driver_info.get("external_http_url")
image_url = img_handler.publish_image( image_url = img_handler.publish_image(

View File

@ -568,7 +568,8 @@ class FsImageTestCase(base.TestCase):
'path/to/kernel', 'path/to/kernel',
'path/to/ramdisk', 'path/to/ramdisk',
deploy_iso='path/to/deploy_iso', deploy_iso='path/to/deploy_iso',
kernel_params=params) kernel_params=params,
publisher_id='1-23-4')
get_iso_files_mock.assert_called_once_with('path/to/deploy_iso', get_iso_files_mock.assert_called_once_with('path/to/deploy_iso',
'mountdir') 'mountdir')
create_root_fs_mock.assert_called_once_with('tmpdir', files_info) create_root_fs_mock.assert_called_once_with('tmpdir', files_info)
@ -576,7 +577,8 @@ class FsImageTestCase(base.TestCase):
grub_options) grub_options)
write_to_file_mock.assert_any_call(grub_file, grubcfg) write_to_file_mock.assert_any_call(grub_file, grubcfg)
execute_mock.assert_called_once_with( execute_mock.assert_called_once_with(
'mkisofs', '-r', '-V', 'VMEDIA_BOOT_ISO', '-l', '-e', 'mkisofs', '-r', '-V', 'VMEDIA_BOOT_ISO', '-l',
'-publisher', '1-23-4', '-e',
'path/to/efiboot.img', '-no-emul-boot', '-o', 'tgt_file', 'tmpdir') 'path/to/efiboot.img', '-no-emul-boot', '-o', 'tgt_file', 'tmpdir')
rmtree_mock.assert_called_once_with('mountdir') rmtree_mock.assert_called_once_with('mountdir')
@ -651,7 +653,8 @@ class FsImageTestCase(base.TestCase):
'path/to/kernel', 'path/to/kernel',
'path/to/ramdisk', 'path/to/ramdisk',
kernel_params=params, kernel_params=params,
inject_files=inject_files) inject_files=inject_files,
publisher_id='1-23-4')
files_info = { files_info = {
'path/to/kernel': 'vmlinuz', 'path/to/kernel': 'vmlinuz',
@ -670,6 +673,7 @@ class FsImageTestCase(base.TestCase):
execute_mock.assert_called_once_with( execute_mock.assert_called_once_with(
'mkisofs', '-r', '-V', 'mkisofs', '-r', '-V',
"VMEDIA_BOOT_ISO", '-J', '-l', "VMEDIA_BOOT_ISO", '-J', '-l',
'-publisher', '1-23-4',
'-no-emul-boot', '-boot-load-size', '-no-emul-boot', '-boot-load-size',
'4', '-boot-info-table', '-b', 'isolinux/isolinux.bin', '4', '-boot-info-table', '-b', 'isolinux/isolinux.bin',
'-o', 'tgt_file', 'tmpdir') '-o', 'tgt_file', 'tmpdir')
@ -809,7 +813,8 @@ class FsImageTestCase(base.TestCase):
create_isolinux_mock.assert_called_once_with( create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk', 'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk',
deploy_iso='tmpdir/iso', deploy_iso='tmpdir/iso',
esp_image=None, kernel_params=params, inject_files=None) esp_image=None, kernel_params=params, inject_files=None,
publisher_id=None)
@mock.patch.object(images, 'create_esp_image_for_uefi', autospec=True) @mock.patch.object(images, 'create_esp_image_for_uefi', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True) @mock.patch.object(images, 'fetch', autospec=True)
@ -837,7 +842,8 @@ class FsImageTestCase(base.TestCase):
create_isolinux_mock.assert_called_once_with( create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk', 'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk',
deploy_iso=None, esp_image='tmpdir/esp', deploy_iso=None, esp_image='tmpdir/esp',
kernel_params=params, inject_files=None) kernel_params=params, inject_files=None,
publisher_id=None)
@mock.patch.object(images, 'create_esp_image_for_uefi', autospec=True) @mock.patch.object(images, 'create_esp_image_for_uefi', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True) @mock.patch.object(images, 'fetch', autospec=True)
@ -865,7 +871,8 @@ class FsImageTestCase(base.TestCase):
create_isolinux_mock.assert_called_once_with( create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk', 'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk',
deploy_iso='tmpdir/iso', deploy_iso='tmpdir/iso',
esp_image=None, kernel_params=params, inject_files=None) esp_image=None, kernel_params=params, inject_files=None,
publisher_id=None)
@mock.patch.object(images, 'create_esp_image_for_uefi', autospec=True) @mock.patch.object(images, 'create_esp_image_for_uefi', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True) @mock.patch.object(images, 'fetch', autospec=True)
@ -880,7 +887,7 @@ class FsImageTestCase(base.TestCase):
'ctx', 'output_file', 'http://kernel-href', 'http://ramdisk-href', 'ctx', 'output_file', 'http://kernel-href', 'http://ramdisk-href',
esp_image_href='http://efiboot-href', esp_image_href='http://efiboot-href',
root_uuid='root-uuid', kernel_params='kernel-params', root_uuid='root-uuid', kernel_params='kernel-params',
boot_mode='uefi') boot_mode='uefi', publisher_id='1-23-4')
expected_calls = [mock.call('ctx', 'http://kernel-href', expected_calls = [mock.call('ctx', 'http://kernel-href',
'tmpdir/kernel'), 'tmpdir/kernel'),
@ -893,7 +900,8 @@ class FsImageTestCase(base.TestCase):
create_isolinux_mock.assert_called_once_with( create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk', 'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk',
deploy_iso=None, esp_image='tmpdir/esp', deploy_iso=None, esp_image='tmpdir/esp',
kernel_params=params, inject_files=None) kernel_params=params, inject_files=None,
publisher_id='1-23-4')
@mock.patch.object(images, 'create_isolinux_image_for_bios', autospec=True) @mock.patch.object(images, 'create_isolinux_image_for_bios', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True) @mock.patch.object(images, 'fetch', autospec=True)
@ -907,7 +915,8 @@ class FsImageTestCase(base.TestCase):
images.create_boot_iso('ctx', 'output_file', 'kernel-uuid', images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
'ramdisk-uuid', 'deploy_iso-uuid', 'ramdisk-uuid', 'deploy_iso-uuid',
'efiboot-uuid', 'root-uuid', 'efiboot-uuid', 'root-uuid',
'kernel-params', 'bios') 'kernel-params', 'bios',
publisher_id='1-23-4')
fetch_images_mock.assert_any_call( fetch_images_mock.assert_any_call(
'ctx', 'kernel-uuid', 'tmpdir/kernel') 'ctx', 'kernel-uuid', 'tmpdir/kernel')
@ -924,7 +933,8 @@ class FsImageTestCase(base.TestCase):
params = ['root=UUID=root-uuid', 'kernel-params'] params = ['root=UUID=root-uuid', 'kernel-params']
create_isolinux_mock.assert_called_once_with( create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk', 'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk',
kernel_params=params, inject_files=None) kernel_params=params, inject_files=None,
publisher_id='1-23-4')
@mock.patch.object(images, 'create_isolinux_image_for_bios', autospec=True) @mock.patch.object(images, 'create_isolinux_image_for_bios', autospec=True)
@mock.patch.object(images, 'fetch', autospec=True) @mock.patch.object(images, 'fetch', autospec=True)
@ -949,7 +959,8 @@ class FsImageTestCase(base.TestCase):
params = ['root=UUID=root-uuid', 'kernel-params'] params = ['root=UUID=root-uuid', 'kernel-params']
create_isolinux_mock.assert_called_once_with( create_isolinux_mock.assert_called_once_with(
'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk', 'output_file', 'tmpdir/kernel', 'tmpdir/ramdisk',
kernel_params=params, inject_files=None) kernel_params=params, inject_files=None,
publisher_id=None)
@mock.patch.object(image_service, 'get_image_service', autospec=True) @mock.patch.object(image_service, 'get_image_service', autospec=True)
def test_get_glance_image_properties_no_such_prop(self, def test_get_glance_image_properties_no_such_prop(self,

View File

@ -379,11 +379,14 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_unpublish.assert_called_once_with(mock.ANY, object_name) mock_unpublish.assert_called_once_with(mock.ANY, object_name)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_uefi( def test__prepare_iso_image_uefi(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
task.node.instance_info.update(deploy_boot_mode='uefi') task.node.instance_info.update(deploy_boot_mode='uefi')
@ -404,18 +407,21 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href='http://bootloader/img', boot_mode='uefi', esp_image_href='http://bootloader/img',
kernel_params='nofb vga=normal', kernel_params='nofb vga=normal ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(expected_url, url) self.assertEqual(expected_url, url)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_default_boot_mode( def test__prepare_iso_image_default_boot_mode(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
self.config(default_boot_mode='uefi', group='deploy') self.config(default_boot_mode='uefi', group='deploy')
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
image_utils._prepare_iso_image( image_utils._prepare_iso_image(
@ -425,16 +431,19 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None, boot_mode='uefi', esp_image_href=None,
kernel_params='nofb vga=normal', kernel_params='nofb vga=normal ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_with_node_external_http_url( def test__prepare_iso_image_with_node_external_http_url(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
self.config(default_boot_mode='uefi', group='deploy') self.config(default_boot_mode='uefi', group='deploy')
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
override_url = 'https://node.external/' override_url = 'https://node.external/'
@ -455,18 +464,21 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href='http://bootloader/img', boot_mode='uefi', esp_image_href='http://bootloader/img',
kernel_params='nofb vga=normal', kernel_params='nofb vga=normal ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(expected_url, url) self.assertEqual(expected_url, url)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_bios( def test__prepare_iso_image_bios(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
self.config(default_boot_mode='bios', group='deploy') self.config(default_boot_mode='bios', group='deploy')
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
@ -486,17 +498,20 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='bios', esp_image_href=None, boot_mode='bios', esp_image_href=None,
kernel_params='nofb vga=normal', kernel_params='nofb vga=normal ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(expected_url, url) self.assertEqual(expected_url, url)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params( def test__prepare_iso_image_kernel_params(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -510,15 +525,19 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None, boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params, kernel_params=f'{kernel_params} ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(1, mock_generate_uuid.call_count)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_driver_info( def test__prepare_iso_image_kernel_params_driver_info(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -532,15 +551,19 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None, boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params, kernel_params=f'{kernel_params} ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(1, mock_generate_uuid.call_count)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_defaults( def test__prepare_iso_image_kernel_params_defaults(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -555,16 +578,21 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None, boot_mode='uefi', esp_image_href=None,
kernel_params=f'nofb vga=normal {kernel_params}', kernel_params=(f'nofb vga=normal {kernel_params} '
'ir_pub_id=1-23-4'),
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(1, mock_generate_uuid.call_count)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_driver_info_bios( def test__prepare_iso_image_kernel_params_driver_info_bios(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
self.config(default_boot_mode='bios', group='deploy') self.config(default_boot_mode='bios', group='deploy')
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -578,16 +606,20 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='bios', esp_image_href=None, boot_mode='bios', esp_image_href=None,
kernel_params=kernel_params, kernel_params=f'{kernel_params} ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None,
publisher_id='1-23-4')
self.assertEqual(1, mock_generate_uuid.call_count)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(deploy_utils, 'get_boot_option', lambda node: 'ramdisk') @mock.patch.object(deploy_utils, 'get_boot_option', lambda node: 'ramdisk')
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_for_ramdisk_uefi( def test__prepare_iso_image_kernel_params_for_ramdisk_uefi(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -601,17 +633,21 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None, boot_mode='uefi', esp_image_href=None,
kernel_params="root=/dev/ram0 text " + kernel_params, kernel_params=f'root=/dev/ram0 text {kernel_params}',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None)
mock_generate_uuid.assert_not_called()
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(deploy_utils, 'get_boot_option', lambda node: 'ramdisk') @mock.patch.object(deploy_utils, 'get_boot_option', lambda node: 'ramdisk')
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_for_ramdisk_bios( def test__prepare_iso_image_kernel_params_for_ramdisk_bios(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
self.config(default_boot_mode='bios', group='deploy') self.config(default_boot_mode='bios', group='deploy')
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -625,16 +661,20 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='bios', esp_image_href=None, boot_mode='bios', esp_image_href=None,
kernel_params="root=/dev/ram0 text " + kernel_params, kernel_params=f'root=/dev/ram0 text {kernel_params}',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None)
mock_generate_uuid.assert_not_called()
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(deploy_utils, 'get_boot_option', lambda node: 'ramdisk') @mock.patch.object(deploy_utils, 'get_boot_option', lambda node: 'ramdisk')
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_kernel_params_for_ramdisk_cleaning( def test__prepare_iso_image_kernel_params_for_ramdisk_cleaning(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -649,15 +689,19 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None, boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params, kernel_params=f'{kernel_params} ir_pub_id=1-23-4',
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(1, mock_generate_uuid.call_count)
@mock.patch.object(uuidutils, 'generate_uuid', autospec=True)
@mock.patch.object(image_utils.ImageHandler, 'publish_image', @mock.patch.object(image_utils.ImageHandler, 'publish_image',
autospec=True) autospec=True)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
def test__prepare_iso_image_extra_params( def test__prepare_iso_image_extra_params(
self, mock_create_boot_iso, mock_publish_image): self, mock_create_boot_iso, mock_publish_image,
mock_generate_uuid):
mock_generate_uuid.return_value = '1-23-4'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
kernel_params = 'network-config=base64-cloudinit-blob' kernel_params = 'network-config=base64-cloudinit-blob'
@ -672,9 +716,12 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
mock_create_boot_iso.assert_called_once_with( mock_create_boot_iso.assert_called_once_with(
mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img', mock.ANY, mock.ANY, 'http://kernel/img', 'http://ramdisk/img',
boot_mode='uefi', esp_image_href=None, boot_mode='uefi', esp_image_href=None,
kernel_params=kernel_params + ' foo=bar banana', kernel_params=(f'{kernel_params} ir_pub_id=1-23-4 '
'foo=bar banana'),
root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123', root_uuid='1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
inject_files=None) inject_files=None, publisher_id='1-23-4')
self.assertEqual(1, mock_generate_uuid.call_count)
self.assertEqual(1, mock_generate_uuid.call_count)
@mock.patch.object(images, 'create_boot_iso', autospec=True) @mock.patch.object(images, 'create_boot_iso', autospec=True)
@mock.patch.object(image_utils, 'prepare_remote_image', autospec=True) @mock.patch.object(image_utils, 'prepare_remote_image', autospec=True)

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Adds an ISO publisher value to ISO images which are mastered as part of
cleaning/deployment/service operations in support of a fix for
`bug 2032377 <https://bugs.launchpad.net/ironic/+bug/2032377>`_.