Skip to content

Conversation

frelon
Copy link
Contributor

@frelon frelon commented Aug 25, 2025

The customize command can be used to customize a pre-built installer
image (right now only ISO supported).

The customization process uses xorriso to add config files and overlays into the installer image.

@frelon frelon marked this pull request as ready for review August 26, 2025 09:05
@frelon frelon requested a review from a team as a code owner August 26, 2025 09:05
Copy link
Contributor

@davidcassany davidcassany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if it wouldn't have been easier to simply repack the ISO in a single xorriso call, something similar to what the seedimage does in classic Elemental.

xorriso -indev <inputISO> -outdev <outputISO> -map /overlay/ / -boot_image any replay

The above command would add/overwrite the contents of the /overlay folder in host to the root of the ISO filesystem. If we can limit our customizations there then the process is way faster, reuses the already existing ISO contents without re-generating them (squashfs, EFI partitions, etc.) and narrows the changes applied to the resulting image.

what do you think?

return fmt.Errorf("failed extracting ISO fs: %w", err)
}

err = i.extractSquashRootfs(isoDir, rootDir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this extracting entirely the squashfs image content to actually squash it again later on without any modification?
Modifying the squashfs should not be allowed in any case, I think. Moreover if we keep the squashfs image untouched the process will be way faster to my understanding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, since we are not dealing with a golden image repacking should be a noop unless we add extra information as stated before.

return nil
}

func (i ISO) extractSquashRootfs(isoDir, rootDir string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I struggle to see why we need this part...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not constructive

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry my bad, should have explained what I had in mind.

I was trying to say I don't see the need of unpacking the squashfs file system and then resquash it back again. As far as I understand we only need to unpack the filesystem to run the bootloader installation, for which we can only modify the kernel command line setup.
Unless I am missing something the customize process does not allow changing the rootfs contents hence this results into a uncompress -> copy -> recompress -> copy sequence, just to update a kernel command line which is not part of the squashed image.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I am missing something the customize process does not allow changing the rootfs contents hence this results into a uncompress -> copy -> recompress -> copy sequence, just to update a kernel command line which is not part of the squashed image.

Where is this described for the customize process? I have been trying to find docs about this process, but have not been successful in finding anything.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we have it described anywhere yet 😞

In my head (and this is only MY understanding) this is allowing to produce an auto installable ISO (from a given ISO built in OBS) that runs an installation on first boot resulting in to a setup equivalent to what is achievable by elemental build. So my first iteration would be to make it similar to the build-iso command INPUT wise, so it can set the target device, config script, etc. Which essentially means adding some parameters to the current given ISO.

So as user, I get and ISO, I run customize with my custom parameters and the result is an ISO which self installs on first boot.

At least this is how I imagined it... but you are right, I don't think we have it well defined anywhere.

In a wider picture I guess this is should be used by elemental build instead of actually running an installation.

return fmt.Errorf("failed preparing iso directory tree: %w", err)
}

err = i.prepareEFI(isoDir, efiDir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is required only to set the kernel command line in case of changes... I am wondering if shouldn't the keep the kernel cmd line in the ISO filesystem as a grub variable or similar. This way we could even omit having to recreate the EFI partition too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that would be another way to solve this.

@frelon
Copy link
Contributor Author

frelon commented Aug 28, 2025

I am wondering if it wouldn't have been easier to simply repack the ISO in a single xorriso call, something similar to what the seedimage does in classic Elemental.

xorriso -indev <inputISO> -outdev <outputISO> -map /overlay/ / -boot_image any replay

The above command would add/overwrite the contents of the /overlay folder in host to the root of the ISO filesystem. If we can limit our customizations there then the process is way faster, reuses the already existing ISO contents without re-generating them (squashfs, EFI partitions, etc.) and narrows the changes applied to the resulting image.

what do you think?

Sure it would have been easier, but not allow the same level of customization. The thinking here was to open the way to customize the rootfs in case things such as extra binaries or kernel-modules are needed.

Regenerating the squashfs and EFI-partitions should not be a problem, since we use the same input it should produce the same output.

Copy link
Contributor

@davidcassany davidcassany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure it would have been easier, but not allow the same level of customization. The thinking here was to open the way to customize the rootfs in case things such as extra binaries or kernel-modules are needed.

I understand, but if rootfs refers to the OS tree then I don't see how to keep those changes across updates... 🤔 Moreover, if I understand it correctly, the OverlayTree applies on the ISO filesystem, not over the squashfs tree. So the contents of the squashfs image can't be modified anyway.

Regenerating the squashfs and EFI-partitions should not be a problem, since we use the same input it should produce the same output.

I agree the result would be equivalent, however rebuilding the squashfs is a CPU demanding process.

return nil
}

func (i ISO) extractSquashRootfs(isoDir, rootDir string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry my bad, should have explained what I had in mind.

I was trying to say I don't see the need of unpacking the squashfs file system and then resquash it back again. As far as I understand we only need to unpack the filesystem to run the bootloader installation, for which we can only modify the kernel command line setup.
Unless I am missing something the customize process does not allow changing the rootfs contents hence this results into a uncompress -> copy -> recompress -> copy sequence, just to update a kernel command line which is not part of the squashed image.

@frelon frelon changed the title customize cmd Add customize command Aug 29, 2025
@frelon frelon requested review from davidcassany and a team August 29, 2025 10:49
@@ -225,7 +341,7 @@ func (i ISO) prepareRoot(rootDir string) error {

err = selinux.Relabel(i.ctx, i.s, rootDir)
if err != nil {
return fmt.Errorf("SELinux labelling failed: %w", err)
i.s.Logger().Warn("Error selinux relabelling: %s", err.Error())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I needed this to be able to build a new ISO without errors. When this fails we also need to add selinux=0 to command-line.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting... SE Linux is also hitting me with the ISO build in OBS, I guess we will need to make an effort on that front to understand and review where we can actually improve SE Linux setup.

Copy link
Contributor

@davidcassany davidcassany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good, great work.

Simple and flexible enough to actually test and refine the actual use cases and flows we need.

@@ -225,7 +341,7 @@ func (i ISO) prepareRoot(rootDir string) error {

err = selinux.Relabel(i.ctx, i.s, rootDir)
if err != nil {
return fmt.Errorf("SELinux labelling failed: %w", err)
i.s.Logger().Warn("Error selinux relabelling: %s", err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting... SE Linux is also hitting me with the ISO build in OBS, I guess we will need to make an effort on that front to understand and review where we can actually improve SE Linux setup.

return nil
}

func (i ISO) extractSquashRootfs(isoDir, rootDir string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we have it described anywhere yet 😞

In my head (and this is only MY understanding) this is allowing to produce an auto installable ISO (from a given ISO built in OBS) that runs an installation on first boot resulting in to a setup equivalent to what is achievable by elemental build. So my first iteration would be to make it similar to the build-iso command INPUT wise, so it can set the target device, config script, etc. Which essentially means adding some parameters to the current given ISO.

So as user, I get and ISO, I run customize with my custom parameters and the result is an ISO which self installs on first boot.

At least this is how I imagined it... but you are right, I don't think we have it well defined anywhere.

In a wider picture I guess this is should be used by elemental build instead of actually running an installation.

@frelon frelon enabled auto-merge (rebase) September 2, 2025 07:48
@atanasdinov atanasdinov self-requested a review September 2, 2025 09:42
Copy link
Contributor

@atanasdinov atanasdinov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. This establishes a good base that we can build upon -- I expect the input to eventually be the configuration directory currently used for the build command but we will figure this out later.

Found one minor issue in one of the tests. Happy to approve as soon as this is fixed.

@frelon frelon disabled auto-merge September 2, 2025 11:11
The customize command can be used to customize a pre-built installer
image (right now only ISO supported).

Use single call to xorriso to map files onto the ISO.

Write a grubenv to /boot/grub2/grubenv with extra_cmdline parameter used
by grub_live.cfg.

Also overwrite /LiveOS/setup.sh with file provided in --config and map
the passed in --overlay over /

Signed-off-by: Fredrik Lönnegren <[email protected]>
@frelon frelon merged commit c0fccd5 into SUSE:main Sep 2, 2025
4 checks passed
@frelon frelon deleted the customize-cmd branch September 2, 2025 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants