From 66bd2a857cbf2e577fef3dc0bea9c7e29934e9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20L=C3=B6nnegren?= Date: Wed, 11 Oct 2023 16:10:27 +0200 Subject: [PATCH] Add elemental-setup services to elemental-rootfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The elemental-setup and rootfs features are heavily dependent on each other. This commit copies the elemental-setup feature into elemental-rootfs, and changes the mount-command to actually start the elemental-setup-rootfs service during mount to not run the yip rootfs stage twice. Signed-off-by: Fredrik Lönnegren --- Dockerfile | 2 +- config.yaml.example | 2 +- examples/green/Dockerfile | 2 +- examples/tumbleweed/Dockerfile | 2 +- go.mod | 2 +- pkg/action/mount.go | 9 +++++---- pkg/config/config.go | 2 +- .../02-elemental-setup-initramfs.conf | 4 ++++ .../system/elemental-setup-boot.service | 11 ++++++++++ .../systemd/system/elemental-setup-fs.service | 14 +++++++++++++ .../system/elemental-setup-initramfs.service | 16 +++++++++++++++ .../system/elemental-setup-network.service | 17 ++++++++++++++++ .../system/elemental-setup-reconcile.service | 15 ++++++++++++++ .../system/elemental-setup-reconcile.timer | 10 ++++++++++ .../system/elemental-setup-rootfs.service | 15 ++++++++++++++ pkg/features/features.go | 20 ++++++++++++++++++- pkg/systemd/unit.go | 5 +++++ pkg/types/v1/config.go | 2 +- 18 files changed, 138 insertions(+), 12 deletions(-) create mode 100644 pkg/features/embedded/elemental-rootfs/etc/dracut.conf.d/02-elemental-setup-initramfs.conf create mode 100644 pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-boot.service create mode 100644 pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-fs.service create mode 100644 pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-initramfs.service create mode 100644 pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-network.service create mode 100644 pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.service create mode 100644 pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.timer create mode 100644 pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-rootfs.service diff --git a/Dockerfile b/Dockerfile index f8abad9f460..dd3d0070a55 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG GO_VERSION=1.20 +ARG GO_VERSION=1.21 ARG LEAP_VERSION=15.5 FROM golang:${GO_VERSION}-alpine as elemental-bin diff --git a/config.yaml.example b/config.yaml.example index f470b020e96..88d5ea95b34 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -129,7 +129,7 @@ mount: read-kernel-cmdline: true # read and parse /proc/cmdline for arguments sysroot: /sysroot # Path to mount system to write-fstab: true # Write fstab into sysroot/etc/fstab - run-cloud-init: true # Run rootfs stage + run-rootfs-service: true # Run rootfs stage run-fsck: true # Run fsck on all partitions before mounting overlay: type: tmpfs # tmpfs|block diff --git a/examples/green/Dockerfile b/examples/green/Dockerfile index 2fab3b67c83..f6537ab19b3 100644 --- a/examples/green/Dockerfile +++ b/examples/green/Dockerfile @@ -54,7 +54,7 @@ RUN systemctl enable NetworkManager.service RUN cp /usr/share/systemd/tmp.mount /etc/systemd/system # Generate initrd with required elemental services -RUN elemental init -f elemental-rootfs,grub-config,grub-default-bootargs,elemental-setup,dracut-config,cloud-config-defaults,cloud-config-essentials && \ +RUN elemental init -f elemental-rootfs,grub-config,grub-default-bootargs,dracut-config,cloud-config-defaults,cloud-config-essentials && \ kernel=$(ls /boot/Image-* | head -n1) && \ if [ -e "$kernel" ]; then ln -sf "${kernel#/boot/}" /boot/vmlinuz; fi && \ rm -rf /var/log/update* && \ diff --git a/examples/tumbleweed/Dockerfile b/examples/tumbleweed/Dockerfile index 19659975983..e43f2ae1de6 100644 --- a/examples/tumbleweed/Dockerfile +++ b/examples/tumbleweed/Dockerfile @@ -54,7 +54,7 @@ RUN systemctl enable NetworkManager.service RUN echo "PermitRootLogin yes" > /etc/ssh/sshd_config.d/rootlogin.conf # Generate initrd with required elemental services -RUN elemental init -f elemental-rootfs,grub-config,grub-default-bootargs,elemental-setup,dracut-config,cloud-config-defaults,cloud-config-essentials && \ +RUN elemental init -f elemental-rootfs,grub-config,grub-default-bootargs,dracut-config,cloud-config-defaults,cloud-config-essentials && \ kernel=$(ls /boot/Image-* | head -n1) && \ if [ -e "$kernel" ]; then ln -sf "${kernel#/boot/}" /boot/vmlinuz; fi && \ rm -rf /var/log/update* && \ diff --git a/go.mod b/go.mod index 10fed42efb7..c8811d77e7b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/rancher/elemental-toolkit -go 1.20 +go 1.21 require ( github.com/canonical/go-efilib v0.3.1-0.20220324150059-04e254148b45 diff --git a/pkg/action/mount.go b/pkg/action/mount.go index 891d7e73995..1d274c59daf 100644 --- a/pkg/action/mount.go +++ b/pkg/action/mount.go @@ -25,6 +25,7 @@ import ( "github.com/rancher/elemental-toolkit/pkg/constants" "github.com/rancher/elemental-toolkit/pkg/elemental" + "github.com/rancher/elemental-toolkit/pkg/systemd" v1 "github.com/rancher/elemental-toolkit/pkg/types/v1" "github.com/rancher/elemental-toolkit/pkg/utils" ) @@ -52,15 +53,15 @@ func RunMount(cfg *v1.RunConfig, spec *v1.MountSpec) error { return err } - if spec.RunCloudInit { - cfg.Logger.Debug("Running rootfs cloud-init stage") - err := utils.RunStage(&cfg.Config, "rootfs", cfg.Strict, cfg.CloudInitPaths...) + if spec.RunRootfsService { + cfg.Logger.Debug("Running elemental-setup-rootfs service") + err := systemd.Start(&cfg.Config.Runner, systemd.NewUnit("elemental-setup-rootfs")) if err != nil { cfg.Logger.Errorf("Error running rootfs stage: %s", err.Error()) return err } } else { - cfg.Logger.Debug("Skipping cloud-init rootfs stage") + cfg.Logger.Debug("Skipping elemental-setup-rootfs") } if err := applyLayoutConfig(cfg, spec); err != nil { diff --git a/pkg/config/config.go b/pkg/config/config.go index 1ea7080e707..eef6c0a2ace 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -227,7 +227,7 @@ func NewMountSpec() *v1.MountSpec { ReadKernelCmdline: true, Sysroot: "/sysroot", WriteFstab: true, - RunCloudInit: true, + RunRootfsService: true, RunFsck: true, Image: &v1.Image{ FS: constants.LinuxImgFs, diff --git a/pkg/features/embedded/elemental-rootfs/etc/dracut.conf.d/02-elemental-setup-initramfs.conf b/pkg/features/embedded/elemental-rootfs/etc/dracut.conf.d/02-elemental-setup-initramfs.conf new file mode 100644 index 00000000000..479f9b8b834 --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/etc/dracut.conf.d/02-elemental-setup-initramfs.conf @@ -0,0 +1,4 @@ +install_items+=" /usr/lib/systemd/system/elemental-setup-initramfs.service /etc/systemd/system/initrd.target.requires/elemental-setup-initramfs.service " +install_items+=" /usr/lib/systemd/system/elemental-setup-rootfs.service /etc/systemd/system/initrd-fs.target.requires/elemental-setup-rootfs.service " +install_items+=" /etc/hosts " +add_dracutmodules+=" network " diff --git a/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-boot.service b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-boot.service new file mode 100644 index 00000000000..fb0d5c9c528 --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-boot.service @@ -0,0 +1,11 @@ +[Unit] +Description=Elemental system configuration +Before=getty.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/elemental run-stage boot + +[Install] +WantedBy=multi-user.target diff --git a/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-fs.service b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-fs.service new file mode 100644 index 00000000000..70b4163b920 --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-fs.service @@ -0,0 +1,14 @@ +[Unit] +Description=Elemental system after FS setup +DefaultDependencies=no +After=local-fs.target +Wants=local-fs.target +Before=sysinit.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/elemental run-stage fs + +[Install] +WantedBy=sysinit.target diff --git a/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-initramfs.service b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-initramfs.service new file mode 100644 index 00000000000..d87dca49923 --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-initramfs.service @@ -0,0 +1,16 @@ +[Unit] +Description=Elemental system initramfs setup before switch root +DefaultDependencies=no +After=initrd-fs.target +Requires=initrd-fs.target +Before=initrd.target + +[Service] +RootDirectory=/sysroot +BindPaths=/proc /sys /dev /run /tmp +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/elemental run-stage initramfs + +[Install] +RequiredBy=initrd.target diff --git a/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-network.service b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-network.service new file mode 100644 index 00000000000..37a3245b192 --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-network.service @@ -0,0 +1,17 @@ +[Unit] +Description=Elemental setup after network +After=network-online.target +Wants=network-online.target + +[Service] +Nice=19 +IOSchedulingClass=2 +IOSchedulingPriority=7 +Type=oneshot +ExecStart=/usr/bin/elemental run-stage network +TimeoutStopSec=180 +KillMode=process +KillSignal=SIGINT + +[Install] +WantedBy=multi-user.target diff --git a/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.service b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.service new file mode 100644 index 00000000000..a5dc97b2b3f --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.service @@ -0,0 +1,15 @@ +[Unit] +Description=Elemental setup reconciler + +[Service] +Nice=19 +IOSchedulingClass=2 +IOSchedulingPriority=7 +Type=oneshot +ExecStart=/bin/bash -c "systemd-inhibit /usr/bin/elemental run-stage reconcile" +TimeoutStopSec=180 +KillMode=process +KillSignal=SIGINT + +[Install] +WantedBy=multi-user.target diff --git a/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.timer b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.timer new file mode 100644 index 00000000000..e9242dbfe67 --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-reconcile.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Elemental setup reconciler + +[Timer] +OnBootSec=5min +OnUnitActiveSec=60min +Unit=elemental-setup-reconcile.service + +[Install] +WantedBy=multi-user.target diff --git a/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-rootfs.service b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-rootfs.service new file mode 100644 index 00000000000..0048dcf64ae --- /dev/null +++ b/pkg/features/embedded/elemental-rootfs/usr/lib/systemd/system/elemental-setup-rootfs.service @@ -0,0 +1,15 @@ +[Unit] +Description=Elemental system early rootfs setup +DefaultDependencies=no +After=initrd-root-fs.target +Requires=initrd-root-fs.target +Conflicts=initrd-switch-root.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStartPre=/usr/bin/ln -sf -t / /sysroot/system +ExecStart=/usr/bin/elemental run-stage rootfs + +[Install] +RequiredBy=initrd-fs.target diff --git a/pkg/features/features.go b/pkg/features/features.go index 392ff8bc812..c2961726b65 100644 --- a/pkg/features/features.go +++ b/pkg/features/features.go @@ -21,6 +21,7 @@ import ( "fmt" "io/fs" "path/filepath" + "slices" "strings" "github.com/rancher/elemental-toolkit/pkg/constants" @@ -134,9 +135,22 @@ func Get(names []string) ([]*Feature, error) { case FeatureCloudConfigEssentials: features = append(features, New(name, nil)) case FeatureImmutableRootfs: + if slices.Contains(names, FeatureElementalRootfs) { + return features, fmt.Errorf("Conflicting features: %s and %s", FeatureImmutableRootfs, FeatureElementalRootfs) + } + features = append(features, New(name, nil)) case FeatureElementalRootfs: - features = append(features, New(name, nil)) + units := []*systemd.Unit{ + systemd.NewUnit("elemental-setup-reconcile.service"), + systemd.NewUnit("elemental-setup-reconcile.timer"), + systemd.NewUnit("elemental-setup-boot.service"), + systemd.NewUnit("elemental-setup-rootfs.service"), + systemd.NewUnit("elemental-setup-network.service"), + systemd.NewUnit("elemental-setup-initramfs.service"), + systemd.NewUnit("elemental-setup-fs.service"), + } + features = append(features, New(name, units)) case FeatureDracutConfig: features = append(features, New(name, nil)) case FeatureGrubConfig: @@ -144,6 +158,10 @@ func Get(names []string) ([]*Feature, error) { case FeatureGrubDefaultBootargs: features = append(features, New(name, nil)) case FeatureElementalSetup: + if slices.Contains(names, FeatureElementalRootfs) { + return features, fmt.Errorf("Conflicting features: %s and %s", FeatureElementalSetup, FeatureElementalRootfs) + } + units := []*systemd.Unit{ systemd.NewUnit("elemental-setup-reconcile.service"), systemd.NewUnit("elemental-setup-reconcile.timer"), diff --git a/pkg/systemd/unit.go b/pkg/systemd/unit.go index 1513875d119..f82eb221324 100644 --- a/pkg/systemd/unit.go +++ b/pkg/systemd/unit.go @@ -34,3 +34,8 @@ func Enable(runner v1.Runner, unit *Unit) error { _, err := runner.Run("systemctl", "enable", unit.Name) return err } + +func Start(runner v1.Runner, unit *Unit) error { + _, err := runner.Run("systemctl", "start", unit.Name) + return err +} diff --git a/pkg/types/v1/config.go b/pkg/types/v1/config.go index 5c024ba9071..e96829d0b09 100644 --- a/pkg/types/v1/config.go +++ b/pkg/types/v1/config.go @@ -241,7 +241,7 @@ type InitSpec struct { type MountSpec struct { ReadKernelCmdline bool `yaml:"read-kernel-cmdline,omitempty" mapstructure:"read-kernel-cmdline"` WriteFstab bool `yaml:"write-fstab,omitempty" mapstructure:"write-fstab"` - RunCloudInit bool `yaml:"run-cloud-init,omitempty" mapstructure:"run-cloud-init"` + RunRootfsService bool `yaml:"run-rootfs-service,omitempty" mapstructure:"run-rootfs-service"` RunFsck bool `yaml:"run-fsck,omitempty" mapstructure:"run-fsck"` Disable bool `yaml:"disable,omitempty" mapstructure:"disable"` Sysroot string `yaml:"sysroot,omitempty" mapstructure:"sysroot"`