Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable image builds that use systemd mount units and kargs instead of writing /etc/fstab #1270

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

achilleas-k
Copy link
Member

This PR enables the use of systemd .mount (and .swap) units to replace writing an /etc/fstab file for the filesystem configuration. This is enabled for the Fedora minimal-raw image and its derivatives for Fedora 43 (rawhide) and above.

The feature will be useful for bootc-image-builder, where filesystem configurations can be written at different stages (base container image build or disk build) and creating a systemd unit for each mount is more straightforward than merging different entries in an /etc/fstab file.

The lack of an /etc/fstab requires a few changes to kernel commandline arguments and the partition table. Each change is described in its respective commit message, but I also summarise here:

  • Partitions need to have GUIDs in accordance with the Discoverable Partitions Specification (done in Set GUIDs for / and /usr according to the Discoverable Partitions Specification #1231).
  • The /usr partition, if separate from /, must be defined in the kernel command line arguments.
  • The system root needs to be mounted rw during initial boot, because the lack of /etc/fstab means that the systemd-remount-fs service will not discover the mount options for / (and /usr) to remount them.
  • For the same reason, the / mount options (rootflags) need to be defined in the kernel command line arguments.

This PR requires osbuild/osbuild#2001.

Move the static TestPartitionTables into a function.  Having them in a
mutable, package-global, public map makes any modification in one test
affect subsequent ones.
Add a Swap section and support for .swap systemd units.
This commit also adds a separate filename regex for unit files that
differs from the one we have for general files.  Specifically, it allows
for backslashes, which we will need to create .swap unit files.  The
filenames for these units must be the escaped path to the device or file
they control, which can contain escape characters (e.g. \x2d for
escaping a dash).

The Service and Install sections are now marked 'omitempty' since they
can be omitted (depending on the type of the unit).

See also systemd.swap(5)
GenSystemdMountStages() generates systemd .mount and .swap stages based
on a partition table.  This is an alternative to generating an fstab
stage for the mountpoints.

The generator creates one systemd.unit.create stage for each mountpoint
(and swap) and an extra stage that enables all the new units after they
are written.
Test GenSystemdMountStages() using test partition tables from testdisk.
Add a boolean to each pipeline that generates a filesystem description
(i.e. creates an org.osbuild.fstab stage), which when enabled will
create systemd mount units instead of writing the static filesystem
description to /etc/fstab.
Test all pipelines that support filesystem configuration switching
between /etc/fstab and systemd .mount units.  These are:
- OS
- OSTreeDeployment
- RawBootcImage

This commit also includes some test restructuring.
- The OS pipeline tests have been moved to manifest_test, external to
  the manifest package.
- Functions that are needed for both internal and external tests are
  defined and exported from the export_test.go file in the manifest
  package.  We should move all tests to the external manifest_test
  package eventually.

The testing is a little inconsistent now between different kinds of
pipelines.  Some run serializeStart() and serialize() in the same
exported function, and others (bootc) export both.  These should be
made consistent, but for now it's okay.
Add a flag for enabling mount units on ImageConfig and copy the value to
the OSCustomizations (for rpm-based disk images) and the
OSTreeDploymentCustomizations.
Add repos for branched (42) and rawhide (43) to start testing.
Generate the new gitlab config.
Make KernelOptions a string slice where each element is a separate
option.  This makes it easier to manipulate each option individually,
which we will need later to modify default options when using mount
units.
When /usr is on a separate mountpoint and we're not writing an
/etc/fstab, the filesystem information should be included in the kernel
cmdline arguments for autodiscovery to work.
The systemd-remount-fs service reads mount options from /etc/fstab for
the root partition (and /usr, if separate).  If there is no /etc/fstab,
the fs is not remounted, so a read-only mount will stay read-only on
boot.

Switch the "ro" command line argument to "rw" if we're not writing an
/etc/fstab file.
Also, add the root mount options as rootflags.
Starting from Fedora 43, use mount units instead of writing /etc/fstab
for the minimal-raw image type.

Convert the image type declaration to a function of the distribution
version so we can apply the configuration accordingly.
@achilleas-k achilleas-k requested a review from a team as a code owner February 26, 2025 23:58
Copy link
Contributor

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! I only gave a quick skim

Comment on lines +893 to +896
if kernelOptions[idx] == "ro" {
kernelOptions[idx] = "rw"
break
}
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like it'd be cleaner to ensure that rw is injected from the start if mount units are in use.

if err != nil {
panic(fmt.Sprintf("error getting filesystem options for / mountpoint: %s", err))
}
kernelOptions = append(kernelOptions, fmt.Sprintf("rootflags=%s", fsOptions.MntOps))
Copy link
Contributor

Choose a reason for hiding this comment

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

Cosmetic: Since most use cases don't use rootflags it'd be nice to not end up with rootflags=default, so we could special case that and not emit rootflags at all.

@supakeen
Copy link
Member

supakeen commented Feb 27, 2025

I'll do a comment before I take a look at the code and say this is super nice and exciting to have.


With a Fedora Minimal hat on: while we do plan to eventually have no-/etc/fstab I'd like to do some testing with this first even before landing in rawhide.

Can this PR include experimentalflags.String("no-fstab") != "" in the version gate for Fedora Minimal?

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