From 586d2d7d7fa36e2b7786ef9986c27b590a9b3edc Mon Sep 17 00:00:00 2001 From: Artem Chernyshev Date: Fri, 19 Apr 2024 14:12:23 +0300 Subject: [PATCH] feat: generate overlay info by extracting board kernel args This is compatibility code for SBCs running Talos < 1.7.x. With this change it's possible to do seamless upgrade of SBCs running without overlays. Fixes: https://github.com/siderolabs/omni/issues/145 Signed-off-by: Artem Chernyshev --- go.mod | 1 + go.sum | 2 + .../controllers/omni/installation_media.go | 26 +++++--- .../omni/internal/boards/boards.go | 65 +++++++++++++++++++ .../omni/internal/task/machine/poll.go | 38 +++++++++++ 5 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 internal/backend/runtime/omni/controllers/omni/internal/boards/boards.go diff --git a/go.mod b/go.mod index 0637e609..5ee73540 100644 --- a/go.mod +++ b/go.mod @@ -63,6 +63,7 @@ require ( github.com/siderolabs/go-kubernetes v0.2.8 github.com/siderolabs/go-loadbalancer v0.3.3 github.com/siderolabs/go-pointer v1.0.0 + github.com/siderolabs/go-procfs v0.1.2 github.com/siderolabs/go-retry v0.3.3 github.com/siderolabs/go-tail v0.1.0 github.com/siderolabs/go-talos-support v0.1.0 diff --git a/go.sum b/go.sum index 52463b2c..17725b7f 100644 --- a/go.sum +++ b/go.sum @@ -473,6 +473,8 @@ github.com/siderolabs/go-loadbalancer v0.3.3 h1:D6ONnP9Erlh4TS6kV9L7ocnfrNYCA/58 github.com/siderolabs/go-loadbalancer v0.3.3/go.mod h1:7j4Q9peU/UFuTNSFfwhKLQ028CNkyMkAdGnSi1Dm7Jw= github.com/siderolabs/go-pointer v1.0.0 h1:6TshPKep2doDQJAAtHUuHWXbca8ZfyRySjSBT/4GsMU= github.com/siderolabs/go-pointer v1.0.0/go.mod h1:HTRFUNYa3R+k0FFKNv11zgkaCLzEkWVzoYZ433P3kHc= +github.com/siderolabs/go-procfs v0.1.2 h1:bDs9hHyYGE2HO1frpmUsD60yg80VIEDrx31fkbi4C8M= +github.com/siderolabs/go-procfs v0.1.2/go.mod h1:dBzQXobsM7+TWRRI3DS9X7vAuj8Nkfgu3Z/U9iY3ZTY= github.com/siderolabs/go-retry v0.3.3 h1:zKV+S1vumtO72E6sYsLlmIdV/G/GcYSBLiEx/c9oCEg= github.com/siderolabs/go-retry v0.3.3/go.mod h1:Ff/VGc7v7un4uQg3DybgrmOWHEmJ8BzZds/XNn/BqMI= github.com/siderolabs/go-tail v0.1.0 h1:U+ZClt7BXLGsxDNU/XQ12sz7lQElfFZBYEPdkW78Qro= diff --git a/internal/backend/runtime/omni/controllers/omni/installation_media.go b/internal/backend/runtime/omni/controllers/omni/installation_media.go index 608ee3ed..dcf98ca0 100644 --- a/internal/backend/runtime/omni/controllers/omni/installation_media.go +++ b/internal/backend/runtime/omni/controllers/omni/installation_media.go @@ -16,6 +16,7 @@ import ( "github.com/siderolabs/omni/client/pkg/omni/resources" "github.com/siderolabs/omni/client/pkg/omni/resources/omni" + "github.com/siderolabs/omni/internal/backend/runtime/omni/controllers/omni/internal/boards" "github.com/siderolabs/omni/internal/pkg/config" ) @@ -245,10 +246,9 @@ var installationMedia = []installationMediaSpec{ { Name: "Banana Pi BPI-M64 (arm64)", Architecture: arm64Arch, + Profile: constants.BoardBananaPiM64, Type: rawType, SBC: true, - Overlay: "bananapi_m64", - Profile: constants.BoardBananaPiM64, ContentType: "application/x-xz", }, { @@ -257,7 +257,6 @@ var installationMedia = []installationMediaSpec{ Profile: constants.BoardJetsonNano, Type: rawType, SBC: true, - Overlay: "jetson_nano", ContentType: "application/x-xz", }, { @@ -266,7 +265,6 @@ var installationMedia = []installationMediaSpec{ Profile: constants.BoardLibretechAllH3CCH5, Type: rawType, SBC: true, - Overlay: "libretech_all_h3_cc_h5", ContentType: "application/x-xz", }, { @@ -275,7 +273,6 @@ var installationMedia = []installationMediaSpec{ Profile: constants.BoardPine64, Type: rawType, SBC: true, - Overlay: "pine64", ContentType: "application/x-xz", }, { @@ -284,7 +281,6 @@ var installationMedia = []installationMediaSpec{ Profile: constants.BoardRock64, Type: rawType, SBC: true, - Overlay: "rock64", ContentType: "application/x-xz", }, { @@ -293,7 +289,6 @@ var installationMedia = []installationMediaSpec{ Profile: constants.BoardRockpi4, Type: rawType, SBC: true, - Overlay: "rockpi4", ContentType: "application/x-xz", }, { @@ -302,7 +297,6 @@ var installationMedia = []installationMediaSpec{ Profile: constants.BoardRockpi4c, Type: rawType, SBC: true, - Overlay: "rockpi4c", ContentType: "application/x-xz", }, { @@ -311,7 +305,14 @@ var installationMedia = []installationMediaSpec{ Profile: constants.BoardRPiGeneric, Type: rawType, SBC: true, - Overlay: "rpi_generic", + ContentType: "application/x-xz", + }, + { + Name: "Nano Pi R4S", + Architecture: arm64Arch, + Profile: constants.BoardNanoPiR4S, + Type: rawType, + SBC: true, ContentType: "application/x-xz", }, } @@ -360,7 +361,12 @@ func (ctrl *InstallationMediaController) Run(ctx context.Context, r controller.R newMedia.TypedSpec().Value.DestFilePrefix = fmt.Sprintf("%s-omni-%s", fname.srcPrefix, config.Config.Name) newMedia.TypedSpec().Value.Extension = fname.extension newMedia.TypedSpec().Value.NoSecureBoot = m.SBC - newMedia.TypedSpec().Value.Overlay = m.Overlay + + overlay := boards.GetOverlay(m.Profile) + + if overlay != nil { + newMedia.TypedSpec().Value.Overlay = overlay.Name + } tracker.keep(newMedia) diff --git a/internal/backend/runtime/omni/controllers/omni/internal/boards/boards.go b/internal/backend/runtime/omni/controllers/omni/internal/boards/boards.go new file mode 100644 index 00000000..fcccb26e --- /dev/null +++ b/internal/backend/runtime/omni/controllers/omni/internal/boards/boards.go @@ -0,0 +1,65 @@ +// Copyright (c) 2024 Sidero Labs, Inc. +// +// Use of this software is governed by the Business Source License +// included in the LICENSE file. + +// Package boards contains helpers for mapping board types to the overlays. +package boards + +import ( + "github.com/siderolabs/image-factory/pkg/schematic" + "github.com/siderolabs/talos/pkg/machinery/constants" +) + +// GetOverlay converts board constant to it's overlay. +func GetOverlay(board string) *schematic.Overlay { + switch board { + case constants.BoardBananaPiM64: + return &schematic.Overlay{ + Name: "bananapi_m64", + Image: "siderolabs/sbc-allwinner", + } + case constants.BoardJetsonNano: + return &schematic.Overlay{ + Name: "jetson_nano", + Image: "siderolabs/sbc-jetson", + } + case constants.BoardLibretechAllH3CCH5: + return &schematic.Overlay{ + Name: "libretech_all_h3_cc_h5", + Image: "siderolabs/sbc-allwinner", + } + case constants.BoardPine64: + return &schematic.Overlay{ + Name: "pine64", + Image: "siderolabs/sbc-allwinner", + } + case constants.BoardRock64: + return &schematic.Overlay{ + Name: "bananapi_m64", + Image: "siderolabs/sbc-allwinner", + } + case constants.BoardRockpi4: + return &schematic.Overlay{ + Name: "rockpi4", + Image: "siderolabs/sbc-rockchip", + } + case constants.BoardRockpi4c: + return &schematic.Overlay{ + Name: "rockpi4c", + Image: "siderolabs/sbc-rockchip", + } + case constants.BoardNanoPiR4S: + return &schematic.Overlay{ + Name: "nanopi-r4s", + Image: "siderolabs/sbc-rockchip", + } + case constants.BoardRPiGeneric: + return &schematic.Overlay{ + Name: "rpi_generic", + Image: "siderolabs/sbc-raspberrypi", + } + } + + return nil +} diff --git a/internal/backend/runtime/omni/controllers/omni/internal/task/machine/poll.go b/internal/backend/runtime/omni/controllers/omni/internal/task/machine/poll.go index 0b8c0e81..af617c85 100644 --- a/internal/backend/runtime/omni/controllers/omni/internal/task/machine/poll.go +++ b/internal/backend/runtime/omni/controllers/omni/internal/task/machine/poll.go @@ -9,14 +9,18 @@ import ( "context" "errors" "fmt" + "io" "maps" "github.com/cosi-project/runtime/pkg/safe" "github.com/cosi-project/runtime/pkg/state" "github.com/siderolabs/gen/value" "github.com/siderolabs/go-pointer" + "github.com/siderolabs/go-procfs/procfs" + "github.com/siderolabs/image-factory/pkg/schematic" "github.com/siderolabs/talos/pkg/machinery/client" "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1" + "github.com/siderolabs/talos/pkg/machinery/constants" "github.com/siderolabs/talos/pkg/machinery/nethelpers" "github.com/siderolabs/talos/pkg/machinery/resources/config" "github.com/siderolabs/talos/pkg/machinery/resources/hardware" @@ -28,6 +32,7 @@ import ( "github.com/siderolabs/omni/client/api/omni/specs" omnimeta "github.com/siderolabs/omni/client/pkg/meta" + "github.com/siderolabs/omni/internal/backend/runtime/omni/controllers/omni/internal/boards" "github.com/siderolabs/omni/internal/backend/runtime/omni/controllers/omni/internal/talos" ) @@ -327,6 +332,28 @@ func pollMeta(ctx context.Context, c *client.Client, info *Info) error { }) } +func detectOverlay(ctx context.Context, c *client.Client) (*schematic.Overlay, error) { + reader, err := c.Read(ctx, "/proc/cmdline") + if err != nil { + return nil, err + } + + data, err := io.ReadAll(reader) + if err != nil { + return nil, err + } + + cmdline := procfs.NewCmdline(string(data)) + + value := cmdline.Get(constants.KernelParamBoard) + + if value == nil || value.Get(0) == nil { + return nil, nil //nolint:nilnil + } + + return boards.GetOverlay(*value.Get(0)), nil +} + func pollExtensions(ctx context.Context, c *client.Client, info *Info) error { machineSchematic := &specs.MachineStatusSpec_Schematic{} info.Schematic = machineSchematic @@ -344,6 +371,17 @@ func pollExtensions(ctx context.Context, c *client.Client, info *Info) error { return err } + if schematicInfo.Schematic.Overlay.Name == "" { + overlay, err := detectOverlay(ctx, c) + if err != nil && status.Code(err) != codes.Unimplemented { + return err + } + + if overlay != nil { + schematicInfo.Schematic.Overlay = *overlay + } + } + machineSchematic.Id = schematicInfo.ID machineSchematic.Extensions = schematicInfo.Extensions machineSchematic.Overlay = &specs.MachineStatusSpec_Schematic_Overlay{