Skip to content

Commit

Permalink
anaconda: introduce container-installer
Browse files Browse the repository at this point in the history
A new image type that will use Anaconda to install a container to a
filesystem unattended. This initial commit introduces the image without
actually making the install unattended, just a bootable ISO.
  • Loading branch information
supakeen committed Dec 20, 2023
1 parent 9bb70a1 commit 865f727
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 42 deletions.
149 changes: 149 additions & 0 deletions pkg/image/anaconda_container_installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package image

import (
"fmt"
"math/rand"

"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/artifact"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/rpmmd"
"github.com/osbuild/images/pkg/runner"
)

type AnacondaContainerInstaller struct {
Base
Platform platform.Platform
ExtraBasePackages rpmmd.PackageSet
Users []users.User
Groups []users.Group

SquashfsCompression string

ISOLabelTempl string
Product string
Variant string
OSName string
Ref string
OSVersion string
Release string

ContainerSource container.SourceSpec

Filename string

AdditionalDracutModules []string
AdditionalAnacondaModules []string
AdditionalDrivers []string
FIPS bool
}

func NewAnacondaContainerInstaller(container container.SourceSpec, ref string) *AnacondaContainerInstaller {
return &AnacondaContainerInstaller{
Base: NewBase("container-installer"),
ContainerSource: container,
Ref: ref,
}
}

func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos, &manifest.BuildOptions{ContainerBuildable: true})
buildPipeline.Checkpoint()

anacondaPipeline := manifest.NewAnacondaInstaller(m,
manifest.AnacondaInstallerTypePayload,
buildPipeline,
img.Platform,
repos,
"kernel",
img.Product,
img.OSVersion)

// This is only built with ELN for now
anacondaPipeline.UseRHELLoraxTemplates = true

anacondaPipeline.ExtraPackages = img.ExtraBasePackages.Include
anacondaPipeline.ExcludePackages = img.ExtraBasePackages.Exclude
anacondaPipeline.ExtraRepos = img.ExtraBasePackages.Repositories
anacondaPipeline.Users = img.Users
anacondaPipeline.Groups = img.Groups
anacondaPipeline.Variant = img.Variant
anacondaPipeline.Biosdevname = (img.Platform.GetArch() == arch.ARCH_X86_64)
anacondaPipeline.Checkpoint()
anacondaPipeline.AdditionalDracutModules = img.AdditionalDracutModules
anacondaPipeline.AdditionalAnacondaModules = img.AdditionalAnacondaModules
if img.FIPS {
anacondaPipeline.AdditionalAnacondaModules = append(
anacondaPipeline.AdditionalAnacondaModules,
"org.fedoraproject.Anaconda.Modules.Security",
)
}
anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers

rootfsPartitionTable := &disk.PartitionTable{
Size: 20 * common.MebiByte,
Partitions: []disk.Partition{
{
Start: 0,
Size: 20 * common.MebiByte,
Payload: &disk.Filesystem{
Type: "vfat",
Mountpoint: "/",
UUID: disk.NewVolIDFromRand(rng),
},
},
},
}

// TODO: replace isoLabelTmpl with more high-level properties
isoLabel := fmt.Sprintf(img.ISOLabelTempl, img.Platform.GetArch())

rootfsImagePipeline := manifest.NewISORootfsImg(buildPipeline, anacondaPipeline)
rootfsImagePipeline.Size = 4 * common.GibiByte

bootTreePipeline := manifest.NewEFIBootTree(m, buildPipeline, img.Product, img.OSVersion)
bootTreePipeline.Platform = img.Platform
bootTreePipeline.UEFIVendor = img.Platform.GetUEFIVendor()
bootTreePipeline.ISOLabel = isoLabel
bootTreePipeline.KernelOpts = []string{fmt.Sprintf("inst.stage2=hd:LABEL=%s", isoLabel), fmt.Sprintf("inst.ks=hd:LABEL=%s:%s", isoLabel, kspath)}
if img.FIPS {
bootTreePipeline.KernelOpts = append(bootTreePipeline.KernelOpts, "fips=1")
}

// enable ISOLinux on x86_64 only
isoLinuxEnabled := img.Platform.GetArch() == arch.ARCH_X86_64

isoTreePipeline := manifest.NewAnacondaInstallerISOTree(buildPipeline, anacondaPipeline, rootfsImagePipeline, bootTreePipeline)
isoTreePipeline.PartitionTable = rootfsPartitionTable
isoTreePipeline.Release = img.Release
isoTreePipeline.OSName = img.OSName
isoTreePipeline.Users = img.Users
isoTreePipeline.Groups = img.Groups

isoTreePipeline.SquashfsCompression = img.SquashfsCompression

// For ostree installers, always put the kickstart file in the root of the ISO
isoTreePipeline.KSPath = kspath
isoTreePipeline.PayloadPath = "/container"

isoTreePipeline.ContainerSource = &img.ContainerSource
isoTreePipeline.ISOLinux = isoLinuxEnabled
if img.FIPS {
isoTreePipeline.KernelOpts = append(isoTreePipeline.KernelOpts, "fips=1")
}

isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, isoLabel)
isoPipeline.SetFilename(img.Filename)
isoPipeline.ISOLinux = isoLinuxEnabled
artifact := isoPipeline.Export()

return artifact, nil
}
2 changes: 1 addition & 1 deletion pkg/image/anaconda_ostree_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.KSPath = kspath
isoTreePipeline.PayloadPath = "/ostree/repo"

isoTreePipeline.OSTreeCommitSource = &img.Commit
isoTreePipeline.CommitSource = &img.Commit
isoTreePipeline.ISOLinux = isoLinuxEnabled
if img.FIPS {
isoTreePipeline.KernelOpts = append(isoTreePipeline.KernelOpts, "fips=1")
Expand Down
27 changes: 25 additions & 2 deletions pkg/manifest/anaconda_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ type AnacondaInstaller struct {
AdditionalDrivers []string

Files []*fsnode.File

// Temporary
UseRHELLoraxTemplates bool
}

func NewAnacondaInstaller(m *Manifest,
Expand Down Expand Up @@ -135,8 +138,20 @@ func (p *AnacondaInstaller) getBuildPackages(Distro) []string {
packages := p.anacondaBootPackageSet()
packages = append(packages,
"rpm",
"lorax-templates-generic",
)
// XXX switch this one something
// - OSName -> no
// - Explicit
if p.UseRHELLoraxTemplates {
packages = append(packages,
"lorax-templates-rhel",
)
} else {
packages = append(packages,
"lorax-templates-generic",
)
}

return packages
}

Expand Down Expand Up @@ -269,9 +284,17 @@ func (p *AnacondaInstaller) serialize() osbuild.Pipeline {
}

if p.Type == AnacondaInstallerTypePayload {
var LoraxPath string

if p.UseRHELLoraxTemplates {
LoraxPath = "80-rhel/runtime-postinstall.tmpl"
} else {
LoraxPath = "99-generic/runtime-postinstall.tmpl"
}

pipeline.AddStage(osbuild.NewAnacondaStage(osbuild.NewAnacondaStageOptions(p.AdditionalAnacondaModules)))
pipeline.AddStage(osbuild.NewLoraxScriptStage(&osbuild.LoraxScriptStageOptions{
Path: "99-generic/runtime-postinstall.tmpl",
Path: LoraxPath,
BaseArch: p.platform.GetArch().String(),
}))
}
Expand Down
Loading

0 comments on commit 865f727

Please sign in to comment.