mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-06-03 01:44:53 +00:00
Run install off the same command (#196)
This commit is contained in:
parent
663801091d
commit
775756f4b6
@ -5,6 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/uki"
|
||||
internalutils "github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
@ -14,13 +16,10 @@ import (
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/sanity-io/litter"
|
||||
|
||||
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/cmd"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
"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"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/kairos-io/kairos-sdk/machine"
|
||||
@ -217,41 +216,27 @@ func RunInstall(c *config.Config) error {
|
||||
c.Install.Device = detectDevice()
|
||||
}
|
||||
|
||||
// Load the installation spec from the Config
|
||||
installSpec, err := config.ReadInstallSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
// UKI path. Check if we are on UKI AND if we are running off a cd, otherwise it makes no sense to run the install
|
||||
// From the installed system
|
||||
if internalutils.UkiBootMode() == internalutils.UkiRemovableMedia {
|
||||
return runInstallUki(c)
|
||||
} else { // Non-uki path
|
||||
return runInstall(c)
|
||||
}
|
||||
}
|
||||
|
||||
f, err := fsutils.TempFile(c.Fs, "", "kairos-install-config-xxx.yaml")
|
||||
if err != nil {
|
||||
c.Logger.Error("Error creating temporary file for install config: %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(f.Name())
|
||||
|
||||
ccstring, err := c.String()
|
||||
// runInstallUki runs the UKI path install
|
||||
func runInstallUki(c *config.Config) error {
|
||||
// Load the spec from the config
|
||||
installSpec, err := config.ReadUkiInstallSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(f.Name(), []byte(ccstring), os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Printf("could not write cloud init to %s: %s\n", f.Name(), err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: This should not be neccessary
|
||||
installSpec.NoFormat = c.Install.NoFormat
|
||||
|
||||
// Set our cloud-init to the file we just created
|
||||
installSpec.CloudInit = append(installSpec.CloudInit, f.Name())
|
||||
// Get the source of the installation if we are overriding it
|
||||
if c.Install.Image != "" {
|
||||
imgSource, err := v1.NewSrcFromURI(c.Install.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
installSpec.Active.Source = imgSource
|
||||
f, err := dumpCCStringToFile(c)
|
||||
if err == nil {
|
||||
installSpec.CloudInit = append(installSpec.CloudInit, f)
|
||||
}
|
||||
|
||||
// Check if values are correct
|
||||
@ -263,20 +248,59 @@ func RunInstall(c *config.Config) error {
|
||||
// Add user's cloud-config (to run user defined "before-install" stages)
|
||||
c.CloudInitPaths = append(c.CloudInitPaths, installSpec.CloudInit...)
|
||||
|
||||
// Run pre-install stage
|
||||
_ = elementalUtils.RunStage(c, "kairos-install.pre")
|
||||
events.RunHookScript("/usr/bin/kairos-agent.install.pre.hook") //nolint:errcheck
|
||||
// Create the action
|
||||
installAction := action.NewInstallAction(c, installSpec)
|
||||
// Run it
|
||||
if err := installAction.Run(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
_ = elementalUtils.RunStage(c, "kairos-install.after")
|
||||
events.RunHookScript("/usr/bin/kairos-agent.install.after.hook") //nolint:errcheck
|
||||
installAction := uki.NewInstallAction(c, installSpec)
|
||||
return installAction.Run()
|
||||
}
|
||||
|
||||
return hook.Run(*c, installSpec, hook.AfterInstall...)
|
||||
// runInstall runs the non-UKI path install
|
||||
func runInstall(c *config.Config) error {
|
||||
// Load the installation spec from the Config
|
||||
installSpec, err := config.ReadInstallSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: This should not be neccessary
|
||||
installSpec.NoFormat = c.Install.NoFormat
|
||||
|
||||
// Set our cloud-init to the file we just created
|
||||
f, err := dumpCCStringToFile(c)
|
||||
if err == nil {
|
||||
installSpec.CloudInit = append(installSpec.CloudInit, f)
|
||||
}
|
||||
|
||||
// Check if values are correct
|
||||
err = installSpec.Sanitize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add user's cloud-config (to run user defined "before-install" stages)
|
||||
c.CloudInitPaths = append(c.CloudInitPaths, installSpec.CloudInit...)
|
||||
|
||||
installAction := action.NewInstallAction(c, installSpec)
|
||||
return installAction.Run()
|
||||
}
|
||||
|
||||
// dumpCCStringToFile dumps the cloud-init string to a file and returns the path of the file
|
||||
func dumpCCStringToFile(c *config.Config) (string, error) {
|
||||
f, err := fsutils.TempFile(c.Fs, "", "kairos-install-config-xxx.yaml")
|
||||
if err != nil {
|
||||
c.Logger.Error("Error creating temporary file for install config: %s\n", err.Error())
|
||||
return "", err
|
||||
}
|
||||
defer os.RemoveAll(f.Name())
|
||||
|
||||
ccstring, err := c.String()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = os.WriteFile(f.Name(), []byte(ccstring), os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Printf("could not write cloud init to %s: %s\n", f.Name(), err.Error())
|
||||
return "", err
|
||||
}
|
||||
return f.Name(), nil
|
||||
}
|
||||
|
||||
func ensureDataSourceReady() {
|
||||
|
41
main.go
41
main.go
@ -711,47 +711,6 @@ The validate command expects a configuration file as its only argument. Local fi
|
||||
// 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",
|
||||
},
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
if c.String("device") == "" {
|
||||
return fmt.Errorf("on uki, --device flag is required")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
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{
|
||||
|
@ -18,7 +18,9 @@ package action
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
@ -123,6 +125,10 @@ func (i InstallAction) Run() (err error) {
|
||||
cleanup := utils.NewCleanStack()
|
||||
defer func() { err = cleanup.Cleanup(err) }()
|
||||
|
||||
// Run pre-install stage
|
||||
_ = utils.RunStage(i.cfg, "kairos-install.pre")
|
||||
events.RunHookScript("/usr/bin/kairos-agent.install.pre.hook") //nolint:errcheck
|
||||
|
||||
// Set installation sources from a downloaded ISO
|
||||
if i.spec.Iso != "" {
|
||||
tmpDir, err := e.GetIso(i.spec.Iso)
|
||||
@ -275,5 +281,8 @@ func (i InstallAction) Run() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
_ = utils.RunStage(i.cfg, "kairos-install.after")
|
||||
_ = events.RunHookScript("/usr/bin/kairos-agent.install.after.hook") //nolint:errcheck
|
||||
|
||||
return hook.Run(*i.cfg, i.spec, hook.AfterInstall...)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/kairos-io/kairos-sdk/state"
|
||||
"io"
|
||||
random "math/rand"
|
||||
"net/url"
|
||||
@ -498,3 +499,31 @@ func FindCommand(defaultPath string, options []string) string {
|
||||
// Otherwise return default
|
||||
return defaultPath
|
||||
}
|
||||
|
||||
// IsUki returns true if the system is running in UKI mode. Checks the cmdline as UKI artifacts have the rd.immucore.uki flag
|
||||
func IsUki() bool {
|
||||
cmdline, _ := os.ReadFile("/proc/cmdline")
|
||||
if strings.Contains(string(cmdline), "rd.immucore.uki") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
UkiHDD state.Boot = "uki_boot_mode"
|
||||
UkiRemovableMedia state.Boot = "uki_install_mode"
|
||||
)
|
||||
|
||||
// UkiBootMode will return where the system is running from, either HDD or RemovableMedia
|
||||
// HDD means we are booting from an already installed system
|
||||
// RemovableMedia means we are booting from a live media like a CD or USB
|
||||
func UkiBootMode() state.Boot {
|
||||
if IsUki() {
|
||||
_, err := os.Stat("/run/cos/uki_boot_mode")
|
||||
if err != nil {
|
||||
return UkiHDD
|
||||
}
|
||||
return UkiRemovableMedia
|
||||
}
|
||||
return state.Unknown
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user