diff --git a/pkg/machinery/platforms/platforms.go b/pkg/machinery/platforms/platforms.go new file mode 100644 index 0000000000..57daea045d --- /dev/null +++ b/pkg/machinery/platforms/platforms.go @@ -0,0 +1,386 @@ +// 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 platforms provides meta information about supported Talos platforms, boards, etc. +package platforms + +import ( + "fmt" + + "github.com/blang/semver/v4" +) + +// Arch represents an architecture supported by Talos. +type Arch = string + +// Architecture constants. +const ( + ArchAmd64 = "amd64" + ArchArm64 = "arm64" +) + +// BootMethod represents a boot method supported by Talos. +type BootMethod = string + +// BootMethod constants. +const ( + BootMethodDiskImage = "disk-image" + BootMethodISO = "iso" + BootMethodPXE = "pxe" +) + +// Platform represents a platform supported by Talos. +type Platform struct { + Name string + + Label string + Description string + + MinVersion semver.Version + Architectures []Arch + Documentation string + DiskImageSuffix string + BootMethods []BootMethod + SecureBootSupported bool +} + +// NotOnlyDiskImage is true if the platform supports boot methods other than disk-image. +func (p Platform) NotOnlyDiskImage() bool { + if len(p.BootMethods) == 1 && p.BootMethods[0] == BootMethodDiskImage { + return false + } + + return true +} + +// DiskImageDefaultPath returns the path to the disk image for the platform. +func (p Platform) DiskImageDefaultPath(arch Arch) string { + return p.DiskImagePath(arch, p.DiskImageSuffix) +} + +// SecureBootDiskImageDefaultPath returns the path to the SecureBoot disk image for the platform. +func (p Platform) SecureBootDiskImageDefaultPath(arch Arch) string { + return p.SecureBootDiskImagePath(arch, p.DiskImageSuffix) +} + +// DiskImagePath returns the path to the disk image for the platform and suffix. +func (p Platform) DiskImagePath(arch Arch, suffix string) string { + return fmt.Sprintf("%s-%s.%s", p.Name, arch, suffix) +} + +// SecureBootDiskImagePath returns the path to the SecureBoot disk image for the platform and suffix. +func (p Platform) SecureBootDiskImagePath(arch Arch, suffix string) string { + return fmt.Sprintf("%s-%s-secureboot.%s", p.Name, arch, suffix) +} + +// ISOPath returns the path to the ISO for the platform. +func (p Platform) ISOPath(arch Arch) string { + return fmt.Sprintf("%s-%s.iso", p.Name, arch) +} + +// SecureBootISOPath returns the path to the SecureBoot ISO for the platform. +func (p Platform) SecureBootISOPath(arch Arch) string { + return fmt.Sprintf("%s-%s-secureboot.iso", p.Name, arch) +} + +// PXEScriptPath returns the path to the PXE script for the platform. +func (p Platform) PXEScriptPath(arch Arch) string { + return fmt.Sprintf("%s-%s", p.Name, arch) +} + +// SecureBootPXEScriptPath returns the path to the SecureBoot PXE script for the platform. +func (p Platform) SecureBootPXEScriptPath(arch Arch) string { + return fmt.Sprintf("%s-%s-secureboot", p.Name, arch) +} + +// UKIPath returns the path to the UKI for the platform. +func (p Platform) UKIPath(arch Arch) string { + return fmt.Sprintf("%s-%s-uki.efi", p.Name, arch) +} + +// SecureBootUKIPath returns the path to the SecureBoot UKI for the platform. +func (p Platform) SecureBootUKIPath(arch Arch) string { + return fmt.Sprintf("%s-%s-secureboot-uki.efi", p.Name, arch) +} + +// KernelPath returns the path to the kernel for the platform. +// +// NB: Kernel path doesn't depend on the platform. +func (p Platform) KernelPath(arch Arch) string { + return fmt.Sprintf("kernel-%s", arch) +} + +// InitramfsPath returns the path to the initramfs for the platform. +// +// NB: Initramfs path doesn't depend on the platform. +func (p Platform) InitramfsPath(arch Arch) string { + return fmt.Sprintf("initramfs-%s.xz", arch) +} + +// CmdlinePath returns the path to the cmdline for the platform. +func (p Platform) CmdlinePath(arch Arch) string { + return fmt.Sprintf("cmdline-%s-%s", p.Name, arch) +} + +// MetalPlatform returns a metal platform. +func MetalPlatform() Platform { + return Platform{ + Name: "metal", + + Label: "Bare Metal", + Description: "Runs on bare-metal servers", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/bare-metal-platforms/", + DiskImageSuffix: "raw.zst", + BootMethods: []BootMethod{ + BootMethodISO, + BootMethodDiskImage, + BootMethodPXE, + }, + } +} + +// CloudPlatforms returns a list of supported cloud platforms. +func CloudPlatforms() []Platform { + // metal platform is not listed here, as it is handled separately. + return []Platform{ + // Tier 1 + { + Name: "aws", + + Label: "Amazon Web Services (AWS)", + Description: "Runs on AWS VMs booted from an AMI", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/aws/", + DiskImageSuffix: "raw.xz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "gcp", + + Label: "Google Cloud (GCP)", + Description: "Runs on Google Cloud VMs booted from a disk image", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/gcp/", + DiskImageSuffix: "raw.tar.gz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "equinixMetal", + + Label: "Equinix Metal", + Description: "Runs on Equinix Metal bare-metal servers", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/bare-metal-platforms/equinix-metal/", + BootMethods: []BootMethod{ + BootMethodPXE, + }, + }, + // Tier 2 + { + Name: "azure", + + Label: "Microsoft Azure", + Description: "Runs on Microsoft Azure Linux Virtual Machines", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/azure/", + DiskImageSuffix: "vhd.xz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "digital-ocean", + + Label: "Digital Ocean", + Description: "Runs on Digital Ocean droplets", + + Architectures: []Arch{ArchAmd64}, + Documentation: "/talos-guides/install/cloud-platforms/digitalocean/", + DiskImageSuffix: "raw.gz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "nocloud", + + Label: "Nocloud", + Description: "Runs on various hypervisors supporting 'nocloud' metadata (Proxmox, Oxide Computer, etc.)", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/nocloud/", + DiskImageSuffix: "raw.xz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + BootMethodISO, + BootMethodPXE, + }, + SecureBootSupported: true, + }, + { + Name: "openstack", + + Label: "OpenStack", + Description: "Runs on OpenStack virtual machines", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/openstack/", + DiskImageSuffix: "raw.xz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + BootMethodISO, + BootMethodPXE, + }, + }, + { + Name: "vmware", + + Label: "VMWare", + Description: "Runs on VMWare ESXi virtual machines", + + Architectures: []Arch{ArchAmd64}, + Documentation: "/talos-guides/install/virtualized-platforms/vmware/", + DiskImageSuffix: "ova", + BootMethods: []BootMethod{ + BootMethodDiskImage, + BootMethodISO, + }, + }, + // Tier 3 + { + Name: "akamai", + + Label: "Akamai", + Description: "Runs on Akamai Cloud (Linode) virtual machines", + + Architectures: []Arch{ArchAmd64}, + MinVersion: semver.MustParse("1.7.0"), + Documentation: "/talos-guides/install/cloud-platforms/akamai/", + DiskImageSuffix: "raw.gz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "cloudstack", + + Label: "Apache CloudStack", + Description: "Runs on Apache CloudStack virtual machines", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/cloudstack/", + DiskImageSuffix: "raw.gz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + MinVersion: semver.MustParse("1.8.0-alpha.2"), + }, + { + Name: "hcloud", + + Label: "Hetzner", + Description: "Runs on Hetzner virtual machines", + + Architectures: []Arch{ArchAmd64}, + Documentation: "/talos-guides/install/cloud-platforms/hetzner/", + DiskImageSuffix: "raw.xz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "oracle", + + Label: "Oracle Cloud", + Description: "Runs on Oracle Cloud virtual machines", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/oracle/", + DiskImageSuffix: "raw.xz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "upcloud", + + Label: "UpCloud", + Description: "Runs on UpCloud virtual machines", + + Architectures: []Arch{ArchAmd64}, + Documentation: "/talos-guides/install/cloud-platforms/ucloud/", + DiskImageSuffix: "raw.xz", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + }, + { + Name: "vultr", + + Label: "Vultr", + Description: "Runs on Vultr Cloud Compute virtual machines", + + Architectures: []Arch{ArchAmd64}, + Documentation: "/talos-guides/install/cloud-platforms/vultr/", + BootMethods: []BootMethod{ + BootMethodISO, + BootMethodPXE, + }, + }, + // Tier 4 (no documentation). + { + Name: "exoscale", + + Label: "Exoscale", + Description: "Runs on Exoscale virtual machines", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + Documentation: "/talos-guides/install/cloud-platforms/exoscale/", + DiskImageSuffix: "qcow2", + BootMethods: []BootMethod{ + BootMethodDiskImage, + }, + MinVersion: semver.MustParse("1.3.0"), + }, + { + Name: "opennebula", + + Label: "OpenNebula", + Description: "Runs on OpenNebula virtual machines", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + DiskImageSuffix: "raw.zst", + Documentation: "/talos-guides/install/virtualized-platforms/opennebula/", + BootMethods: []BootMethod{ + BootMethodDiskImage, + BootMethodISO, + }, + MinVersion: semver.MustParse("1.7.0"), + }, + { + Name: "scaleway", + + Label: "Scaleway", + Description: "Runs on Scaleway virtual machines", + + Architectures: []Arch{ArchAmd64, ArchArm64}, + DiskImageSuffix: "raw.zst", + Documentation: "/talos-guides/install/cloud-platforms/scaleway/", + BootMethods: []BootMethod{ + BootMethodDiskImage, + BootMethodISO, + }, + }, + } +} diff --git a/pkg/machinery/platforms/platforms_test.go b/pkg/machinery/platforms/platforms_test.go new file mode 100644 index 0000000000..92e9284ec7 --- /dev/null +++ b/pkg/machinery/platforms/platforms_test.go @@ -0,0 +1,86 @@ +// 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 platforms_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/siderolabs/talos/pkg/machinery/platforms" +) + +func TestPlatform(t *testing.T) { + t.Parallel() + + for _, test := range []struct { + name string + + platform platforms.Platform + + expectedDefaultDiskImagePath string + expectedISOPath string + expectedSecureBootISOPath string + expectedPXEPath string + expectedSecureBootPXEPath string + expectedUKIPath string + expectedSecureBootUKIPath string + expectedKernelPath string + expectedInitramfsPath string + expectedCmdlinePath string + expectedNotOnlyDiskImage bool + }{ + { + name: "metal", + + platform: platforms.MetalPlatform(), + + expectedDefaultDiskImagePath: "metal-amd64.raw.zst", + expectedISOPath: "metal-amd64.iso", + expectedSecureBootISOPath: "metal-amd64-secureboot.iso", + expectedPXEPath: "metal-amd64", + expectedSecureBootPXEPath: "metal-amd64-secureboot", + expectedUKIPath: "metal-amd64-uki.efi", + expectedSecureBootUKIPath: "metal-amd64-secureboot-uki.efi", + expectedKernelPath: "kernel-amd64", + expectedInitramfsPath: "initramfs-amd64.xz", + expectedCmdlinePath: "cmdline-metal-amd64", + expectedNotOnlyDiskImage: true, + }, + { + name: "aws", + + platform: platforms.CloudPlatforms()[0], + + expectedDefaultDiskImagePath: "aws-amd64.raw.xz", + expectedISOPath: "aws-amd64.iso", + expectedSecureBootISOPath: "aws-amd64-secureboot.iso", + expectedPXEPath: "aws-amd64", + expectedSecureBootPXEPath: "aws-amd64-secureboot", + expectedUKIPath: "aws-amd64-uki.efi", + expectedSecureBootUKIPath: "aws-amd64-secureboot-uki.efi", + expectedKernelPath: "kernel-amd64", + expectedInitramfsPath: "initramfs-amd64.xz", + expectedCmdlinePath: "cmdline-aws-amd64", + expectedNotOnlyDiskImage: false, + }, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + assert.Equal(t, test.expectedDefaultDiskImagePath, test.platform.DiskImageDefaultPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedISOPath, test.platform.ISOPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedSecureBootISOPath, test.platform.SecureBootISOPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedPXEPath, test.platform.PXEScriptPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedSecureBootPXEPath, test.platform.SecureBootPXEScriptPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedUKIPath, test.platform.UKIPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedSecureBootUKIPath, test.platform.SecureBootUKIPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedKernelPath, test.platform.KernelPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedInitramfsPath, test.platform.InitramfsPath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedCmdlinePath, test.platform.CmdlinePath(platforms.ArchAmd64)) + assert.Equal(t, test.expectedNotOnlyDiskImage, test.platform.NotOnlyDiskImage()) + }) + } +} diff --git a/pkg/machinery/platforms/sbcs.go b/pkg/machinery/platforms/sbcs.go new file mode 100644 index 0000000000..873ff1dbb3 --- /dev/null +++ b/pkg/machinery/platforms/sbcs.go @@ -0,0 +1,220 @@ +// 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 platforms + +import ( + "github.com/blang/semver/v4" + + "github.com/siderolabs/talos/pkg/machinery/imager/quirks" +) + +// SBC describes a Single Board Computer configuration. +type SBC struct { + Name string + + // For Talos < 1.7. + BoardName string + + // For Talos 1.7+ + OverlayName string + OverlayImage string + + Label string + Documentation string + + MinVersion semver.Version +} + +// DiskImagePath returns the path to the disk image for the SBC. +func (s SBC) DiskImagePath(talosVersion string) string { + if quirks.New(talosVersion).SupportsOverlay() { + return "metal-arm64.raw.xz" + } + + return "metal-" + s.BoardName + "-arm64.raw.xz" +} + +// SBCs returns a list of supported Single Board Computers. +func SBCs() []SBC { + return []SBC{ + { + Name: "rpi_generic", + + BoardName: "rpi_generic", + + OverlayName: "rpi_generic", + OverlayImage: "siderolabs/sbc-raspberrypi", + + Label: "Raspberry Pi Series", + Documentation: "/talos-guides/install/single-board-computers/rpi_generic/", + }, + { + Name: "bananapi_m64", + + BoardName: "bananapi_m64", + + OverlayName: "bananapi_m64", + OverlayImage: "siderolabs/sbc-allwinner", + + Label: "Banana Pi M64", + Documentation: "/talos-guides/install/single-board-computers/bananapi_m64/", + }, + { + Name: "nanopi_r4s", + + BoardName: "rockpi_4", + + OverlayName: "nanopi-r4s", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Friendlyelec Nano PI R4S", + Documentation: "/talos-guides/install/single-board-computers/nanopi_r4s/", + + MinVersion: semver.MustParse("1.3.0"), + }, + { + Name: "nanopi_r5s", + + OverlayName: "nanopi-r5s", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Friendlyelec Nano PI R5S", + + MinVersion: semver.MustParse("1.8.0-alpha.2"), + }, + { + Name: "jetson_nano", + + BoardName: "jetson_nano", + + OverlayName: "jetson_nano", + OverlayImage: "siderolabs/sbc-jetson", + + Label: "Jetson Nano", + Documentation: "/talos-guides/install/single-board-computers/jetson_nano/", + }, + { + Name: "libretech_all_h3_cc_h5", + + BoardName: "libretech_all_h3_cc_h5", + + OverlayName: "libretech_all_h3_cc_h5", + OverlayImage: "siderolabs/sbc-allwinner", + + Label: "Libre Computer Board ALL-H3-CC", + Documentation: "/talos-guides/install/single-board-computers/libretech_all_h3_cc_h5/", + }, + { + Name: "orangepi_r1_plus_lts", + + OverlayName: "orangepi-r1-plus-lts", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Orange Pi R1 Plus LTS", + Documentation: "/talos-guides/install/single-board-computers/orangepi_r1_plus_lts/", + + MinVersion: semver.MustParse("1.7.0"), + }, + { + Name: "pine64", + + BoardName: "pine64", + + OverlayName: "pine64", + OverlayImage: "siderolabs/sbc-allwinner", + + Label: "Pine64", + Documentation: "/talos-guides/install/single-board-computers/pine64/", + }, + { + Name: "rock64", + + BoardName: "rock64", + + OverlayName: "rock64", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Pine64 Rock64", + Documentation: "/talos-guides/install/single-board-computers/rock64/", + }, + { + Name: "rock4cplus", + + OverlayName: "rock4cplus", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Radxa ROCK 4C Plus", + Documentation: "/talos-guides/install/single-board-computers/rock4cplus/", + + MinVersion: semver.MustParse("1.7.0"), + }, + { + Name: "rock4se", + + OverlayName: "rock4se", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Radxa ROCK 4SE", + Documentation: "", // missing + + MinVersion: semver.MustParse("1.8.0-alpha.1"), + }, + { + Name: "rock5b", + + OverlayName: "rock5b", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Radxa ROCK 5B", + Documentation: "/talos-guides/install/single-board-computers/rock5b/", + + MinVersion: semver.MustParse("1.9.2"), + }, + { + Name: "rockpi_4", + + BoardName: "rockpi_4", + + OverlayName: "rockpi4", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Radxa ROCK PI 4", + Documentation: "/talos-guides/install/single-board-computers/rockpi_4/", + }, + { + Name: "rockpi_4c", + + BoardName: "rockpi_4c", + + OverlayName: "rockpi4c", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Radxa ROCK PI 4C", + Documentation: "/talos-guides/install/single-board-computers/rockpi_4c/", + }, + { + Name: "helios64", + + OverlayName: "helios64", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Kobol Helios64", + Documentation: "", // missing + + MinVersion: semver.MustParse("1.8.0-alpha.2"), + }, + { + Name: "turingrk1", + + OverlayName: "turingrk1", + OverlayImage: "siderolabs/sbc-rockchip", + + Label: "Turing RK1", + Documentation: "/talos-guides/install/single-board-computers/turing_rk1/", + + MinVersion: semver.MustParse("1.9.0-beta.0"), + }, + } +} diff --git a/pkg/machinery/platforms/sbcs_test.go b/pkg/machinery/platforms/sbcs_test.go new file mode 100644 index 0000000000..9e7c584a39 --- /dev/null +++ b/pkg/machinery/platforms/sbcs_test.go @@ -0,0 +1,49 @@ +// 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 platforms_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/siderolabs/talos/pkg/machinery/platforms" +) + +func TestSBC(t *testing.T) { + t.Parallel() + + for _, test := range []struct { + name string + + sbc platforms.SBC + talosVersion string + + expectedDiskImagePath string + }{ + { + name: "rpi_generic", + + sbc: platforms.SBCs()[0], + talosVersion: "1.9.0", + + expectedDiskImagePath: "metal-arm64.raw.xz", + }, + { + name: "bananapi_m64", + + sbc: platforms.SBCs()[0], + talosVersion: "1.4.0", + + expectedDiskImagePath: "metal-rpi_generic-arm64.raw.xz", + }, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + assert.Equal(t, test.expectedDiskImagePath, test.sbc.DiskImagePath(test.talosVersion)) + }) + } +}