fix: overlay installer operations

1. Use overlay installer to build the `cmdline` when running in
   install/upgrade mode.

2. Pull down the overlay installer with the arch specific to the
   installer being generated, vs. the arch of the `imager`.

3. Print a message when running an overlay installer.

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
Andrey Smirnov 2024-04-16 19:52:31 +04:00
parent b1b63f658e
commit 0a785802ea
No known key found for this signature in database
GPG Key ID: FE042E3D4085A811
5 changed files with 64 additions and 24 deletions

View File

@ -124,6 +124,8 @@ var rootCmd = &cobra.Command{
},
ExtraOptions: extraOverlayOptions,
}
prof.Input.OverlayInstaller.ImageRef = cmdFlags.OverlayImage
}
prof.Input.SystemExtensions = xslices.Map(

View File

@ -48,16 +48,21 @@ func Execute() {
}
}
var options = &install.Options{}
var options = &install.Options{
Board: constants.BoardNone,
}
var bootloader bool
var (
bootloader bool
dummy string
)
func init() {
rootCmd.PersistentFlags().StringVar(&options.ConfigSource, "config", "", "The value of "+constants.KernelParamConfig)
rootCmd.PersistentFlags().StringVar(&options.Disk, "disk", "", "The path to the disk to install to")
rootCmd.PersistentFlags().StringVar(&options.Platform, "platform", "", "The value of "+constants.KernelParamPlatform)
rootCmd.PersistentFlags().StringVar(&options.Arch, "arch", runtime.GOARCH, "The target architecture")
rootCmd.PersistentFlags().StringVar(&options.Board, "board", constants.BoardNone, "Deprecated: no op")
rootCmd.PersistentFlags().StringVar(&dummy, "board", constants.BoardNone, "Deprecated: no op")
rootCmd.PersistentFlags().StringArrayVar(&options.ExtraKernelArgs, "extra-kernel-arg", []string{}, "Extra argument to pass to the kernel")
rootCmd.PersistentFlags().BoolVar(&bootloader, "bootloader", true, "Deprecated: no op")
rootCmd.PersistentFlags().BoolVar(&options.Upgrade, "upgrade", false, "Indicates that the install is being performed by an upgrade")

View File

@ -47,6 +47,7 @@ type Options struct {
LegacyBIOSSupport bool
MetaValues MetaValues
OverlayInstaller overlay.Installer[overlay.ExtraOptions]
OverlayName string
OverlayExtractedDir string
ExtraOptions overlay.ExtraOptions
@ -85,6 +86,25 @@ func Install(ctx context.Context, p runtime.Platform, mode Mode, opts *Options)
return fmt.Errorf("using standard installer image is not supported for board: %s, use an installer with overlay", b)
}
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
}
cmdline := procfs.NewCmdline("")
cmdline.Append(constants.KernelParamPlatform, p.Name())
@ -117,6 +137,17 @@ func Install(ctx context.Context, p runtime.Platform, mode Mode, opts *Options)
cmdline.SetAll(b.KernelArgs().Strings())
}
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)
}
if err := cmdline.AppendAll(
opts.ExtraKernelArgs,
procfs.WithOverwriteArgs("console"),
@ -126,25 +157,6 @@ func Install(ctx context.Context, p runtime.Platform, mode Mode, opts *Options)
return err
}
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
}
i, err := NewInstaller(ctx, cmdline, mode, opts)
if err != nil {
return err
@ -338,6 +350,8 @@ func (i *Installer) Install(ctx context.Context, mode Mode) (err error) {
}
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,

View File

@ -411,6 +411,21 @@ func (i *Imager) outInstaller(ctx context.Context, path string, report *reporter
}
if i.overlayInstaller != nil {
tempOverlayPath := filepath.Join(i.tempDir, "overlay-installer", constants.ImagerOverlayBasePath)
if err := os.MkdirAll(tempOverlayPath, 0o755); err != nil {
return fmt.Errorf("failed to create overlay directory: %w", err)
}
if err := i.prof.Input.OverlayInstaller.Extract(
ctx,
tempOverlayPath,
i.prof.Arch,
progressPrintf(report, reporter.Update{Message: "pulling overlay for installer...", Status: reporter.StatusRunning}),
); err != nil {
return err
}
extraOpts, internalErr := yaml.Marshal(i.prof.Overlay.ExtraOptions)
if internalErr != nil {
return fmt.Errorf("failed to marshal extra options: %w", internalErr)
@ -430,11 +445,11 @@ func (i *Imager) outInstaller(ctx context.Context, path string, report *reporter
mode os.FileMode
}{
{
sourcePath: filepath.Join(i.tempDir, constants.ImagerOverlayArtifactsPath),
sourcePath: filepath.Join(i.tempDir, "overlay-installer", constants.ImagerOverlayArtifactsPath),
imagePath: strings.TrimLeft(constants.ImagerOverlayArtifactsPath, "/"),
},
{
sourcePath: filepath.Join(i.tempDir, constants.ImagerOverlayInstallersPath, i.prof.Overlay.Name),
sourcePath: filepath.Join(i.tempDir, "overlay-installer", constants.ImagerOverlayInstallersPath, i.prof.Overlay.Name),
imagePath: strings.TrimLeft(constants.ImagerOverlayInstallerDefaultPath, "/"),
mode: 0o755,
},

View File

@ -54,6 +54,10 @@ type Input struct {
RPiFirmware FileAsset `yaml:"rpiFirmware,omitempty"`
// Base installer image to mutate.
BaseInstaller ContainerAsset `yaml:"baseInstaller,omitempty"`
// OverlayInstaller is an overlay image to inject into the installer.
//
// OverlayInstaller architecture should match the output installer architecture.
OverlayInstaller ContainerAsset `yaml:"overlayInstaller,omitempty"`
// SecureBoot is a section with secureboot keys, only for SecureBoot enabled builds.
SecureBoot *SecureBootAssets `yaml:"secureboot,omitempty"`
// SystemExtensions is a list of system extensions to install.