osbuild2: add prefix parameter to the fix-bls stage

The `fix-bls` stage supports a `prefix` argument, which was not
supported in composer. Specifying this argument is necessary in case the
`/boot` mountpoint is on a separate partition.

Add the `prefix` argument to the `fix-bls` stage. Amend unit tests.

The RHEL-8.5 and RHEL-9.0 `aarch64` `ec2` and `ami` images use partitioning
with `/boot` on a separate partition. Due to this, the pipeline must specify
a non-default prefix to the `fix-bls` stage.

Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
Tomas Hozza 2021-08-11 10:16:55 +02:00 committed by Tomas Hozza
parent 7ac1d68fb6
commit 6edf4aad49
5 changed files with 55 additions and 27 deletions

View file

@ -160,13 +160,19 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations,
// any additional stages to the pipeline, but before the SELinuxStage, which must be always the last one.
func ec2BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string,
defaultTarget string, withRHUI bool) (*osbuild.Pipeline, error) {
defaultTarget string, withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
p := new(osbuild.Pipeline)
p.Name = "os"
p.Build = "name:build"
packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage())
// If the /boot is on a separate partition, the prefix for the BLS stage must be ""
if pt.BootPartition() == nil {
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
} else {
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{Prefix: common.StringToPtr("")}))
}
language, keyboard := c.GetPrimaryLocale()
if language != nil {
@ -358,9 +364,9 @@ func ec2BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
func ec2X86_64BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string,
defaultTarget string, withRHUI bool) (*osbuild.Pipeline, error) {
defaultTarget string, withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
treePipeline, err := ec2BaseTreePipeline(repos, packages, bpPackages, c, options, enabledServices, disabledServices, defaultTarget, withRHUI)
treePipeline, err := ec2BaseTreePipeline(repos, packages, bpPackages, c, options, enabledServices, disabledServices, defaultTarget, withRHUI, pt)
if err != nil {
return nil, err
}
@ -385,22 +391,23 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations,
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
partitionTable := ec2PartitionTable(options, t.arch, rng)
var treePipeline *osbuild.Pipeline
var err error
switch arch := t.arch.Name(); arch {
// rhel-ec2-x86_64, rhel-ha-ec2
case x86_64ArchName:
treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI)
treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, &partitionTable)
// rhel-ec2-aarch64
case aarch64ArchName:
treePipeline, err = ec2BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI)
treePipeline, err = ec2BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, &partitionTable)
default:
return nil, fmt.Errorf("ec2CommonPipelines: unsupported image architecture: %q", arch)
}
if err != nil {
return nil, err
}
partitionTable := ec2PartitionTable(options, t.arch, rng)
treePipeline.AddStage(osbuild.NewFSTabStage(partitionTable.FSTabStageOptionsV2()))
kernelVer := kernelVerStr(packageSetSpecs[blueprintPkgsKey], customizations.GetKernel().Name, t.Arch().Name())
treePipeline.AddStage(bootloaderConfigStage(t, partitionTable, customizations.GetKernel(), kernelVer))
@ -550,7 +557,7 @@ func osPipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackag
p.Build = "name:build"
packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage())
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
@ -631,7 +638,7 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage())
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))

View file

@ -158,13 +158,19 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations,
// any additional stages to the pipeline, but before the SELinuxStage, which must be always the last one.
func ec2BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string,
defaultTarget string, withRHUI bool) (*osbuild.Pipeline, error) {
defaultTarget string, withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
p := new(osbuild.Pipeline)
p.Name = "os"
p.Build = "name:build"
packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage())
// If the /boot is on a separate partition, the prefix for the BLS stage must be ""
if pt.BootPartition() == nil {
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
} else {
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{Prefix: common.StringToPtr("")}))
}
language, keyboard := c.GetPrimaryLocale()
if language != nil {
@ -356,9 +362,9 @@ func ec2BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
func ec2X86_64BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string,
defaultTarget string, withRHUI bool) (*osbuild.Pipeline, error) {
defaultTarget string, withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
treePipeline, err := ec2BaseTreePipeline(repos, packages, bpPackages, c, options, enabledServices, disabledServices, defaultTarget, withRHUI)
treePipeline, err := ec2BaseTreePipeline(repos, packages, bpPackages, c, options, enabledServices, disabledServices, defaultTarget, withRHUI, pt)
if err != nil {
return nil, err
}
@ -383,22 +389,23 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations,
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
partitionTable := ec2PartitionTable(options, t.arch, rng)
var treePipeline *osbuild.Pipeline
var err error
switch arch := t.arch.Name(); arch {
// rhel-ec2-x86_64, rhel-ha-ec2
case x86_64ArchName:
treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI)
treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, &partitionTable)
// rhel-ec2-aarch64
case aarch64ArchName:
treePipeline, err = ec2BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI)
treePipeline, err = ec2BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, &partitionTable)
default:
return nil, fmt.Errorf("ec2CommonPipelines: unsupported image architecture: %q", arch)
}
if err != nil {
return nil, err
}
partitionTable := ec2PartitionTable(options, t.arch, rng)
treePipeline = prependKernelCmdlineStage(treePipeline, t, &partitionTable)
treePipeline.AddStage(osbuild.NewFSTabStage(partitionTable.FSTabStageOptionsV2()))
kernelVer := kernelVerStr(packageSetSpecs[blueprintPkgsKey], customizations.GetKernel().Name, t.Arch().Name())
@ -549,7 +556,7 @@ func osPipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackag
p.Build = "name:build"
packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage())
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
@ -630,7 +637,7 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage())
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))

View file

@ -1,21 +1,23 @@
package osbuild2
// A FixBLSStageOptions struct is empty, as the stage takes no options.
// A FixBLSStageOptions struct
//
// The FixBLSStage fixes the paths in the Boot Loader Specification
// snippets installed into /boot. grub2's kernel install script will
// try to guess the correct path to the kernel and bootloader, and adjust
// the boot loader scripts accordingly. When run under OSBuild this does
// not work correctly, so this stage essentially reverts the "fixup".
// The paths in the Bootloader Specification are relative to the partition
// they are located on, i.e. `/boot/loader/...` if `/boot` is on the root
// file-system partition. If `/boot` is on a separate partition, the correct
// path would be `/loader/.../` The `prefix` can be used to adjust for that.
// By default it is `/boot`, i.e. assumes `/boot` is on the root file-system.
type FixBLSStageOptions struct {
// Prefix defaults to "/boot" if not provided
Prefix *string `json:"prefix,omitempty"`
}
func (FixBLSStageOptions) isStageOptions() {}
// NewFixBLSStage creates a new FixBLSStage.
func NewFixBLSStage() *Stage {
func NewFixBLSStage(options *FixBLSStageOptions) *Stage {
return &Stage{
Type: "org.osbuild.fix-bls",
Options: &FixBLSStageOptions{},
Options: options,
}
}

View file

@ -11,6 +11,6 @@ func TestNewFixBLSStage(t *testing.T) {
Type: "org.osbuild.fix-bls",
Options: &FixBLSStageOptions{},
}
actualStage := NewFixBLSStage()
actualStage := NewFixBLSStage(&FixBLSStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -189,6 +189,18 @@ func TestStage_UnmarshalJSON(t *testing.T) {
data: []byte(`{"type":"org.osbuild.fix-bls","options":{}}`),
},
},
{
name: "fix-bls-empty-prefix",
fields: fields{
Type: "org.osbuild.fix-bls",
Options: &FixBLSStageOptions{
Prefix: common.StringToPtr(""),
},
},
args: args{
data: []byte(`{"type":"org.osbuild.fix-bls","options":{"prefix":""}}`),
},
},
{
name: "fstab",
fields: fields{