2019-10-25 23:45:41 +03:00
// 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/.
2019-07-31 17:16:10 +00:00
2020-04-23 21:12:44 -07:00
package install
2019-07-31 17:16:10 +00:00
import (
2024-02-29 20:26:46 +05:30
"bytes"
2022-11-24 22:48:22 +04:00
"context"
2024-02-13 15:32:06 +03:00
"errors"
2019-10-16 04:50:06 +00:00
"fmt"
2020-03-10 07:52:10 -07:00
"log"
2023-06-14 17:33:11 +04:00
"os"
2024-02-29 20:26:46 +05:30
"path/filepath"
2024-08-25 10:26:49 +05:30
"slices"
2019-07-31 17:16:10 +00:00
2024-06-11 16:19:04 +04:00
"github.com/google/uuid"
"github.com/siderolabs/go-blockdevice/v2/blkid"
"github.com/siderolabs/go-blockdevice/v2/block"
"github.com/siderolabs/go-blockdevice/v2/partitioning"
"github.com/siderolabs/go-blockdevice/v2/partitioning/gpt"
"github.com/siderolabs/go-pointer"
2022-11-01 12:06:37 +04:00
"github.com/siderolabs/go-procfs/procfs"
2024-02-29 20:26:46 +05:30
"gopkg.in/yaml.v3"
2020-10-05 20:35:41 +03:00
2022-11-02 15:06:45 +04:00
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader"
2023-07-27 12:50:06 +04:00
bootloaderoptions "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/options"
2023-03-14 14:33:11 +04:00
"github.com/siderolabs/talos/internal/pkg/meta"
2024-06-11 16:19:04 +04:00
"github.com/siderolabs/talos/internal/pkg/partition"
2024-02-29 20:26:46 +05:30
"github.com/siderolabs/talos/pkg/imager/overlay/executor"
2024-06-11 16:19:04 +04:00
"github.com/siderolabs/talos/pkg/machinery/compatibility"
2022-11-02 15:06:45 +04:00
"github.com/siderolabs/talos/pkg/machinery/constants"
2024-06-11 16:19:04 +04:00
"github.com/siderolabs/talos/pkg/machinery/imager/quirks"
2022-11-02 15:06:45 +04:00
"github.com/siderolabs/talos/pkg/machinery/kernel"
2024-02-29 20:26:46 +05:30
"github.com/siderolabs/talos/pkg/machinery/overlay"
2024-03-05 18:04:11 +03:00
"github.com/siderolabs/talos/pkg/machinery/version"
2019-07-31 17:16:10 +00:00
)
2020-04-23 21:12:44 -07:00
// Options represents the set of options available for an install.
type Options struct {
2024-02-29 20:26:46 +05:30
ConfigSource string
Disk string
Platform string
Arch string
Board string
ExtraKernelArgs [ ] string
Upgrade bool
Force bool
Zero bool
LegacyBIOSSupport bool
MetaValues MetaValues
OverlayInstaller overlay . Installer [ overlay . ExtraOptions ]
2024-04-16 19:52:31 +04:00
OverlayName string
2024-02-29 20:26:46 +05:30
OverlayExtractedDir string
ExtraOptions overlay . ExtraOptions
2023-07-27 12:50:06 +04:00
// Options specific for the image creation mode.
ImageSecureboot bool
Version string
BootAssets bootloaderoptions . BootAssets
2023-08-04 23:11:16 +04:00
Printf func ( string , ... any )
2023-08-31 22:21:41 +04:00
MountPrefix string
2023-07-27 12:50:06 +04:00
}
// Mode is the install mode.
type Mode int
const (
// ModeInstall is the install mode.
ModeInstall Mode = iota
// ModeUpgrade is the upgrade mode.
ModeUpgrade
// ModeImage is the image creation mode.
ModeImage
)
// IsImage returns true if the mode is image creation.
func ( m Mode ) IsImage ( ) bool {
return m == ModeImage
2020-04-23 21:12:44 -07:00
}
2024-06-11 16:19:04 +04:00
const typeGPT = "gpt"
2020-04-23 21:12:44 -07:00
// Install installs Talos.
2024-02-29 20:26:46 +05:30
//
//nolint:gocyclo
func Install ( ctx context . Context , p runtime . Platform , mode Mode , opts * Options ) error {
overlayPresent := overlayPresent ( )
if b := getBoard ( ) ; b != constants . BoardNone && ! overlayPresent {
return fmt . Errorf ( "using standard installer image is not supported for board: %s, use an installer with overlay" , b )
}
2024-04-16 19:52:31 +04:00
if overlayPresent {
extraOptionsBytes , err := os . ReadFile ( constants . ImagerOverlayExtraOptionsPath )
if err != nil {
return err
}
var extraOptions overlay . ExtraOptions
decoder := yaml . NewDecoder ( bytes . NewReader ( extraOptionsBytes ) )
decoder . KnownFields ( true )
if err := decoder . Decode ( & extraOptions ) ; err != nil {
return fmt . Errorf ( "failed to decode extra options: %w" , err )
}
opts . OverlayInstaller = executor . New ( constants . ImagerOverlayInstallerDefaultPath )
opts . ExtraOptions = extraOptions
}
2020-04-23 21:12:44 -07:00
cmdline := procfs . NewCmdline ( "" )
cmdline . Append ( constants . KernelParamPlatform , p . Name ( ) )
2020-11-25 18:00:02 +03:00
if opts . ConfigSource != "" {
cmdline . Append ( constants . KernelParamConfig , opts . ConfigSource )
}
2020-04-23 21:12:44 -07:00
2024-04-02 14:40:38 +04:00
cmdline . SetAll ( p . KernelArgs ( opts . Arch ) . Strings ( ) )
2020-04-23 21:12:44 -07:00
2020-12-10 17:10:06 +03:00
// first defaults, then extra kernel args to allow extra kernel args to override defaults
2024-02-29 20:26:46 +05:30
if err := cmdline . AppendAll ( kernel . DefaultArgs ) ; err != nil {
2020-12-24 15:19:41 +03:00
return err
}
2020-12-10 17:10:06 +03:00
2023-07-27 12:50:06 +04:00
if opts . Board != constants . BoardNone {
2023-08-21 18:05:42 +04:00
// board 'rpi_4' was removed in Talos 1.5 in favor of `rpi_generic`
if opts . Board == "rpi_4" {
opts . Board = constants . BoardRPiGeneric
}
2023-07-27 12:50:06 +04:00
var b runtime . Board
2024-02-29 20:26:46 +05:30
b , err := board . NewBoard ( opts . Board )
2023-07-27 12:50:06 +04:00
if err != nil {
return err
}
cmdline . Append ( constants . KernelParamBoard , b . Name ( ) )
cmdline . SetAll ( b . KernelArgs ( ) . Strings ( ) )
}
2024-04-16 19:52:31 +04:00
if opts . OverlayInstaller != nil {
overlayOpts , getOptsErr := opts . OverlayInstaller . GetOptions ( opts . ExtraOptions )
if getOptsErr != nil {
return fmt . Errorf ( "failed to get overlay installer options: %w" , getOptsErr )
}
opts . OverlayName = overlayOpts . Name
cmdline . SetAll ( overlayOpts . KernelArgs )
}
2024-08-25 10:26:49 +05:30
// preserve console=ttyS0 if it was already present in cmdline for metal platform
existingCmdline := procfs . ProcCmdline ( )
if * existingCmdline . Get ( constants . KernelParamPlatform ) . First ( ) == constants . PlatformMetal && existingCmdline . Get ( "console" ) . Contains ( "ttyS0" ) {
if ! slices . Contains ( opts . ExtraKernelArgs , "console=ttyS0" ) {
cmdline . Append ( "console" , "ttyS0" )
}
}
2024-02-29 20:26:46 +05:30
if err := cmdline . AppendAll (
2022-07-05 10:01:12 +03:00
opts . ExtraKernelArgs ,
procfs . WithOverwriteArgs ( "console" ) ,
procfs . WithOverwriteArgs ( constants . KernelParamPlatform ) ,
2023-11-23 10:51:01 +05:30
procfs . WithDeleteNegatedArgs ( ) ,
2022-07-05 10:01:12 +03:00
) ; err != nil {
2020-04-23 21:12:44 -07:00
return err
}
2023-07-27 12:50:06 +04:00
i , err := NewInstaller ( ctx , cmdline , mode , opts )
2020-04-23 21:12:44 -07:00
if err != nil {
return err
}
2023-07-27 12:50:06 +04:00
if err = i . Install ( ctx , mode ) ; err != nil {
2020-04-23 21:12:44 -07:00
return err
}
2023-08-04 23:11:16 +04:00
i . options . Printf ( "installation of %s complete" , version . Tag )
2020-04-23 21:12:44 -07:00
return nil
}
2019-07-31 17:16:10 +00:00
// Installer represents the installer logic. It serves as the entrypoint to all
// installation methods.
type Installer struct {
2024-06-11 16:19:04 +04:00
cmdline * procfs . Cmdline
options * Options
2019-07-31 17:16:10 +00:00
}
// NewInstaller initializes and returns an Installer.
2023-07-27 12:50:06 +04:00
func NewInstaller ( ctx context . Context , cmdline * procfs . Cmdline , mode Mode , opts * Options ) ( i * Installer , err error ) {
2019-08-15 15:21:55 +00:00
i = & Installer {
2019-07-31 17:16:10 +00:00
cmdline : cmdline ,
2020-04-23 21:12:44 -07:00
options : opts ,
2019-07-31 17:16:10 +00:00
}
2023-07-27 12:50:06 +04:00
if i . options . Version == "" {
i . options . Version = version . Tag
}
2023-08-04 23:11:16 +04:00
if i . options . Printf == nil {
i . options . Printf = log . Printf
}
2024-06-11 16:19:04 +04:00
if mode == ModeUpgrade && i . options . Force {
i . options . Printf ( "system disk wipe on upgrade is not supported anymore, option ignored" )
2019-08-15 15:21:55 +00:00
}
2019-07-31 17:16:10 +00:00
2024-06-11 16:19:04 +04:00
if i . options . Zero && mode != ModeInstall {
i . options . Printf ( "zeroing of the disk is only supported for the initial installation, option ignored" )
2020-10-20 15:49:45 +03:00
}
2024-06-11 16:19:04 +04:00
i . options . BootAssets . FillDefaults ( opts . Arch )
2022-02-09 21:11:42 +01:00
2023-06-07 20:45:53 +05:30
return i , nil
2020-10-20 15:49:45 +03:00
}
2019-07-31 17:16:10 +00:00
// Install fetches the necessary data locations and copies or extracts
// to the target locations.
2020-03-10 07:52:10 -07:00
//
2021-03-12 02:17:28 +03:00
//nolint:gocyclo,cyclop
2023-07-27 12:50:06 +04:00
func ( i * Installer ) Install ( ctx context . Context , mode Mode ) ( err error ) {
2024-06-11 16:19:04 +04:00
// pre-flight checks, erratas
hostTalosVersion , err := readHostTalosVersion ( )
if err != nil {
return err
}
2022-11-24 21:45:08 +04:00
2023-07-27 12:50:06 +04:00
if mode == ModeUpgrade {
2024-06-11 16:19:04 +04:00
errataArm64ZBoot ( )
i . errataNetIfnames ( hostTalosVersion )
2023-05-29 23:00:13 +04:00
}
2023-07-27 12:50:06 +04:00
if err = i . runPreflightChecks ( mode ) ; err != nil {
2022-11-24 22:48:22 +04:00
return err
}
2024-06-11 16:19:04 +04:00
// prepare extensions if legacy machine.install.extensions is present
2022-01-20 20:53:28 +03:00
if err = i . installExtensions ( ) ; err != nil {
return err
}
2024-06-11 16:19:04 +04:00
// open and lock the blockdevice for the installation disk for the whole duration of the installer
bd , err := block . NewFromPath ( i . options . Disk , block . OpenForWrite ( ) )
if err != nil {
return fmt . Errorf ( "failed to open blockdevice %s: %w" , i . options . Disk , err )
2019-07-31 17:16:10 +00:00
}
2024-06-11 16:19:04 +04:00
defer bd . Close ( ) //nolint:errcheck
2021-02-16 22:50:18 +03:00
2024-06-11 16:19:04 +04:00
if err = bd . Lock ( true ) ; err != nil {
return fmt . Errorf ( "failed to lock blockdevice %s: %w" , i . options . Disk , err )
2023-06-14 22:35:33 +04:00
}
2024-06-11 16:19:04 +04:00
defer bd . Unlock ( ) //nolint:errcheck
2021-02-16 22:50:18 +03:00
2024-06-11 16:19:04 +04:00
var bootlder bootloader . Bootloader
2021-02-16 22:50:18 +03:00
2024-06-11 16:19:04 +04:00
// if running in install/image mode, just create new GPT partition table
// if running in upgrade mode, verify that install disk has correct GPT partition table and expected partitions
2021-02-16 22:50:18 +03:00
2024-06-11 16:19:04 +04:00
// probe the disk anyways
info , err := blkid . Probe ( bd . File ( ) , blkid . WithSkipLocking ( true ) )
if err != nil {
return fmt . Errorf ( "failed to probe blockdevice %s: %w" , i . options . Disk , err )
}
2021-02-16 22:50:18 +03:00
2024-06-11 16:19:04 +04:00
gptdev , err := gpt . DeviceFromBlockDevice ( bd )
if err != nil {
return fmt . Errorf ( "error getting GPT device: %w" , err )
}
2021-02-16 22:50:18 +03:00
2024-06-11 16:19:04 +04:00
switch mode {
case ModeImage :
// on image creation, we don't care about disk contents
bootlder = bootloader . New ( i . options . ImageSecureboot , i . options . Version )
case ModeInstall :
if ! i . options . Zero && ! i . options . Force {
// verify that the disk is either empty or has an empty GPT partition table, otherwise fail the install
switch {
case info . Name == "" :
// empty, ok
case info . Name == typeGPT && len ( info . Parts ) == 0 :
// GPT, no partitions, ok
default :
return fmt . Errorf ( "disk %s is not empty, skipping install, detected %q" , i . options . Disk , info . Name )
2021-02-16 22:50:18 +03:00
}
2024-06-11 16:19:04 +04:00
} else {
// zero the disk
if err = bd . FastWipe ( ) ; err != nil {
return fmt . Errorf ( "failed to zero blockdevice %s: %w" , i . options . Disk , err )
}
}
2021-02-16 22:50:18 +03:00
2024-06-11 16:19:04 +04:00
// on install, automatically detect the bootloader
bootlder = bootloader . NewAuto ( )
case ModeUpgrade :
// on upgrade, we don't touch the disk partitions, but we need to verify that the disk has the expected GPT partition table
if info . Name != typeGPT {
return fmt . Errorf ( "disk %s has an unexpected format %q" , i . options . Disk , info . Name )
2021-02-16 22:50:18 +03:00
}
2020-03-10 07:52:10 -07:00
}
2019-08-08 00:16:43 -05:00
2024-06-11 16:19:04 +04:00
if mode == ModeImage || mode == ModeInstall {
// create partitions and re-probe the device
info , err = i . createPartitions ( gptdev , mode , hostTalosVersion , bootlder )
if err != nil {
return fmt . Errorf ( "failed to create partitions: %w" , err )
}
2020-08-18 15:52:26 -07:00
}
2024-06-11 16:19:04 +04:00
if mode == ModeUpgrade {
// on upgrade, probe the bootloader
bootlder , err = bootloader . Probe ( i . options . Disk , bootloaderoptions . ProbeOptions {
// the disk is already locked
BlockProbeOptions : [ ] blkid . ProbeOption {
blkid . WithSkipLocking ( true ) ,
} ,
} )
if err != nil {
return fmt . Errorf ( "failed to probe bootloader on upgrade: %w" , err )
2020-08-18 15:52:26 -07:00
}
2024-06-11 16:19:04 +04:00
}
2020-08-18 15:52:26 -07:00
2019-07-31 17:16:10 +00:00
// Install the bootloader.
2024-06-11 16:19:04 +04:00
bootInstallResult , err := bootlder . Install ( bootloaderoptions . InstallOptions {
2023-08-31 22:21:41 +04:00
BootDisk : i . options . Disk ,
Arch : i . options . Arch ,
Cmdline : i . cmdline . String ( ) ,
Version : i . options . Version ,
ImageMode : mode . IsImage ( ) ,
MountPrefix : i . options . MountPrefix ,
BootAssets : i . options . BootAssets ,
Printf : i . options . Printf ,
2024-06-11 16:19:04 +04:00
BlkidInfo : info ,
2019-11-05 23:13:50 +00:00
2024-06-11 16:19:04 +04:00
ExtraInstallStep : func ( ) error {
if i . options . Board != constants . BoardNone {
var b runtime . Board
2020-11-25 18:00:02 +03:00
2024-06-11 16:19:04 +04:00
b , err = board . NewBoard ( i . options . Board )
if err != nil {
return err
}
2020-11-25 18:00:02 +03:00
2024-06-11 16:19:04 +04:00
i . options . Printf ( "installing U-Boot for %q" , b . Name ( ) )
if err = b . Install ( runtime . BoardInstallOptions {
InstallDisk : i . options . Disk ,
MountPrefix : i . options . MountPrefix ,
UBootPath : i . options . BootAssets . UBootPath ,
DTBPath : i . options . BootAssets . DTBPath ,
RPiFirmwarePath : i . options . BootAssets . RPiFirmwarePath ,
Printf : i . options . Printf ,
} ) ; err != nil {
return fmt . Errorf ( "failed to install for board %s: %w" , b . Name ( ) , err )
}
}
2020-11-25 18:00:02 +03:00
2024-06-11 16:19:04 +04:00
if i . options . OverlayInstaller != nil {
i . options . Printf ( "running overlay installer %q" , i . options . OverlayName )
if err = i . options . OverlayInstaller . Install ( overlay . InstallOptions [ overlay . ExtraOptions ] {
InstallDisk : i . options . Disk ,
MountPrefix : i . options . MountPrefix ,
ArtifactsPath : filepath . Join ( i . options . OverlayExtractedDir , constants . ImagerOverlayArtifactsPath ) ,
ExtraOptions : i . options . ExtraOptions ,
} ) ; err != nil {
return fmt . Errorf ( "failed to run overlay installer: %w" , err )
}
}
return nil
} ,
} )
if err != nil {
return fmt . Errorf ( "failed to install bootloader: %w" , err )
2024-02-29 20:26:46 +05:30
}
2023-07-27 12:50:06 +04:00
if mode == ModeUpgrade || len ( i . options . MetaValues . values ) > 0 {
2023-11-01 20:34:41 +04:00
var (
metaState * meta . Meta
metaPartitionName string
)
2020-10-16 17:00:40 +03:00
2024-06-11 16:19:04 +04:00
for _ , partition := range info . Parts {
if pointer . SafeDeref ( partition . PartitionLabel ) == constants . MetaPartitionLabel {
metaPartitionName = partitioning . DevName ( i . options . Disk , partition . PartitionIndex )
2023-11-01 20:34:41 +04:00
break
}
}
if metaPartitionName == "" {
2024-02-13 15:32:06 +03:00
return errors . New ( "failed to detect META partition" )
2023-11-01 20:34:41 +04:00
}
2024-06-11 16:19:04 +04:00
if metaState , err = meta . New ( ctx , nil , meta . WithPrinter ( i . options . Printf ) , meta . WithFixedPath ( metaPartitionName ) ) ; err != nil {
2024-03-20 16:05:18 +04:00
return fmt . Errorf ( "failed to open META: %w" , err )
2020-10-16 17:00:40 +03:00
}
2023-03-14 14:33:11 +04:00
var ok bool
2020-10-16 17:00:40 +03:00
2023-07-27 12:50:06 +04:00
if mode == ModeUpgrade {
2024-06-11 16:19:04 +04:00
if ok , err = metaState . SetTag ( ctx , meta . Upgrade , bootInstallResult . PreviousLabel ) ; ! ok || err != nil {
return fmt . Errorf ( "failed to set upgrade tag: %q" , bootInstallResult . PreviousLabel )
2023-03-27 14:16:06 +04:00
}
}
for _ , v := range i . options . MetaValues . values {
2024-06-11 16:19:04 +04:00
if ok , err = metaState . SetTag ( ctx , v . Key , v . Value ) ; ! ok || err != nil {
2023-03-27 14:16:06 +04:00
return fmt . Errorf ( "failed to set meta tag: %q -> %q" , v . Key , v . Value )
}
2020-10-16 17:00:40 +03:00
}
2023-03-14 14:33:11 +04:00
if err = metaState . Flush ( ) ; err != nil {
2024-03-20 16:05:18 +04:00
return fmt . Errorf ( "failed to flush META: %w" , err )
2020-10-16 17:00:40 +03:00
}
}
2020-03-10 07:52:10 -07:00
return nil
2019-07-31 17:16:10 +00:00
}
2022-11-24 22:48:22 +04:00
2024-06-11 16:19:04 +04:00
//nolint:gocyclo,cyclop
func ( i * Installer ) createPartitions ( gptdev gpt . Device , mode Mode , hostTalosVersion * compatibility . TalosVersion , bootlder bootloader . Bootloader ) ( * blkid . Info , error ) {
var partitionOptions * runtime . PartitionOptions
if i . options . Board != constants . BoardNone && ! quirks . New ( i . options . Version ) . SupportsOverlay ( ) {
var b runtime . Board
b , err := board . NewBoard ( i . options . Board )
if err != nil {
return nil , err
}
partitionOptions = b . PartitionOptions ( )
}
if i . options . OverlayInstaller != nil {
overlayOpts , getOptsErr := i . options . OverlayInstaller . GetOptions ( i . options . ExtraOptions )
if getOptsErr != nil {
return nil , fmt . Errorf ( "failed to get overlay installer options: %w" , getOptsErr )
}
if overlayOpts . PartitionOptions . Offset != 0 {
partitionOptions = & runtime . PartitionOptions {
PartitionsOffset : overlayOpts . PartitionOptions . Offset ,
}
}
}
var gptOptions [ ] gpt . Option
if partitionOptions != nil && partitionOptions . PartitionsOffset != 0 {
gptOptions = append ( gptOptions , gpt . WithSkipLBAs ( uint ( partitionOptions . PartitionsOffset ) ) )
}
if i . options . LegacyBIOSSupport {
gptOptions = append ( gptOptions , gpt . WithMarkPMBRBootable ( ) )
}
pt , err := gpt . New ( gptdev , gptOptions ... )
if err != nil {
return nil , fmt . Errorf ( "failed to initialize GPT: %w" , err )
}
// boot partitions
partitions := bootlder . RequiredPartitions ( )
// META partition
partitions = append ( partitions ,
partition . NewPartitionOptions ( constants . MetaPartitionLabel , false ) ,
)
legacyImage := mode == ModeImage && ! quirks . New ( i . options . Version ) . SkipDataPartitions ( )
// compatibility when installing on Talos < 1.8
if legacyImage || ( hostTalosVersion != nil && hostTalosVersion . PrecreateStatePartition ( ) ) {
partitions = append ( partitions ,
partition . NewPartitionOptions ( constants . StatePartitionLabel , false ) ,
)
}
if legacyImage {
partitions = append ( partitions ,
partition . NewPartitionOptions ( constants . EphemeralPartitionLabel , false ) ,
)
}
for _ , p := range partitions {
size := p . Size
if size == 0 {
size = pt . LargestContiguousAllocatable ( )
}
partitionTyp := uuid . MustParse ( p . PartitionType )
_ , _ , err = pt . AllocatePartition ( size , p . PartitionLabel , partitionTyp , p . PartitionOpts ... )
if err != nil {
return nil , fmt . Errorf ( "failed to allocate partition %s: %w" , p . PartitionLabel , err )
}
i . options . Printf ( "created %s (%s) size %d bytes" , p . PartitionLabel , p . PartitionType , size )
}
if err = pt . Write ( ) ; err != nil {
return nil , fmt . Errorf ( "failed to write GPT: %w" , err )
}
// now format all partitions
for idx , p := range partitions {
devName := partitioning . DevName ( i . options . Disk , uint ( idx + 1 ) )
if err = partition . Format ( devName , & p . FormatOptions , i . options . Printf ) ; err != nil {
return nil , fmt . Errorf ( "failed to format partition %s: %w" , devName , err )
}
}
info , err := blkid . ProbePath ( i . options . Disk , blkid . WithSkipLocking ( true ) )
if err != nil {
return nil , fmt . Errorf ( "failed to probe blockdevice %s: %w" , i . options . Disk , err )
}
if len ( info . Parts ) != len ( partitions ) {
return nil , fmt . Errorf ( "expected %d partitions, got %d" , len ( partitions ) , len ( info . Parts ) )
}
// this is weird, but sometimes blkid doesn't return the filesystem type for freshly formatted partitions
for idx , p := range partitions {
if p . FormatOptions . FileSystemType == partition . FilesystemTypeNone || p . FormatOptions . FileSystemType == partition . FilesystemTypeZeroes {
continue
}
info . Parts [ idx ] . Name = p . FormatOptions . FileSystemType
}
return info , nil
}
2023-07-27 12:50:06 +04:00
func ( i * Installer ) runPreflightChecks ( mode Mode ) error {
if mode != ModeUpgrade {
2022-11-24 22:48:22 +04:00
// pre-flight checks only apply to upgrades
return nil
}
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
checks , err := NewPreflightChecks ( ctx )
if err != nil {
return fmt . Errorf ( "error initializing pre-flight checks: %w" , err )
}
defer checks . Close ( ) //nolint:errcheck
return checks . Run ( ctx )
}
2024-01-31 22:17:20 +04:00
2024-02-29 20:26:46 +05:30
func overlayPresent ( ) bool {
_ , err := os . Stat ( constants . ImagerOverlayInstallerDefaultPath )
return err == nil
}
func getBoard ( ) string {
cmdline := procfs . ProcCmdline ( )
if cmdline == nil {
return constants . BoardNone
}
board := cmdline . Get ( constants . KernelParamBoard )
if board == nil {
return constants . BoardNone
}
return * board . First ( )
}