Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ignition in simplified-installer and raw-image #3130

Merged
merged 7 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/blueprint/customizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type IgnitionCustomization struct {

type EmbeddedIgnitionCustomization struct {
ProvisioningURL string `json:"url,omitempty" toml:"url,omitempty"`
Data64 string `json:"data,omitempty" toml:"data,omitempty"`
Config string `json:"config,omitempty" toml:"config,omitempty"`
}

type FirstBootIgnitionCustomization struct {
Expand Down Expand Up @@ -421,7 +421,7 @@ func (c *EmbeddedIgnitionCustomization) CheckEmbeddedIgnition() error {
if c == nil {
return nil
}
if c.Data64 != "" && c.ProvisioningURL != "" {
if c.Config != "" && c.ProvisioningURL != "" {
t := reflect.TypeOf(*c)
return &CustomizationError{fmt.Sprintf("'%s' and '%s' are not allowed at the same time", t.Field(0).Name, t.Field(1).Name)}
}
Expand Down
4 changes: 4 additions & 0 deletions internal/distro/rhel9/edge.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ func edgeCommitPackageSet(t *imageType) rpmmd.PackageSet {
ps = ps.Append(aarch64EdgeCommitPackageSet(t))
}

if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !common.VersionLessThan(t.arch.distro.osVersion, "9-stream") {
runcom marked this conversation as resolved.
Show resolved Hide resolved
ps.Include = append(ps.Include, "ignition", "ignition-edge", "ssh-key-dir")
}

runcom marked this conversation as resolved.
Show resolved Hide resolved
return ps

}
Expand Down
35 changes: 31 additions & 4 deletions internal/distro/rhel9/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math/rand"

"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/container"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/fdo"
Expand Down Expand Up @@ -210,6 +211,9 @@ func edgeCommitImage(workload workload.Workload,

img.Platform = t.platform
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], options, containers, customizations)
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || t.arch.distro.osVersion == "9-stream" {
img.OSCustomizations.EnabledServices = append(img.OSCustomizations.EnabledServices, "ignition-firstboot-complete.service", "coreos-ignition-write-issues.service")
}
img.Environment = t.environment
img.Workload = workload

Expand Down Expand Up @@ -243,6 +247,9 @@ func edgeContainerImage(workload workload.Workload,

img.Platform = t.platform
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], options, containers, customizations)
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || t.arch.distro.osVersion == "9-stream" {
img.OSCustomizations.EnabledServices = append(img.OSCustomizations.EnabledServices, "ignition-firstboot-complete.service", "coreos-ignition-write-issues.service")
}
img.ContainerLanguage = img.OSCustomizations.Language
img.Environment = t.environment
img.Workload = workload
Expand Down Expand Up @@ -348,6 +355,15 @@ func edgeRawImage(workload workload.Workload,
}
img.OSName = "redhat"

if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}

// 92+ only
if kopts := customizations.GetKernel(); kopts != nil && kopts.Append != "" {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, kopts.Append)
}

// TODO: move generation into LiveImage
pt, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
Expand Down Expand Up @@ -375,6 +391,7 @@ func edgeSimplifiedInstallerImage(workload workload.Workload,
Checksum: options.OSTree.FetchChecksum,
}
rawImg := image.NewOSTreeRawImage(commit)
rawImg.Ignition = true

rawImg.Users = users.UsersFromBP(customizations.GetUsers())
rawImg.Groups = users.GroupsFromBP(customizations.GetGroups())
Expand Down Expand Up @@ -404,6 +421,15 @@ func edgeSimplifiedInstallerImage(workload workload.Workload,

rawImg.Filename = t.Filename()

if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}

// 92+ only
if kopts := customizations.GetKernel(); kopts != nil && kopts.Append != "" {
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, kopts.Append)
}

img := image.NewOSTreeSimplifiedInstaller(rawImg, customizations.InstallationDevice)
img.ExtraBasePackages = packageSets[installerPkgsKey]
// img.Workload = workload
Expand All @@ -414,11 +440,12 @@ func edgeSimplifiedInstallerImage(workload workload.Workload,
}
// ignition configs from blueprint
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil {
if bpIgnition.FirstBoot != nil {
img.IgnitionFirstBoot = ignition.FirstbootOptionsFromBP(*bpIgnition.FirstBoot)
}
if bpIgnition.Embedded != nil {
img.IgnitionEmbedded = ignition.EmbeddedOptionsFromBP(*bpIgnition.Embedded)
var err error
img.IgnitionEmbedded, err = ignition.EmbeddedOptionsFromBP(*bpIgnition.Embedded)
if err != nil {
return nil, err
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/distro/rhel9/imagetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio
}

if t.name == "edge-simplified-installer" {
allowed := []string{"InstallationDevice", "FDO", "Ignition"}
allowed := []string{"InstallationDevice", "FDO", "Ignition", "Kernel"}
if err := customizations.CheckAllowed(allowed...); err != nil {
return fmt.Errorf("unsupported blueprint customizations found for boot ISO image type %q: (allowed: %s)", t.name, strings.Join(allowed, ", "))
}
Expand Down Expand Up @@ -388,7 +388,7 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio
return fmt.Errorf("edge raw images require specifying a URL from which to retrieve the OSTree commit")
}

if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.rpmOstree {
if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.rpmOstree && t.name != "edge-raw-image" && t.name != "edge-simplified-installer" {
return fmt.Errorf("kernel boot parameter customizations are not supported for ostree types")
}

Expand Down
21 changes: 16 additions & 5 deletions internal/ignition/ignition.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package ignition

import "github.com/osbuild/osbuild-composer/internal/blueprint"
import (
"encoding/base64"
"errors"

"github.com/osbuild/osbuild-composer/internal/blueprint"
)

type FirstBootOptions struct {
ProvisioningURL string
Expand All @@ -13,10 +18,16 @@ func FirstbootOptionsFromBP(bpIgnitionFirstboot blueprint.FirstBootIgnitionCusto

type EmbeddedOptions struct {
ProvisioningURL string
Data64 string
Config string
}

func EmbeddedOptionsFromBP(bpIgnitionEmbedded blueprint.EmbeddedIgnitionCustomization) *EmbeddedOptions {
ignition := EmbeddedOptions(bpIgnitionEmbedded)
return &ignition
func EmbeddedOptionsFromBP(bpIgnitionEmbedded blueprint.EmbeddedIgnitionCustomization) (*EmbeddedOptions, error) {
decodedConfig, err := base64.StdEncoding.DecodeString(bpIgnitionEmbedded.Config)
if err != nil {
return nil, errors.New("can't decode Ignition config")
}
return &EmbeddedOptions{
ProvisioningURL: bpIgnitionEmbedded.ProvisioningURL,
Config: string(decodedConfig),
}, nil
}
4 changes: 3 additions & 1 deletion internal/image/ostree_raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type OSTreeRawImage struct {
Locale string

Filename string

Ignition bool
}

func NewOSTreeRawImage(commit ostree.CommitSpec) *OSTreeRawImage {
Expand All @@ -46,7 +48,7 @@ func NewOSTreeRawImage(commit ostree.CommitSpec) *OSTreeRawImage {
}

func ostreeCompressedImagePipelines(img *OSTreeRawImage, m *manifest.Manifest, buildPipeline *manifest.Build) *manifest.XZ {
osPipeline := manifest.NewOSTreeDeployment(m, buildPipeline, img.Commit, img.OSName, img.Platform)
osPipeline := manifest.NewOSTreeDeployment(m, buildPipeline, img.Commit, img.OSName, img.Ignition, img.Platform)
osPipeline.PartitionTable = img.PartitionTable
osPipeline.Remote = img.Remote
osPipeline.KernelOptionsAppend = img.KernelOptionsAppend
Expand Down
5 changes: 0 additions & 5 deletions internal/image/ostree_simplified_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,6 @@ func (img *OSTreeSimplifiedInstaller) InstantiateManifest(m *manifest.Manifest,
}
}

// ignition firstboot options
if img.IgnitionFirstBoot != nil {
kernelOpts = append(kernelOpts, "coreos.inst.append ignition.config.url="+img.IgnitionFirstBoot.ProvisioningURL)
}

bootTreePipeline.KernelOpts = kernelOpts

rootfsPartitionTable := &disk.PartitionTable{
Expand Down
4 changes: 2 additions & 2 deletions internal/manifest/coi_iso_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ func (p *CoreOSISOTree) serialize() osbuild.Pipeline {
copyInput := ""
// These specific filenames in the root of the ISO are expected by
// coreos-installer-dracut during installation
if p.coiPipeline.Ignition.Data64 != "" {
if p.coiPipeline.Ignition.Config != "" {
filename = "ignition_config"
copyInput = p.coiPipeline.Ignition.Data64
copyInput = p.coiPipeline.Ignition.Config
} else {
filename = "ignition_url"
copyInput = p.coiPipeline.Ignition.ProvisioningURL
Expand Down
18 changes: 18 additions & 0 deletions internal/manifest/commit_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type OSTreeDeployment struct {
platform platform.Platform

PartitionTable *disk.PartitionTable

// Whether ignition is in use or not
ignition bool
}

// NewOSTreeDeployment creates a pipeline for an ostree deployment from a
Expand All @@ -45,13 +48,15 @@ func NewOSTreeDeployment(m *Manifest,
buildPipeline *Build,
commit ostree.CommitSpec,
osName string,
ignition bool,
platform platform.Platform) *OSTreeDeployment {

p := &OSTreeDeployment{
Base: NewBase(m, "image-tree", buildPipeline),
commit: commit,
osName: osName,
platform: platform,
ignition: ignition,
}
buildPipeline.addDependent(p)
m.addPipeline(p)
Expand Down Expand Up @@ -95,6 +100,14 @@ func (p *OSTreeDeployment) serialize() osbuild.Pipeline {
kernelOpts := osbuild.GenImageKernelOptions(p.PartitionTable)
kernelOpts = append(kernelOpts, p.KernelOptionsAppend...)

if p.ignition {
kernelOpts = append(kernelOpts,
"coreos.no_persist_ip", // users cannot add connections as we don't have a live iso, this prevents connections to bleed into the system from the ign initrd
"ignition.platform.id=metal",
"$ignition_firstboot",
)
}

pipeline.AddStage(osbuild.NewOSTreeDeployStage(
&osbuild.OSTreeDeployStageOptions{
OsName: p.osName,
Expand Down Expand Up @@ -170,6 +183,10 @@ func (p *OSTreeDeployment) serialize() osbuild.Pipeline {
pipeline.AddStage(grpStage)
}

if p.ignition {
pipeline.AddStage(osbuild.NewIgnitionStage(&osbuild.IgnitionStageOptions{}))
}

// if no root password is set, lock the root account
hasRoot := false
for _, user := range p.Users {
Expand Down Expand Up @@ -216,6 +233,7 @@ func (p *OSTreeDeployment) serialize() osbuild.Pipeline {
p.platform.GetBIOSPlatform(),
p.platform.GetUEFIVendor(), true)
grubOptions.Greenboot = true
grubOptions.Ignition = p.ignition
grubOptions.Config = &osbuild.GRUB2Config{
Default: "saved",
Timeout: 1,
Expand Down
4 changes: 2 additions & 2 deletions internal/manifest/coreos_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ func (p *CoreOSInstaller) getInline() []string {
}
// inline data for ignition embedded (url or data)
if p.Ignition != nil {
if p.Ignition.Data64 != "" {
inlineData = append(inlineData, p.Ignition.Data64)
if p.Ignition.Config != "" {
inlineData = append(inlineData, p.Ignition.Config)
} else {
inlineData = append(inlineData, p.Ignition.ProvisioningURL)
}
Expand Down
1 change: 1 addition & 0 deletions internal/osbuild/grub2_stage.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type GRUB2StageOptions struct {
Greenboot bool `json:"greenboot,omitempty"`
WriteCmdLine *bool `json:"write_cmdline,omitempty"`
Config *GRUB2Config `json:"config,omitempty"`
Ignition bool `json:"ignition,omitempty"`
}

type GRUB2UEFI struct {
Expand Down
12 changes: 12 additions & 0 deletions internal/osbuild/ignition_stage.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ import (
"fmt"
)

type IgnitionStageOptions struct {
}

func (IgnitionStageOptions) isStageOptions() {}

func NewIgnitionStage(options *IgnitionStageOptions) *Stage {
return &Stage{
Type: "org.osbuild.ignition",
Options: options,
}
}

type IgnitionStageInputInline struct {
InlineFile IgnitionStageInput `json:"inlinefile"`
}
Expand Down
Loading