From 2c9b6cd33accad5783edc5db29f700c8eeb9e515 Mon Sep 17 00:00:00 2001 From: Sayan Paul Date: Fri, 16 Feb 2024 14:18:31 +0530 Subject: [PATCH] pipeline/ostree-deployment:add custom-mountpount-create service Hooked up the create-unit-stage to add create-mountpoint.service to ostree deployment. Automatically add and enable osbuild-create-mountpoint.service whenever user adds filesystem customizationi, to ensure that the mountpoints are available post rpm-ostree upgrade. Signed-off-by: Sayan Paul --- pkg/distro/rhel9/images.go | 8 +++++ pkg/image/ostree_disk.go | 3 ++ pkg/manifest/ostree_deployment.go | 50 +++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/pkg/distro/rhel9/images.go b/pkg/distro/rhel9/images.go index 33632ce3b3..c51e14c9e0 100644 --- a/pkg/distro/rhel9/images.go +++ b/pkg/distro/rhel9/images.go @@ -490,6 +490,10 @@ func edgeRawImage(workload workload.Workload, img.Filename = t.Filename() img.Compression = t.compression + for _, fs := range customizations.GetFilesystems() { + img.CustomFilesystems = append(img.CustomFilesystems, fs.Mountpoint) + } + return img, nil } @@ -546,6 +550,10 @@ func edgeSimplifiedInstallerImage(workload workload.Workload, rawImg.Filename = t.Filename() + for _, fs := range customizations.GetFilesystems() { + rawImg.CustomFilesystems = append(rawImg.CustomFilesystems, fs.Mountpoint) + } + // 92+ only if kopts := customizations.GetKernel(); kopts != nil && kopts.Append != "" { rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, kopts.Append) diff --git a/pkg/image/ostree_disk.go b/pkg/image/ostree_disk.go index 99ed5a4d00..2228d56477 100644 --- a/pkg/image/ostree_disk.go +++ b/pkg/image/ostree_disk.go @@ -57,6 +57,8 @@ type OSTreeDiskImage struct { // Container buildable tweaks the buildroot to be container friendly, // i.e. to not rely on an installed osbuild-selinux ContainerBuildable bool + + CustomFilesystems []string } func NewOSTreeDiskImageFromCommit(commit ostree.SourceSpec) *OSTreeDiskImage { @@ -107,6 +109,7 @@ func baseRawOstreeImage(img *OSTreeDiskImage, buildPipeline manifest.Build, opts osPipeline.IgnitionPlatform = img.IgnitionPlatform osPipeline.LockRoot = img.LockRoot osPipeline.UseBootupd = opts.useBootupd + osPipeline.CustomFileSystems = img.CustomFilesystems // other image types (e.g. live) pass the workload to the pipeline. if img.Workload != nil { diff --git a/pkg/manifest/ostree_deployment.go b/pkg/manifest/ostree_deployment.go index 3e3afb97f1..e871cb5079 100644 --- a/pkg/manifest/ostree_deployment.go +++ b/pkg/manifest/ostree_deployment.go @@ -74,6 +74,8 @@ type OSTreeDeployment struct { // Use bootupd instead of grub2 as the bootloader UseBootupd bool + + CustomFileSystems []string } // NewOSTreeCommitDeployment creates a pipeline for an ostree deployment from a @@ -353,6 +355,19 @@ func (p *OSTreeDeployment) serialize() osbuild.Pipeline { }, })) + // This will create a custom systemd unit that create + // mountpoints if its not present.This will safeguard + // any ostree deployment which has custom filesystem + // during ostree upgrade. + // issue # https://github.com/osbuild/images/issues/352 + if len(p.CustomFileSystems) != 0 { + serviceName := "osbuild-ostree-mountpoints.service" + stageOption := osbuild.NewSystemdUnitCreateStageOptions(createMountpointService(serviceName, p.CustomFileSystems)) + stageOption.MountOSTree(p.osName, ref, 0) + pipeline.AddStage(stageOption) + p.EnabledServices = append(p.EnabledServices, serviceName) + } + // We enable / disable services below using the systemd stage, but its effect // may be overridden by systemd which may reset enabled / disabled services on // firstboot (which happend on F37+). This behavior, if available, is triggered @@ -481,3 +496,38 @@ func (p *OSTreeDeployment) getInline() []string { return inlineData } + +// Creates systemd unit stage by ingesting the servicename and mount-points +func createMountpointService(serviceName string, mountpoints []string) *osbuild.SystemdUnitCreateStageOptions { + var conditionPathIsDirectory []string + for _, mountpoint := range mountpoints { + conditionPathIsDirectory = append(conditionPathIsDirectory, "|!"+mountpoint) + } + unit := osbuild.Unit{ + Description: "Ensure custom filesystem mountpoints exist", + DefaultDependencies: false, + ConditionPathIsDirectory: conditionPathIsDirectory, + } + service := osbuild.Service{ + Type: osbuild.Oneshot, + RemainAfterExit: true, + //compatibility with composefs, will require transient rootfs to be enabled too. + ExecStartPre: []string{"/bin/sh -c \"if [ -z \"$(grep -Uq composefs /run/ostree-booted)\" ]; then chattr -i /; fi\""}, + ExecStopPost: []string{"/bin/sh -c \"if [ -z \"$(grep -Uq composefs /run/ostree-booted)\" ]; then chattr +i /; fi\""}, + ExecStart: []string{"mkdir -p " + strings.Join(mountpoints[:], " ")}, + } + install := osbuild.Install{ + WantedBy: []string{"local-fs.target"}, + } + options := osbuild.SystemdUnitCreateStageOptions{ + Filename: serviceName, + UnitPath: osbuild.Etc, + UnitType: osbuild.System, + Config: osbuild.SystemdServiceUnit{ + Unit: &unit, + Service: &service, + Install: &install, + }, + } + return &options +}