Managed bootloader universe

Hello,

for upcoming work Strict SecureBoot/HTTPS Provisioning of Bare-Metal and VMs I need to solve distribution of netboot.iso files onto TFTP smart proxies. Because Foreman already does support bootloader universe directory structure - see more in Provisioning hosts - I think it makes sense to combine both things and think about how smart-proxy might manage this directory.

Foreman today can download PXE files (kernel, initramdisk) from Installation Media and Katello/Pulp, when installed. The way this works is there is a simple API call /tftp/fetch_boot_file (exposed by tftp capability) that takes two parameters: source, destination (they are named path and prefix but for simplicity I changed them). Source is a URL (from installation media or Pulp), destination is a relative path within TFTP directory. Two files are downloaded today: kernel and initramdisk.

A new capability called bootloader_universe was added recently, this activates when Foreman deploys one of its TFTP templates. Instead of simply writing the PXE configuration directly to boot/ directory, it creates host-config/MAC directory as documented and symlinks all files that were manually deployed, for example bootloader-universe/pxegrub2/rhel/9.6/x86_64/grubx64.efi.

What I propose is that Foreman Server + Proxy starts managing the universe directory automatically. AFAIR this was the ultimate goal but would require more work, so we ended up just implementing manual approach. And it looks like this is not too much work!

The feature can be implemented on top of what we have today. We just need to change the current download API /tftp/fetch_boot_file

  • source (is present today)
  • destination (is present today)
  • extract: list of files (source, destination) and type (iso, rpm, extensible)

By using the current API, Foreman can download files not only to boot/ (current behavior) but also to bootloader-universe/. More than that, by adding little bit of code, it can extract various files from formats like ISO, RPM or DEB packages. This is important, because bootloaders are typically not available easily as simple files. This all can be done with little effort and minimal changes.

What is great about this design is it works with or without Katello and with any OS, the only thing is to add a bit of code into Operating System to provide the correct list of files to download. We would implement Red Hat and Debian systems initially so the community can do followups. Also, this is fully backward compatible - existing OSes which will not have support for this bootloader universe management will continue working.

Finally, the change is compatible too from API standpoint, we would be only adding new flags and behavior to the /tftp/fetch_boot_file endpoint. Proxy would need to advertise this capability tho, perhaps using a new bootloader_artifacts and for extraction capabilities we would have bootloader_iso_extract so new formats can be added at later date.

One thing that is open question is the more files Foreman downloads the more the probability of host not being able to boot because files are not yet downloaded. Specifically if we go the extracting Grub2 from boot.iso path, then it is an issue. For that, I think Foreman should trigger downloading of TFTP files the moment Operating System is created or edited (when it has all required associations like Installation Media).

2 Likes

Slight expansion on the problem statement: this isn’t limited to SecureBoot. Using GRUB from EL 9 to boot EL != 9 is unsupported. We found this out the hard way: you can’t use GRUB from EL 9.8 to boot EL 7. So really, IMHO this should be the default regardless of SecureBoot.

Overall this reads like what I had in mind when I looked at the problem.

Correct. This is implemented using the MediumProviders service. MediumProviders::Default uses the DB in plain Foreman, which retrieves it from the internet while Katello::ManagedContentMediumProvider uses Pulp.

Would it make sense to expose each type as its own capability in the Smart Proxy?

On the Foreman side we have Operatingsystem as a model and that somehow needs to map to a type. I can imagine we’d initially introduce some type, but over time find out we need more. Either because initially we didn’t have time for all OSes or a new OS version uses a different type.

Does this include Ubuntu? Because Ubuntu is a complete mess complicated since the introduction of Autoinstall.

I know it was a mess when this was announced, but for more recent versions I do see a download directory with pre-extracted files:

I think for both Debian and Ubuntu, the default implementation could download and extract the netboot tarball to keep it consistent. Also, downloading just one (compressed) file is faster and there is the checksum that is helpful.

I should be able to draft an implementation for Debian and Ubuntu, but perhaps testing would be something I will ask the community for help.

1 Like

It still needs the full iso afterwards which is at least special. But I am totally fine with a draft someone else needs to test. Feel free to ping me and I will try to assign a colleague for testing.

Sure, I will link the PRs into this thread.

I am curious what is it that is not in the netboot tarball, if you can brief me :slight_smile:

From my understand it simply needs the iso as kernel option: foreman/app/views/unattended/provisioning_templates/snippet/preseed_kernel_options_autoinstall.erb at develop · theforeman/foreman · GitHub
It can be that there is another option, but it was implemented at least in this way.

What I typically do is download the iso and mount it then instead of extracting it to save disk space. None of my customer playbooks is public, but our training material is to give you an example: foreman-training/provisioning/02_configuration.md at gh-pages · NETWAYS/foreman-training · GitHub

I quickly took a look and to boot Ubuntu, only linux kernel and initramdisk is needed, then ISO must be provided via the url kernel option which contains the installer code. This can be downloaded from internet, at least that is how it works for Red Hat (stage 2 Anaconda image).

Of course, for most deployments, it is worth having a local mirror or Katello plugin that does all the syncing. So I do not think that the default implementation for Ubuntu needs to download the whole ISO technically speaking.

However, going forward, I think downloading the whole ISO is probably the best option as the same file can be then used for Direct ISO boot provisioning.

To sum it up, if we are going the ISO way, then there makes no sense to download the ISO and then kernel and initramdisk separately these are usually 100 MiB of extra download. All the files are already in the ISO. That can be dropped completely, so the new PXE downloading workflow would be:

Red Hat systems:

  • Download boot.iso from Installation Media
  • Extract shim, grub, kernel, initramdisk from there

Ubuntu systems:

  • Download installation.iso from Installation Media
  • Extract shim, grub, kernel, initramdisk from there

Debian systems:

  • Download netboot.tar.gz from Installation Media
  • Extract shim, grub, kernel, initramdisk from there

Required features:

  • Ability to extract arbitrary files from ISO
  • Ability to extract arbitrary files from tarball
  • Foreman orchestrating different URLs per Operating System
  • Foreman starting downloads the moment Operating System is created/edited

The downloads should be idempotent, meaning, curl will not re-download unchanged files. This is a already existing behavior. I think it might be wise to code a prototype ASAP since we just branched off 5.0 and this is a possibly breaking behavior.

1 Like

Some time ago, we thought about providing the Ubuntu ISO image and allow to sync from foreman to proxy: Fixes #35270 - Enable boot image download by bastian-src · Pull Request #837 · theforeman/smart-proxy · GitHub

Unfortunately, never finished (or, not yet).

1 Like

Yes I just noticed this PR, I created a brand new implementation which is I believe more flexible it is not just for Ubuntu but scales across all OSes. Here is the PR:

Please check it out there is a test script that downloads all universe files for:

  • CentOS 10 Stream
  • Debian
  • Ubuntu

Once I get review ACKs I am gonna work on Foreman changes which should be much smaller than this.

1 Like

For modern Ubuntu, the story is a little bit more difficult than for all other systems. For the installation to work, you need

  • the complete ISO image. The full ISO must be made available over HTTP for the Ubuntu installer.
  • the kernel / initramfs (they are already part of the full ISO Image)

So the ISO image need to be available, then you need to unpack the required files (kernel, initramfs) and then you can start the PXE-boot provisoing with all of these files.

Yeah, I know, I have updated my patch to also include a test example for Ubuntu and it works just fine. In this scenario, Foreman must schedule two actions:

  • Download and extract netboot.tar.gz to get bootloaders and kernel.
  • Download installation ISO.

The same files are also present in the ISO, so if you prefer, we can just download and extract from ISO. Since the new extraction feature always keeps the source archives in the folder for idempotency reasons, we could as well just use the ISO and ignore netboot.tar.gz completely. Both will work just fine.

I just felt like following the recommendation would be better.

2 Likes