Skip to content

Commit

Permalink
chore: pause sequencer when talos installed and iso booted
Browse files Browse the repository at this point in the history
Pause sequencer till the boot timeout if talos is booted from ISO/PXE, but
an existing talos is installed to disk and
`talos.iso.boot.halt_if_installed` kernel argument is set.

Fixes: #9232

Signed-off-by: Noel Georgi <git@frezbo.dev>
  • Loading branch information
frezbo committed Aug 30, 2024
1 parent eade0a9 commit b6b16b3
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 0 deletions.
10 changes: 10 additions & 0 deletions hack/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ Starting with Talos 1.8, `console=ttyS0` kernel argument is removed from the met
This should fix slow boot or no console output issues on most bare metal hardware.
"""

[notes.kernel-args]
title = "`talos.halt_if_installed` kernel argument"
description = """\
Starting with Talos 1.8, ISO's generated from Boot Assets would have a new kernel argument `talos.halt_if_installed` which would pause the boot sequence until boot timeout if Talos is already installed on the disk.
ISO generated for pre 1.8 versions would not have this kernel argument.
This can be also explicitly enabled by setting `talos.halt_if_installed=1` in kernel argument.
"""


[make_deps]

[make_deps.tools]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ func (*Sequencer) Initialize(r runtime.Runtime) []runtime.Phase {
},
"wipeDisks",
ResetSystemDiskPartitions,
).AppendWithDeferredCheck(
func() bool {
haltIfInstalledStr := procfs.ProcCmdline().Get(constants.KernelParamHaltIfInstalled).First()
haltIfInstalled, _ := strconv.ParseBool(pointer.SafeDeref(haltIfInstalledStr)) //nolint:errcheck

return r.State().Machine().Installed() && haltIfInstalled
},
"haltIfInstalled",
haltIfInstalled,
).AppendWithDeferredCheck(
func() bool {
return r.State().Machine().Installed()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,25 @@ func UnmountEFIPartition(runtime.Sequence, any) (runtime.TaskExecutionFunc, stri
}, "unmountEFIPartition"
}

// haltIfInstalled halts the boot process if Talos is installed to disk but booted from ISO.
func haltIfInstalled(seq runtime.Sequence, _ any) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error {
ctx, cancel := context.WithTimeout(ctx, constants.BootTimeout)
defer cancel()

timer := time.NewTicker(30 * time.Second)
defer timer.Stop()

select {
case <-timer.C:
logger.Printf("Talos is already installed to disk but booted from another media and %s kernel parameter is set. Please reboot from the disk.", constants.KernelParamHaltIfInstalled)
case <-ctx.Done():
}

return nil
}, "haltIfInstalled"
}

// MountStatePartition mounts the system partition.
func MountStatePartition(seq runtime.Sequence, _ any) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/imager/imager.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ func (i *Imager) buildCmdline() error {
// platform kernel args
cmdline.Append(constants.KernelParamPlatform, p.Name())

if quirks.New(i.prof.Version).SupportsHaltIfInstalled() && i.prof.Output.Kind == profile.OutKindISO {
cmdline.Append(constants.KernelParamHaltIfInstalled, "1")
}

if quirks.New(i.prof.Version).SupportsMetalPlatformConsoleTTYS0() && i.prof.Platform == constants.PlatformMetal {
cmdline.Append("console", "ttyS0")
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/machinery/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ const (
// KernelParamNetIfnames is the kernel parameter name to control predictable network interface names.
KernelParamNetIfnames = "net.ifnames"

// KernelParamHaltIfInstalled is the kernel parameter name to control if Talos should pause if booting from boot media while Talos is already installed.
KernelParamHaltIfInstalled = "talos.halt_if_installed"

// BoardNone indicates that the install is not for a specific board.
BoardNone = "none"

Expand Down
13 changes: 13 additions & 0 deletions pkg/machinery/imager/quirks/quirks.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,16 @@ func (q Quirks) SupportsMetalPlatformConsoleTTYS0() bool {

return q.v.LT(maxVersionMetalPlatformConsoleTTYS0Dropped)
}

// minVersionSupportsHalfIfInstalled is the version that supports half if installed.
var minVersionSupportsHalfIfInstalled = semver.MustParse("1.8.0")

// SupportsHaltIfInstalled returns true if the Talos version supports half if installed.
func (q Quirks) SupportsHaltIfInstalled() bool {
// if the version doesn't parse, we assume it's latest Talos
if q.v == nil {
return true
}

return q.v.GTE(minVersionSupportsHalfIfInstalled)
}
5 changes: 5 additions & 0 deletions website/content/v1.8/reference/kernel.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,8 @@ Example:
```text
talos.device.settle_time=3m
```

#### `talos.halt_if_installed`

If set to `1`, Talos will pause the boot sequence and keeps printing a message until the boot timeout is reached if it detects that it is already installed.
This is useful if booting from ISO/PXE and you want to prevent the machine accidentally booting from the ISO/PXE after installation to the disk.

0 comments on commit b6b16b3

Please sign in to comment.