pipelines: make OSPipeline own the PartitionTable

The OSPipeline might need to know what disk layout it will be put onto, enforce this by making
the PartitionTable a property of the OSPipeline, and require child pipelines to query it when needed.
This commit is contained in:
Tom Gundersen 2022-06-26 18:56:17 +01:00
parent ae34513d18
commit f60092033b
3 changed files with 59 additions and 70 deletions

View file

@ -17,19 +17,14 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, rng)
if err != nil {
return nil, err
}
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatQCOW2, osbuild.QCOW2Options{Compat: "1.1"})
@ -44,19 +39,14 @@ func vhdPipelines(t *imageType, customizations *blueprint.Customizations, option
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, rng)
if err != nil {
return nil, err
}
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatVPC, nil)
@ -70,19 +60,14 @@ func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, optio
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, rng)
if err != nil {
return nil, err
}
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatVMDK, osbuild.VMDKOptions{Subformat: osbuild.VMDKSubformatStreamOptimized})
@ -96,19 +81,14 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations,
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, rng)
if err != nil {
return nil, err
}
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatQCOW2, nil)
@ -124,18 +104,13 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations,
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, rng)
if err != nil {
return nil, err
}
pipelines = append(pipelines, treePipeline.Serialize())
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
return pipelines, nil
}
@ -209,13 +184,21 @@ func osPipeline(buildPipeline *pipeline.BuildPipeline,
packages []rpmmd.PackageSpec,
c *blueprint.Customizations,
options distro.ImageOptions,
pt *disk.PartitionTable) (pipeline.OSPipeline, error) {
rng *rand.Rand) (pipeline.OSPipeline, error) {
imageConfig := t.getDefaultImageConfig()
pl := pipeline.NewOSPipeline(buildPipeline, t.rpmOstree, repos, packages, c.GetKernel().Name)
var pt *disk.PartitionTable
if t.bootable {
// TODO: should there always be a partition table?
var err error
pt, err = t.getPartitionTable(c.GetFilesystems(), options, rng)
if err != nil {
return pipeline.OSPipeline{}, err
}
}
pl.PartitionTable = pt
pl := pipeline.NewOSPipeline(buildPipeline, t.rpmOstree, repos, packages, pt, c.GetKernel().Name)
if t.Arch().Name() == distro.S390xArchName {
pl.BootLoader = pipeline.BOOTLOADER_ZIPL
@ -369,7 +352,7 @@ func bootISOPipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeli
return p
}
func liveImagePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.OSPipeline, outputFilename string, pt *disk.PartitionTable, arch *architecture) pipeline.LiveImgPipeline {
func liveImagePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.OSPipeline, outputFilename string, arch *architecture) pipeline.LiveImgPipeline {
p := pipeline.NewLiveImgPipeline(buildPipeline, treePipeline)
p.Filename = outputFilename
@ -381,8 +364,6 @@ func liveImagePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipe
p.GRUBLegacy = arch.legacy
}
p.PartitionTable = *pt
return p
}

View file

@ -1,17 +1,15 @@
package pipeline
import (
"github.com/osbuild/osbuild-composer/internal/disk"
"github.com/osbuild/osbuild-composer/internal/osbuild2"
)
type LiveImgPipeline struct {
Pipeline
PartitionTable disk.PartitionTable
BootLoader BootLoader
GRUBLegacy string
treePipeline *OSPipeline
Filename string
BootLoader BootLoader
GRUBLegacy string
treePipeline *OSPipeline
Filename string
}
func NewLiveImgPipeline(buildPipeline *BuildPipeline, treePipeline *OSPipeline) LiveImgPipeline {
@ -24,27 +22,32 @@ func NewLiveImgPipeline(buildPipeline *BuildPipeline, treePipeline *OSPipeline)
func (p LiveImgPipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
for _, stage := range osbuild2.GenImagePrepareStages(&p.PartitionTable, p.Filename, osbuild2.PTSfdisk) {
pt := p.treePipeline.PartitionTable()
if pt == nil {
panic("no partition table in live image")
}
for _, stage := range osbuild2.GenImagePrepareStages(pt, p.Filename, osbuild2.PTSfdisk) {
pipeline.AddStage(stage)
}
inputName := "root-tree"
copyOptions, copyDevices, copyMounts := osbuild2.GenCopyFSTreeOptions(inputName, p.treePipeline.Name(), p.Filename, &p.PartitionTable)
copyOptions, copyDevices, copyMounts := osbuild2.GenCopyFSTreeOptions(inputName, p.treePipeline.Name(), p.Filename, pt)
copyInputs := osbuild2.NewCopyStagePipelineTreeInputs(inputName, p.treePipeline.Name())
pipeline.AddStage(osbuild2.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
for _, stage := range osbuild2.GenImageFinishStages(&p.PartitionTable, p.Filename) {
for _, stage := range osbuild2.GenImageFinishStages(pt, p.Filename) {
pipeline.AddStage(stage)
}
switch p.BootLoader {
case BOOTLOADER_GRUB:
if p.GRUBLegacy != "" {
pipeline.AddStage(osbuild2.NewGrub2InstStage(osbuild2.NewGrub2InstStageOption(p.Filename, &p.PartitionTable, p.GRUBLegacy)))
pipeline.AddStage(osbuild2.NewGrub2InstStage(osbuild2.NewGrub2InstStageOption(p.Filename, pt, p.GRUBLegacy)))
}
case BOOTLOADER_ZIPL:
loopback := osbuild2.NewLoopbackDevice(&osbuild2.LoopbackDeviceOptions{Filename: p.Filename})
pipeline.AddStage(osbuild2.NewZiplInstStage(osbuild2.NewZiplInstStageOptions(p.treePipeline.KernelVer(), &p.PartitionTable), loopback, copyDevices, copyMounts))
pipeline.AddStage(osbuild2.NewZiplInstStage(osbuild2.NewZiplInstStageOptions(p.treePipeline.KernelVer(), pt), loopback, copyDevices, copyMounts))
}
return pipeline

View file

@ -22,7 +22,6 @@ type OSPipeline struct {
GRUBLegacy string
Vendor string
GPGKeyFiles []string
PartitionTable *disk.PartitionTable
Language string
Keyboard *string
Hostname string
@ -55,25 +54,27 @@ type OSPipeline struct {
PwQuality *osbuild2.PwqualityConfStageOptions
WAAgentConfig *osbuild2.WAAgentConfStageOptions
osTree bool
repos []rpmmd.RepoConfig
packageSpecs []rpmmd.PackageSpec
kernelVer string
osTree bool
repos []rpmmd.RepoConfig
packageSpecs []rpmmd.PackageSpec
partitionTable *disk.PartitionTable
kernelVer string
}
func NewOSPipeline(buildPipeline *BuildPipeline, osTree bool, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, kernelName string) OSPipeline {
func NewOSPipeline(buildPipeline *BuildPipeline, osTree bool, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, pt *disk.PartitionTable, kernelName string) OSPipeline {
name := "os"
if osTree {
name = "ostree-tree"
}
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packages, kernelName)
return OSPipeline{
Pipeline: New(name, buildPipeline, nil),
osTree: osTree,
repos: repos,
packageSpecs: packages,
kernelVer: kernelVer,
Hostname: "localhost.localdomain",
Pipeline: New(name, buildPipeline, nil),
osTree: osTree,
repos: repos,
packageSpecs: packages,
partitionTable: pt,
kernelVer: kernelVer,
Hostname: "localhost.localdomain",
}
}
@ -81,6 +82,10 @@ func (p OSPipeline) KernelVer() string {
return p.kernelVer
}
func (p OSPipeline) PartitionTable() *disk.PartitionTable {
return p.partitionTable
}
func (p OSPipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
@ -93,7 +98,7 @@ func (p OSPipeline) Serialize() osbuild2.Pipeline {
pipeline.AddStage(osbuild2.NewRPMStage(rpmOptions, osbuild2.NewRpmStageSourceFilesInputs(p.packageSpecs)))
// If the /boot is on a separate partition, the prefix for the BLS stage must be ""
if p.PartitionTable == nil || p.PartitionTable.FindMountable("/boot") == nil {
if p.PartitionTable() == nil || p.PartitionTable().FindMountable("/boot") == nil {
pipeline.AddStage(osbuild2.NewFixBLSStage(&osbuild2.FixBLSStageOptions{}))
} else {
pipeline.AddStage(osbuild2.NewFixBLSStage(&osbuild2.FixBLSStageOptions{Prefix: common.StringToPtr("")}))
@ -228,17 +233,17 @@ func (p OSPipeline) Serialize() osbuild2.Pipeline {
pipeline.AddStage(osbuild2.NewWAAgentConfStage(p.WAAgentConfig))
}
if p.PartitionTable != nil {
kernelOptions := osbuild2.GenImageKernelOptions(p.PartitionTable)
if pt := p.PartitionTable(); pt != nil {
kernelOptions := osbuild2.GenImageKernelOptions(p.PartitionTable())
kernelOptions = append(kernelOptions, p.KernelOptionsAppend...)
pipeline = prependKernelCmdlineStage(pipeline, strings.Join(kernelOptions, " "), p.PartitionTable)
pipeline = prependKernelCmdlineStage(pipeline, strings.Join(kernelOptions, " "), pt)
pipeline.AddStage(osbuild2.NewFSTabStage(osbuild2.NewFSTabStageOptions(p.PartitionTable)))
pipeline.AddStage(osbuild2.NewFSTabStage(osbuild2.NewFSTabStageOptions(pt)))
var bootloader *osbuild2.Stage
switch p.BootLoader {
case BOOTLOADER_GRUB:
options := osbuild2.NewGrub2StageOptionsUnified(p.PartitionTable, p.kernelVer, p.UEFI, p.GRUBLegacy, p.Vendor, false)
options := osbuild2.NewGrub2StageOptionsUnified(pt, p.kernelVer, p.UEFI, p.GRUBLegacy, p.Vendor, false)
if cfg := p.Grub2Config; cfg != nil {
// TODO: don't store Grub2Config in OSPipeline, making the overrides unnecessary
// grub2.Config.Default is owned and set by `NewGrub2StageOptionsUnified`