mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-06-03 01:44:53 +00:00
[uki] Lyfecycle (#148)
This commit is contained in:
parent
300cc9290a
commit
1b967cccd8
@ -30,6 +30,15 @@ var FirstBoot = []Interface{
|
||||
&GrubPostInstallOptions{},
|
||||
}
|
||||
|
||||
// AfterUkiInstall sets which Hooks to run after uki runs the install action
|
||||
var AfterUkiInstall = []Interface{}
|
||||
|
||||
// AfterUkiReset sets which Hooks to run after uki runs the install action
|
||||
var AfterUkiReset = []Interface{}
|
||||
|
||||
// AfterUkiUpgrade sets which Hooks to run after uki runs the install action
|
||||
var AfterUkiUpgrade = []Interface{}
|
||||
|
||||
func Run(c config.Config, spec v1.Spec, hooks ...Interface) error {
|
||||
for _, h := range hooks {
|
||||
if err := h.Run(c, spec); err != nil {
|
||||
|
107
main.go
107
main.go
@ -19,6 +19,7 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/webui"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/uki"
|
||||
"github.com/kairos-io/kairos-sdk/bundles"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/kairos-io/kairos-sdk/machine"
|
||||
@ -651,6 +652,112 @@ The validate command expects a configuration file as its only argument. Local fi
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "uki",
|
||||
Usage: "UKI subcommands",
|
||||
Description: "UKI subcommands",
|
||||
// we could set the flag --source at this level so we could have the flag for all subcommands but that translates into an ugly command
|
||||
// in which you need to put the source flag before the subcommand, which is a mess. Just bad UX.
|
||||
// command level: kairos-agent uki --source oci:whatever install
|
||||
// subcommand level: kairos-agent uki install --source oci:whatever
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "install",
|
||||
Usage: "Install to disk",
|
||||
UsageText: "install [--device DEVICE]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "source",
|
||||
Usage: "Source for install. Composed of `type:address`. Accepts `file:`,`dir:` or `oci:` for the type of source.\nFor example `file:/var/share/myimage.tar`, `dir:/tmp/extracted` or `oci:repo/image:tag`",
|
||||
Action: func(c *cli.Context, s string) error {
|
||||
return validateSource(s)
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "device",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Load the spec from the config
|
||||
installSpec, err := agentConfig.ReadUkiInstallSpecFromConfig(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.String("device") != "" {
|
||||
installSpec.Target = c.String("device")
|
||||
}
|
||||
|
||||
installAction := uki.NewInstallAction(config, installSpec)
|
||||
return installAction.Run()
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "upgrade",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "source",
|
||||
Usage: "Source for upgrade. Composed of `type:address`. Accepts `file:`,`dir:` or `oci:` for the type of source.\nFor example `file:/var/share/myimage.tar`, `dir:/tmp/extracted` or `oci:repo/image:tag`",
|
||||
Action: func(c *cli.Context, s string) error {
|
||||
return validateSource(s)
|
||||
},
|
||||
},
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs, collector.StrictValidation(c.Bool("strict-validation")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the spec from the config
|
||||
upgradeSpec, err := agentConfig.ReadUkiUpgradeFromConfig(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
upgradeAction := uki.NewUpgradeAction(config, upgradeSpec)
|
||||
return upgradeAction.Run()
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "reset",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "source",
|
||||
Usage: "Source for upgrade. Composed of `type:address`. Accepts `file:`,`dir:` or `oci:` for the type of source.\nFor example `file:/var/share/myimage.tar`, `dir:/tmp/extracted` or `oci:repo/image:tag`",
|
||||
Action: func(c *cli.Context, s string) error {
|
||||
return validateSource(s)
|
||||
},
|
||||
},
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs, collector.StrictValidation(c.Bool("strict-validation")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the spec from the config
|
||||
resetSpec, err := agentConfig.ReadUkiResetSpecFromConfig(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resetAction := uki.NewResetAction(config, resetSpec)
|
||||
return resetAction.Run()
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -478,6 +478,73 @@ func ReadInstallSpecFromConfig(c *Config) (*v1.InstallSpec, error) {
|
||||
return installSpec, nil
|
||||
}
|
||||
|
||||
// ReadUkiResetSpecFromConfig will return a proper v1.ResetUkiSpec based on an agent Config
|
||||
func ReadUkiResetSpecFromConfig(c *Config) (*v1.ResetUkiSpec, error) {
|
||||
sp, err := ReadSpecFromCloudConfig(c, "reset-uki")
|
||||
if err != nil {
|
||||
return &v1.ResetUkiSpec{}, err
|
||||
}
|
||||
resetSpec := sp.(*v1.ResetUkiSpec)
|
||||
return resetSpec, nil
|
||||
}
|
||||
|
||||
func NewUkiInstallSpec(cfg *Config) (*v1.InstallUkiSpec, error) {
|
||||
spec := &v1.InstallUkiSpec{
|
||||
Target: cfg.Install.Device,
|
||||
}
|
||||
|
||||
// Calculate the partitions afterwards so they use the image sizes for the final partition sizes
|
||||
spec.Partitions.EFI = &v1.Partition{
|
||||
FilesystemLabel: constants.EfiLabel,
|
||||
Size: constants.ImgSize, // TODO: Fix this and set proper size based on the source size
|
||||
Name: constants.EfiPartName,
|
||||
FS: constants.EfiFs,
|
||||
MountPoint: constants.EfiDir,
|
||||
Flags: []string{"esp"},
|
||||
}
|
||||
spec.Partitions.OEM = &v1.Partition{
|
||||
FilesystemLabel: constants.OEMLabel,
|
||||
Size: constants.OEMSize,
|
||||
Name: constants.OEMPartName,
|
||||
FS: constants.LinuxFs,
|
||||
MountPoint: constants.OEMDir,
|
||||
Flags: []string{},
|
||||
}
|
||||
spec.Partitions.Persistent = &v1.Partition{
|
||||
FilesystemLabel: constants.PersistentLabel,
|
||||
Size: constants.PersistentSize,
|
||||
Name: constants.PersistentPartName,
|
||||
FS: constants.LinuxFs,
|
||||
MountPoint: constants.PersistentDir,
|
||||
Flags: []string{},
|
||||
}
|
||||
|
||||
// TODO: Which key to use? install or install-uki?
|
||||
err := unmarshallFullSpec(cfg, "install", spec)
|
||||
|
||||
return spec, err
|
||||
}
|
||||
|
||||
// ReadUkiInstallSpecFromConfig will return a proper v1.InstallUkiSpec based on an agent Config
|
||||
func ReadUkiInstallSpecFromConfig(c *Config) (*v1.InstallUkiSpec, error) {
|
||||
sp, err := ReadSpecFromCloudConfig(c, "install-uki")
|
||||
if err != nil {
|
||||
return &v1.InstallUkiSpec{}, err
|
||||
}
|
||||
installSpec := sp.(*v1.InstallUkiSpec)
|
||||
return installSpec, nil
|
||||
}
|
||||
|
||||
// ReadUkiUpgradeFromConfig will return a proper v1.UpgradeUkiSpec based on an agent Config
|
||||
func ReadUkiUpgradeFromConfig(c *Config) (*v1.UpgradeUkiSpec, error) {
|
||||
sp, err := ReadSpecFromCloudConfig(c, "upgrade-uki")
|
||||
if err != nil {
|
||||
return &v1.UpgradeUkiSpec{}, err
|
||||
}
|
||||
upgradeSpec := sp.(*v1.UpgradeUkiSpec)
|
||||
return upgradeSpec, nil
|
||||
}
|
||||
|
||||
// GetSourceSize will try to gather the actual size of the source
|
||||
// Useful to create the exact size of images and by side effect the partition size
|
||||
// This helps adjust the size to be juuuuust right.
|
||||
@ -571,6 +638,14 @@ func ReadSpecFromCloudConfig(r *Config, spec string) (v1.Spec, error) {
|
||||
sp, err = NewUpgradeSpec(r)
|
||||
case "reset":
|
||||
sp, err = NewResetSpec(r)
|
||||
case "install-uki":
|
||||
sp, err = NewUkiInstallSpec(r)
|
||||
case "reset-uki":
|
||||
// TODO: Fill with proper defaults
|
||||
sp = &v1.ResetUkiSpec{}
|
||||
case "upgrade-uki":
|
||||
// TODO: Fill with proper defaults
|
||||
sp = &v1.UpgradeUkiSpec{}
|
||||
default:
|
||||
return nil, fmt.Errorf("spec not valid: %s", spec)
|
||||
}
|
||||
|
@ -106,6 +106,9 @@ const (
|
||||
SignedShim = "shim.efi"
|
||||
|
||||
Rsync = "rsync"
|
||||
|
||||
UkiSource = "/run/install/uki"
|
||||
UkiCdromSource = "/run/install/cdrom"
|
||||
)
|
||||
|
||||
func GetCloudInitPaths() []string {
|
||||
|
@ -50,27 +50,27 @@ func (e *Elemental) FormatPartition(part *v1.Partition, opts ...string) error {
|
||||
// PartitionAndFormatDevice creates a new empty partition table on target disk
|
||||
// and applies the configured disk layout by creating and formatting all
|
||||
// required partitions
|
||||
func (e *Elemental) PartitionAndFormatDevice(i *v1.InstallSpec) error {
|
||||
func (e *Elemental) PartitionAndFormatDevice(i v1.SharedInstallSpec) error {
|
||||
disk := partitioner.NewDisk(
|
||||
i.Target,
|
||||
i.GetTarget(),
|
||||
partitioner.WithRunner(e.config.Runner),
|
||||
partitioner.WithFS(e.config.Fs),
|
||||
partitioner.WithLogger(e.config.Logger),
|
||||
)
|
||||
|
||||
if !disk.Exists() {
|
||||
e.config.Logger.Errorf("Disk %s does not exist", i.Target)
|
||||
return fmt.Errorf("disk %s does not exist", i.Target)
|
||||
e.config.Logger.Errorf("Disk %s does not exist", i.GetTarget())
|
||||
return fmt.Errorf("disk %s does not exist", i.GetTarget())
|
||||
}
|
||||
|
||||
e.config.Logger.Infof("Partitioning device...")
|
||||
out, err := disk.NewPartitionTable(i.PartTable)
|
||||
out, err := disk.NewPartitionTable(i.GetPartTable())
|
||||
if err != nil {
|
||||
e.config.Logger.Errorf("Failed creating new partition table: %s", out)
|
||||
return err
|
||||
}
|
||||
|
||||
parts := i.Partitions.PartitionsByInstallOrder(i.ExtraPartitions)
|
||||
parts := i.GetPartitions().PartitionsByInstallOrder(i.GetExtraPartitions())
|
||||
return e.createPartitions(disk, parts)
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,14 @@ type Spec interface {
|
||||
ShouldShutdown() bool
|
||||
}
|
||||
|
||||
// SharedInstallSpec is the interface that Install specs need to implement
|
||||
type SharedInstallSpec interface {
|
||||
GetPartTable() string
|
||||
GetTarget() string
|
||||
GetPartitions() ElementalPartitions
|
||||
GetExtraPartitions() PartitionList
|
||||
}
|
||||
|
||||
// InstallSpec struct represents all the installation action details
|
||||
type InstallSpec struct {
|
||||
Target string `yaml:"device,omitempty" mapstructure:"device"`
|
||||
@ -106,8 +114,12 @@ func (i *InstallSpec) Sanitize() error {
|
||||
return i.Partitions.SetFirmwarePartitions(i.Firmware, i.PartTable)
|
||||
}
|
||||
|
||||
func (i *InstallSpec) ShouldReboot() bool { return i.Reboot }
|
||||
func (i *InstallSpec) ShouldShutdown() bool { return i.PowerOff }
|
||||
func (i *InstallSpec) ShouldReboot() bool { return i.Reboot }
|
||||
func (i *InstallSpec) ShouldShutdown() bool { return i.PowerOff }
|
||||
func (i *InstallSpec) GetTarget() string { return i.Target }
|
||||
func (i *InstallSpec) GetPartTable() string { return i.PartTable }
|
||||
func (i *InstallSpec) GetPartitions() ElementalPartitions { return i.Partitions }
|
||||
func (i *InstallSpec) GetExtraPartitions() PartitionList { return i.ExtraPartitions }
|
||||
|
||||
// ResetSpec struct represents all the reset action details
|
||||
type ResetSpec struct {
|
||||
@ -476,3 +488,50 @@ type DockerImageMeta struct {
|
||||
Digest string `yaml:"digest,omitempty"`
|
||||
Size int64 `yaml:"size,omitempty"`
|
||||
}
|
||||
|
||||
type InstallUkiSpec struct {
|
||||
Target string `yaml:"device,omitempty" mapstructure:"device"`
|
||||
Reboot bool `yaml:"reboot,omitempty" mapstructure:"reboot"`
|
||||
PowerOff bool `yaml:"poweroff,omitempty" mapstructure:"poweroff"`
|
||||
Partitions ElementalPartitions `yaml:"partitions,omitempty" mapstructure:"partitions"`
|
||||
ExtraPartitions PartitionList `yaml:"extra-partitions,omitempty" mapstructure:"extra-partitions"`
|
||||
CloudInit []string `yaml:"cloud-init,omitempty" mapstructure:"cloud-init"`
|
||||
}
|
||||
|
||||
func (i *InstallUkiSpec) Sanitize() error {
|
||||
var err error
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *InstallUkiSpec) ShouldReboot() bool { return i.Reboot }
|
||||
func (i *InstallUkiSpec) ShouldShutdown() bool { return i.PowerOff }
|
||||
func (i *InstallUkiSpec) GetTarget() string { return i.Target }
|
||||
func (i *InstallUkiSpec) GetPartTable() string { return "gpt" }
|
||||
func (i *InstallUkiSpec) GetPartitions() ElementalPartitions { return i.Partitions }
|
||||
func (i *InstallUkiSpec) GetExtraPartitions() PartitionList { return i.ExtraPartitions }
|
||||
|
||||
type UpgradeUkiSpec struct {
|
||||
Reboot bool `yaml:"reboot,omitempty" mapstructure:"reboot"`
|
||||
PowerOff bool `yaml:"poweroff,omitempty" mapstructure:"poweroff"`
|
||||
}
|
||||
|
||||
func (i *UpgradeUkiSpec) Sanitize() error {
|
||||
var err error
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *UpgradeUkiSpec) ShouldReboot() bool { return i.Reboot }
|
||||
func (i *UpgradeUkiSpec) ShouldShutdown() bool { return i.PowerOff }
|
||||
|
||||
type ResetUkiSpec struct {
|
||||
Reboot bool `yaml:"reboot,omitempty" mapstructure:"reboot"`
|
||||
PowerOff bool `yaml:"poweroff,omitempty" mapstructure:"poweroff"`
|
||||
}
|
||||
|
||||
func (i *ResetUkiSpec) Sanitize() error {
|
||||
var err error
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *ResetUkiSpec) ShouldReboot() bool { return i.Reboot }
|
||||
func (i *ResetUkiSpec) ShouldShutdown() bool { return i.PowerOff }
|
||||
|
147
pkg/uki/install.go
Normal file
147
pkg/uki/install.go
Normal file
@ -0,0 +1,147 @@
|
||||
package uki
|
||||
|
||||
import (
|
||||
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elemental"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type InstallAction struct {
|
||||
cfg *config.Config
|
||||
spec *v1.InstallUkiSpec
|
||||
}
|
||||
|
||||
func NewInstallAction(cfg *config.Config, spec *v1.InstallUkiSpec) *InstallAction {
|
||||
return &InstallAction{cfg: cfg, spec: spec}
|
||||
}
|
||||
|
||||
func (i *InstallAction) Run() (err error) {
|
||||
e := elemental.NewElemental(i.cfg)
|
||||
cleanup := utils.NewCleanStack()
|
||||
defer func() { err = cleanup.Cleanup(err) }()
|
||||
// Run pre-install stage
|
||||
_ = utils.RunStage(i.cfg, "kairos-uki-install.pre")
|
||||
_ = events.RunHookScript("/usr/bin/kairos-agent.uki.install.pre.hook")
|
||||
|
||||
// Get source (from spec?)
|
||||
// If source is empty then we need to find the media we booted from....to get the efi files...
|
||||
// cdrom is kind fo easy...
|
||||
// we set the label EFI_ISO_BOOT so we look for that and then mount the image inside...
|
||||
// TODO: Extract this to a different functions or something. Maybe PrepareUKISource or something
|
||||
_ = fsutils.MkdirAll(i.cfg.Fs, constants.UkiCdromSource, os.ModeDir|os.ModePerm)
|
||||
_ = fsutils.MkdirAll(i.cfg.Fs, constants.UkiSource, os.ModeDir|os.ModePerm)
|
||||
|
||||
cdRom := &v1.Partition{
|
||||
FilesystemLabel: "UKI_ISO_INSTALL", // TODO: Hardcoded on ISO creation
|
||||
FS: "iso9660",
|
||||
Path: "/dev/disk/by-label/UKI_ISO_INSTALL",
|
||||
MountPoint: constants.UkiCdromSource,
|
||||
}
|
||||
err = e.MountPartition(cdRom)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cleanup.Push(func() error {
|
||||
return e.UnmountPartition(cdRom)
|
||||
})
|
||||
|
||||
// TODO: hardcoded
|
||||
image := &v1.Image{
|
||||
File: "/run/install/cdrom/efiboot.img", // TODO: Hardcoded on ISO creation
|
||||
Label: "UKI_SOURCE", // Made up, only for logging
|
||||
MountPoint: constants.UkiSource,
|
||||
}
|
||||
|
||||
err = e.MountImage(image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cleanup.Push(func() error {
|
||||
return e.UnmountImage(image)
|
||||
})
|
||||
|
||||
// Create EFI partition (fat32), we already create the efi partition on normal efi install,we can reuse that?
|
||||
// Create COS_OEM/COS_PERSISTANT if set (optional)
|
||||
// I guess we need to set sensible default values here for sizes? oem -> 64Mb as usual but if no persistent then EFI max size?
|
||||
// if persistent then EFI = source size * 2 (or maybe 3 times! so we can upgrade!) and then persistent the rest of the disk?
|
||||
|
||||
// Deactivate any active volume on target
|
||||
err = e.DeactivateDevices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Partition device
|
||||
err = e.PartitionAndFormatDevice(i.spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = e.MountPartitions(i.spec.GetPartitions().PartitionsByMountPoint(false))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cleanup.Push(func() error {
|
||||
return e.UnmountPartitions(i.spec.GetPartitions().PartitionsByMountPoint(true))
|
||||
})
|
||||
|
||||
// Before install hook happens after partitioning but before the image OS is applied (this is for compatibility with normal install, so users can reuse their configs)
|
||||
err = Hook(i.cfg, constants.BeforeInstallHook)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Store cloud-config in TPM or copy it to COS_OEM?
|
||||
// Copy cloud-init if any
|
||||
err = e.CopyCloudConfig(i.spec.CloudInit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Create dir structure
|
||||
// - /EFI/Kairos/ -> Store our older efi images ?
|
||||
// - /EFI/BOOT/ -> Default fallback dir (efi search for bootaa64.efi or bootx64.efi if no entries in the boot manager)
|
||||
|
||||
err = fsutils.MkdirAll(i.cfg.Fs, filepath.Join(constants.EfiDir, "EFI", "BOOT"), constants.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy the efi file into the proper dir
|
||||
source := v1.NewDirSrc(constants.UkiSource)
|
||||
_, err = e.DumpSource(i.spec.Partitions.EFI.MountPoint, source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// after install hook happens after install (this is for compatibility with normal install, so users can reuse their configs)
|
||||
err = Hook(i.cfg, constants.AfterInstallHook)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Remove all boot manager entries?
|
||||
// Create boot manager entry
|
||||
// Set default entry to the one we just created
|
||||
// Probably copy efi utils, like the Mokmanager and even the shim or grub efi to help with troubleshooting?
|
||||
_ = utils.RunStage(i.cfg, "kairos-uki-install.after")
|
||||
_ = events.RunHookScript("/usr/bin/kairos-agent.uki.install.after.hook") //nolint:errcheck
|
||||
|
||||
return hook.Run(*i.cfg, i.spec, hook.AfterUkiInstall...)
|
||||
}
|
||||
|
||||
// Hook is RunStage wrapper that only adds logic to ignore errors
|
||||
// in case v1.Config.Strict is set to false
|
||||
func Hook(config *config.Config, hook string) error {
|
||||
config.Logger.Infof("Running %s hook", hook)
|
||||
err := utils.RunStage(config, hook)
|
||||
if !config.Strict {
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
}
|
35
pkg/uki/reset.go
Normal file
35
pkg/uki/reset.go
Normal file
@ -0,0 +1,35 @@
|
||||
package uki
|
||||
|
||||
import (
|
||||
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
elementalUtils "github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
)
|
||||
|
||||
type ResetAction struct {
|
||||
cfg *config.Config
|
||||
spec *v1.ResetUkiSpec
|
||||
}
|
||||
|
||||
func NewResetAction(cfg *config.Config, spec *v1.ResetUkiSpec) *ResetAction {
|
||||
return &ResetAction{cfg: cfg, spec: spec}
|
||||
}
|
||||
|
||||
func (i *ResetAction) Run() (err error) {
|
||||
// Run pre-install stage
|
||||
_ = elementalUtils.RunStage(i.cfg, "kairos-uki-reset.pre")
|
||||
_ = events.RunHookScript("/usr/bin/kairos-agent.uki.reset.pre.hook")
|
||||
|
||||
// Get source (from spec?)
|
||||
// Copy the efi file into the proper dir
|
||||
// Remove all boot manager entries?
|
||||
// Create boot manager entry
|
||||
// Set default entry to the one we just created
|
||||
|
||||
_ = elementalUtils.RunStage(i.cfg, "kairos-uki-reset.after")
|
||||
_ = events.RunHookScript("/usr/bin/kairos-agent.uki.reset.after.hook") //nolint:errcheck
|
||||
|
||||
return hook.Run(*i.cfg, i.spec, hook.AfterUkiReset...)
|
||||
}
|
35
pkg/uki/upgrade.go
Normal file
35
pkg/uki/upgrade.go
Normal file
@ -0,0 +1,35 @@
|
||||
package uki
|
||||
|
||||
import (
|
||||
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
elementalUtils "github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
)
|
||||
|
||||
type UpgradeAction struct {
|
||||
cfg *config.Config
|
||||
spec *v1.UpgradeUkiSpec
|
||||
}
|
||||
|
||||
func NewUpgradeAction(cfg *config.Config, spec *v1.UpgradeUkiSpec) *UpgradeAction {
|
||||
return &UpgradeAction{cfg: cfg, spec: spec}
|
||||
}
|
||||
|
||||
func (i *UpgradeAction) Run() (err error) {
|
||||
// Run pre-install stage
|
||||
_ = elementalUtils.RunStage(i.cfg, "kairos-uki-upgrade.pre")
|
||||
_ = events.RunHookScript("/usr/bin/kairos-agent.uki.upgrade.pre.hook")
|
||||
|
||||
// Get source (from spec?)
|
||||
// Copy the efi file into the proper dir
|
||||
// Remove all boot manager entries?
|
||||
// Create boot manager entry
|
||||
// Set default entry to the one we just created
|
||||
|
||||
_ = elementalUtils.RunStage(i.cfg, "kairos-uki-upgrade.after")
|
||||
_ = events.RunHookScript("/usr/bin/kairos-agent.uki.upgrade.after.hook") //nolint:errcheck
|
||||
|
||||
return hook.Run(*i.cfg, i.spec, hook.AfterUkiUpgrade...)
|
||||
}
|
Loading…
Reference in New Issue
Block a user