From 6074a870ad7c63775a39c84b72f79699976a4a1f Mon Sep 17 00:00:00 2001 From: Noel Georgi Date: Wed, 20 Nov 2024 18:35:36 +0530 Subject: [PATCH] feat: add e2fsprogs to talos rootfs Bring in e2fsprogs from pkgs. Initial support for ext* filesystems. Fixes: #9746 Signed-off-by: Noel Georgi --- Dockerfile | 6 ++ Makefile | 4 +- pkg/machinery/constants/constants.go | 2 +- pkg/machinery/gendata/data/pkgs | 2 +- pkg/makefs/ext4.go | 54 ++++++++++++++++ pkg/makefs/ext4_test.go | 97 ++++++++++++++++++++++++++++ 6 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 pkg/makefs/ext4.go create mode 100644 pkg/makefs/ext4_test.go diff --git a/Dockerfile b/Dockerfile index 206bfda222..8dd4600de1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,7 @@ ARG PKG_CA_CERTIFICATES ARG PKG_CRYPTSETUP ARG PKG_CONTAINERD ARG PKG_DOSFSTOOLS +ARG PKG_E2FSPROGS ARG PKG_SYSTEMD_UDEVD ARG PKG_LIBCAP ARG PKG_GRUB @@ -62,6 +63,9 @@ FROM --platform=arm64 ${PKG_CONTAINERD} AS pkg-containerd-arm64 FROM --platform=amd64 ${PKG_DOSFSTOOLS} AS pkg-dosfstools-amd64 FROM --platform=arm64 ${PKG_DOSFSTOOLS} AS pkg-dosfstools-arm64 +FROM --platform=amd64 ${PKG_E2FSPROGS} AS pkg-e2fsprogs-amd64 +FROM --platform=arm64 ${PKG_E2FSPROGS} AS pkg-e2fsprogs-arm64 + FROM --platform=amd64 ${PKG_SYSTEMD_UDEVD} AS pkg-systemd-udevd-amd64 FROM --platform=arm64 ${PKG_SYSTEMD_UDEVD} AS pkg-systemd-udevd-arm64 @@ -673,6 +677,7 @@ COPY --link --from=pkg-flannel-cni-amd64 / /rootfs COPY --link --from=pkg-cryptsetup-amd64 / /rootfs COPY --link --from=pkg-containerd-amd64 / /rootfs COPY --link --from=pkg-dosfstools-amd64 / /rootfs +COPY --link --from=pkg-e2fsprogs-amd64 / /rootfs COPY --link --from=pkg-systemd-udevd-amd64 / /rootfs COPY --link --from=pkg-libcap-amd64 / /rootfs COPY --link --from=pkg-iptables-amd64 / /rootfs @@ -745,6 +750,7 @@ COPY --link --from=pkg-flannel-cni-arm64 / /rootfs COPY --link --from=pkg-cryptsetup-arm64 / /rootfs COPY --link --from=pkg-containerd-arm64 / /rootfs COPY --link --from=pkg-dosfstools-arm64 / /rootfs +COPY --link --from=pkg-e2fsprogs-arm64 / /rootfs COPY --link --from=pkg-systemd-udevd-arm64 / /rootfs COPY --link --from=pkg-libcap-arm64 / /rootfs COPY --link --from=pkg-iptables-arm64 / /rootfs diff --git a/Makefile b/Makefile index 69c62b0472..cb171f78d2 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ TOOLS ?= ghcr.io/siderolabs/tools:v1.9.0-alpha.0-9-ge061b6f DEBUG_TOOLS_SOURCE := scratch PKGS_PREFIX ?= ghcr.io/siderolabs -PKGS ?= v1.9.0-alpha.0-40-g567a14a +PKGS ?= v1.9.0-alpha.0-45-ga463a50 EXTRAS ?= v1.9.0-alpha.0-2-g78ba66b KRES_IMAGE ?= ghcr.io/siderolabs/kres:latest @@ -34,6 +34,7 @@ PKG_APPARMOR ?= $(PKGS_PREFIX)/apparmor:$(PKGS) PKG_CRYPTSETUP ?= $(PKGS_PREFIX)/cryptsetup:$(PKGS) PKG_CONTAINERD ?= $(PKGS_PREFIX)/containerd:$(PKGS) PKG_DOSFSTOOLS ?= $(PKGS_PREFIX)/dosfstools:$(PKGS) +PKG_E2FSPROGS ?= $(PKGS_PREFIX)/e2fsprogs:$(PKGS) PKG_SYSTEMD_UDEVD ?= $(PKGS_PREFIX)/systemd-udevd:$(PKGS) PKG_LIBCAP ?= $(PKGS_PREFIX)/libcap:$(PKGS) PKG_GRUB ?= $(PKGS_PREFIX)/grub:$(PKGS) @@ -209,6 +210,7 @@ COMMON_ARGS += --build-arg=PKG_APPARMOR=$(PKG_APPARMOR) COMMON_ARGS += --build-arg=PKG_CRYPTSETUP=$(PKG_CRYPTSETUP) COMMON_ARGS += --build-arg=PKG_CONTAINERD=$(PKG_CONTAINERD) COMMON_ARGS += --build-arg=PKG_DOSFSTOOLS=$(PKG_DOSFSTOOLS) +COMMON_ARGS += --build-arg=PKG_E2FSPROGS=$(PKG_E2FSPROGS) COMMON_ARGS += --build-arg=PKG_SYSTEMD_UDEVD=$(PKG_SYSTEMD_UDEVD) COMMON_ARGS += --build-arg=PKG_LIBCAP=$(PKG_LIBCAP) COMMON_ARGS += --build-arg=PKG_GRUB=$(PKG_GRUB) diff --git a/pkg/machinery/constants/constants.go b/pkg/machinery/constants/constants.go index 60aa6e7f4d..f7f5228ce9 100644 --- a/pkg/machinery/constants/constants.go +++ b/pkg/machinery/constants/constants.go @@ -14,7 +14,7 @@ import ( const ( // DefaultKernelVersion is the default Linux kernel version. - DefaultKernelVersion = "6.6.60-talos" + DefaultKernelVersion = "6.6.62-talos" // KernelModulesPath is the default path to the kernel modules without the kernel version. KernelModulesPath = "/lib/modules" diff --git a/pkg/machinery/gendata/data/pkgs b/pkg/machinery/gendata/data/pkgs index 4a90f9450d..98a6109bc2 100644 --- a/pkg/machinery/gendata/data/pkgs +++ b/pkg/machinery/gendata/data/pkgs @@ -1 +1 @@ -v1.9.0-alpha.0-40-g567a14a \ No newline at end of file +v1.9.0-alpha.0-45-ga463a50 \ No newline at end of file diff --git a/pkg/makefs/ext4.go b/pkg/makefs/ext4.go new file mode 100644 index 0000000000..404a1c3228 --- /dev/null +++ b/pkg/makefs/ext4.go @@ -0,0 +1,54 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package makefs + +import ( + "fmt" + + "github.com/google/uuid" + "github.com/siderolabs/go-cmd/pkg/cmd" + + "github.com/siderolabs/talos/pkg/imager/utils" +) + +// Ext4 creates a ext4 filesystem on the specified partition. +func Ext4(partname string, setters ...Option) error { + opts := NewDefaultOptions(setters...) + + var args []string + + if opts.Label != "" { + args = append(args, "-L", opts.Label) + } + + if opts.Force { + args = append(args, "-F") + } + + if opts.Reproducible { + if epoch, ok, err := utils.SourceDateEpoch(); err != nil { + return err + } else if ok { + // ref: https://gitlab.archlinux.org/archlinux/archiso/-/merge_requests/202/diffs + detUUID := uuid.NewSHA1(uuid.MustParse("93a870ff-8565-4cf3-a67b-f47299271a96"), []byte(fmt.Sprintf("%d ext4 hash seed", epoch))) + + args = append(args, "-U", detUUID.String()) + args = append(args, "-E", fmt.Sprintf("hash_seed=%s", detUUID.String())) + } + } + + args = append(args, partname) + + _, err := cmd.Run("mkfs.ext4", args...) + + return err +} + +// Ext4Resize expands a ext4 filesystem to the maximum possible. +func Ext4Resize(partname string) error { + _, err := cmd.Run("resize2fs", partname) + + return err +} diff --git a/pkg/makefs/ext4_test.go b/pkg/makefs/ext4_test.go new file mode 100644 index 0000000000..fdbb8d0fbb --- /dev/null +++ b/pkg/makefs/ext4_test.go @@ -0,0 +1,97 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package makefs_test + +import ( + "crypto/sha256" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/siderolabs/talos/pkg/makefs" +) + +// TestExt4Reproducibility tests that the ext4 filesystem is reproducible. +func TestExt4Reproducibility(t *testing.T) { + hostname, _ := os.Hostname() //nolint:errcheck + + if hostname == "buildkitsandbox" { + t.Skip("test not supported under buildkit as partition devices are not propagated from /dev") + } + + t.Setenv("SOURCE_DATE_EPOCH", "1732109929") + + tmpDir := t.TempDir() + + tempFile := filepath.Join(tmpDir, "reproducible-ext4.img") + + if _, err := os.Create(tempFile); err != nil { + t.Fatalf("failed to create file: %v", err) + } + + if err := os.Truncate(tempFile, 64*1024); err != nil { + t.Fatalf("failed to create file: %v", err) + } + + if err := makefs.Ext4(tempFile, makefs.WithReproducible(true)); err != nil { + t.Fatalf("failed to create ext4 filesystem: %v", err) + } + + // get the file sha256 checksum + fileData, err := os.ReadFile(tempFile) + if err != nil { + t.Fatalf("failed to read file: %v", err) + } + + sum1 := sha256.Sum256(fileData) + + // create the filesystem again + if err := makefs.Ext4(tempFile, makefs.WithReproducible(true), makefs.WithForce(true)); err != nil { + t.Fatalf("failed to create ext4 filesystem: %v", err) + } + + // get the file sha256 checksum + fileData, err = os.ReadFile(tempFile) + if err != nil { + t.Fatalf("failed to read file: %v", err) + } + + sum2 := sha256.Sum256(fileData) + + assert.Equal(t, sum1, sum2) +} + +// TestExt4Resize tests that the ext4 filesystem can be resized. +func TestExt4Resize(t *testing.T) { + hostname, _ := os.Hostname() //nolint:errcheck + + if hostname == "buildkitsandbox" { + t.Skip("test not supported under buildkit as partition devices are not propagated from /dev") + } + + tmpDir := t.TempDir() + + tempFile := filepath.Join(tmpDir, "resize-ext4.img") + + if _, err := os.Create(tempFile); err != nil { + t.Fatalf("failed to create file: %v", err) + } + + if err := os.Truncate(tempFile, 64*1024); err != nil { + t.Fatalf("failed to create file: %v", err) + } + + if err := makefs.Ext4(tempFile); err != nil { + t.Fatalf("failed to create ext4 filesystem: %v", err) + } + + if err := os.Truncate(tempFile, 128*1024); err != nil { + t.Fatalf("failed to resize file: %v", err) + } + + assert.NoError(t, makefs.Ext4Resize(tempFile)) +}