Andrey Smirnov 1df841bb54
refactor: change the interface of META
Use a global instance, handle loading/saving META in global context.

Deprecate legacy syslinux ADV, provide an easier interface for
consumers.

Expose META as resources.

Fix the bootloader revert process (it was completely broken for quite a
while :sad:).

This is a first step which mostly does preparation work, real changes
will come in the next PRs:

* add APIs to write to META
* consume META keys for platform network config for `metal`
* custom key for URL `${code}`

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
2023-03-15 15:43:16 +04:00

115 lines
2.3 KiB
Go

// 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 main
import (
"context"
"log"
"os"
"github.com/siderolabs/go-blockdevice/blockdevice/probe"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub"
"github.com/siderolabs/talos/internal/pkg/meta"
"github.com/siderolabs/talos/internal/pkg/mount"
"github.com/siderolabs/talos/pkg/machinery/constants"
)
func revertBootloader() {
if err := revertBootloadInternal(); err != nil {
log.Printf("failed to revert bootloader: %s", err)
}
}
//nolint:gocyclo
func revertBootloadInternal() error {
metaState, err := meta.New(context.Background(), nil)
if err != nil {
if os.IsNotExist(err) {
// no META, no way to revert
return nil
}
return err
}
label, ok := metaState.ReadTag(meta.Upgrade)
if !ok {
return nil
}
if label == "" {
if _, err = metaState.DeleteTag(context.Background(), meta.Upgrade); err != nil {
return err
}
return metaState.Flush()
}
log.Printf("reverting failed upgrade, switching to %q", label)
// attempt to mount BOOT partition directly without using other code paths, as they rely on Runtime
dev, err := probe.GetDevWithPartitionName(constants.BootPartitionLabel)
if os.IsNotExist(err) {
// no BOOT partition???
return nil
}
if err != nil {
return err
}
defer dev.Close() //nolint:errcheck
mp, err := mount.SystemMountPointForLabel(dev.BlockDevice, constants.BootPartitionLabel)
if err != nil {
return err
}
if mp == nil {
return nil
}
alreadyMounted, err := mp.IsMounted()
if err != nil {
return err
}
if !alreadyMounted {
if err = mp.Mount(); err != nil {
return err
}
defer mp.Unmount() //nolint:errcheck
}
conf, err := grub.Read(grub.ConfigPath)
if err != nil {
return err
}
if conf == nil {
return nil
}
bootEntry, err := grub.ParseBootLabel(label)
if err != nil {
return err
}
if conf.Default != bootEntry {
conf.Default, conf.Fallback = bootEntry, conf.Default
if err = conf.Write(grub.ConfigPath); err != nil {
return err
}
}
if _, err = metaState.DeleteTag(context.Background(), meta.Upgrade); err != nil {
return err
}
return metaState.Flush()
}