osbuild2: deduplicate grub2StageOptions() and grub2InstStageOptions()

Use single NewGrub2StageOptions() and NewGrub2InstStageOptions()
functions from osbuild2 instead of implementing them in distros.

A small option flip is required outside the function for RHEL 8.5 and
RHEL 8.6 to maintain the old behaviour.

Co-Authored-By: Christian Kellner <christian@kellner.me>
This commit is contained in:
Christian Kellner 2022-02-21 12:35:02 +01:00 committed by Tom Gundersen
parent adfed6e0d7
commit 153f9b46fd
10 changed files with 147 additions and 307 deletions

View file

@ -1271,16 +1271,23 @@ func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, ker
uefi := t.supportsUEFI()
legacy := t.arch.legacy
options := grub2StageOptions(partitionTable.RootFilesystem(), partitionTable.BootFilesystem(), kernelOptions, kernel, kernelVer, uefi, legacy, install)
options := osbuild.NewGrub2StageOptions(&partitionTable, kernelOptions, kernel, kernelVer, uefi, legacy, "redhat", install)
options.Greenboot = greenboot
// before unifying the org.osbuild.grub2 stage option generator, we didn't
// set the following for RHEL 8.5, so we need to revert here to maintain
// the old behaviour
if uefi {
options.UEFI.Unified = false
}
return osbuild.NewGRUB2Stage(options)
}
func bootloaderInstStage(filename string, pt *disk.PartitionTable, arch *architecture, kernelVer string, devices *osbuild.Devices, mounts *osbuild.Mounts, disk *osbuild.Device) *osbuild.Stage {
platform := arch.legacy
if platform != "" {
return osbuild.NewGrub2InstStage(grub2InstStageOptions(filename, pt, platform))
return osbuild.NewGrub2InstStage(osbuild.NewGrub2InstStageOption(filename, pt, platform))
}
if arch.name == distro.S390xArchName {

View file

@ -5,8 +5,6 @@ import (
"os"
"path/filepath"
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/crypt"
@ -329,44 +327,6 @@ func xorrisofsStageOptions(filename string, arch string, isolinux bool) *osbuild
return options
}
func grub2StageOptions(rootFs *disk.Filesystem, bootFs *disk.Filesystem, kernelOptions string,
kernel *blueprint.KernelCustomization, kernelVer string, uefi bool, legacy string, install bool) *osbuild.GRUB2StageOptions {
if rootFs == nil {
panic("root filesystem must be defined for grub2 stage, this is a programming error")
}
stageOptions := osbuild.GRUB2StageOptions{
RootFilesystemUUID: uuid.MustParse(rootFs.UUID),
KernelOptions: kernelOptions,
Legacy: legacy,
}
if bootFs != nil {
bootFsUUID := uuid.MustParse(bootFs.UUID)
stageOptions.BootFilesystemUUID = &bootFsUUID
}
if uefi {
stageOptions.UEFI = &osbuild.GRUB2UEFI{
Vendor: "redhat",
Install: install,
}
}
if !uefi {
stageOptions.Legacy = legacy
}
if kernel != nil {
if kernel.Append != "" {
stageOptions.KernelOptions += " " + kernel.Append
}
stageOptions.SavedEntry = "ffffffffffffffffffffffffffffffff-" + kernelVer
}
return &stageOptions
}
// sfdiskStageOptions creates the options and devices properties for an
// org.osbuild.sfdisk stage based on a partition table description
func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
@ -389,38 +349,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {
panic("failed to find boot or root partition for grub2.inst stage")
}
bootPart := pt.Partitions[bootPartIndex]
prefixPath := "/boot/grub2"
if bootPart.Payload.Mountpoint == "/boot" {
prefixPath = "/grub2"
}
core := osbuild.CoreMkImage{
Type: "mkimage",
PartLabel: pt.Type,
Filesystem: pt.Partitions[bootPartIndex].Payload.Type,
}
prefix := osbuild.PrefixPartition{
Type: "partition",
PartLabel: pt.Type,
Number: uint(bootPartIndex),
Path: prefixPath,
}
return &osbuild.Grub2InstStageOptions{
Filename: filename,
Platform: platform,
Location: pt.BytesToSectors(pt.Partitions[0].Start),
Core: core,
Prefix: prefix,
}
}
func ziplInstStageOptions(kernel string, pt *disk.PartitionTable) *osbuild.ZiplInstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -995,16 +995,23 @@ func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, ker
uefi := t.supportsUEFI()
legacy := t.arch.legacy
options := grub2StageOptions(partitionTable.RootFilesystem(), partitionTable.BootFilesystem(), kernelOptions, kernel, kernelVer, uefi, legacy, t.arch.distro.vendor, install)
options := osbuild.NewGrub2StageOptions(&partitionTable, kernelOptions, kernel, kernelVer, uefi, legacy, t.arch.distro.vendor, install)
options.Greenboot = greenboot
// before unifying the org.osbuild.grub2 stage option generator, we didn't
// set the following for RHEL 8.5, so we need to revert here to maintain
// the old behaviour
if uefi {
options.UEFI.Unified = false
}
return osbuild.NewGRUB2Stage(options)
}
func bootloaderInstStage(filename string, pt *disk.PartitionTable, arch *architecture, kernelVer string, devices *osbuild.Devices, mounts *osbuild.Mounts, disk *osbuild.Device) *osbuild.Stage {
platform := arch.legacy
if platform != "" {
return osbuild.NewGrub2InstStage(grub2InstStageOptions(filename, pt, platform))
return osbuild.NewGrub2InstStage(osbuild.NewGrub2InstStageOption(filename, pt, platform))
}
if arch.name == distro.S390xArchName {

View file

@ -5,8 +5,6 @@ import (
"os"
"path/filepath"
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/crypt"
@ -363,51 +361,6 @@ func xorrisofsStageOptions(filename, isolabel, arch string, isolinux bool) *osbu
return options
}
func grub2StageOptions(rootFs *disk.Filesystem,
bootFs *disk.Filesystem,
kernelOptions string,
kernel *blueprint.KernelCustomization,
kernelVer string,
uefi bool,
legacy string,
vendor string,
install bool) *osbuild.GRUB2StageOptions {
if rootFs == nil {
panic("root partition must be defined for grub2 stage, this is a programming error")
}
stageOptions := osbuild.GRUB2StageOptions{
RootFilesystemUUID: uuid.MustParse(rootFs.UUID),
KernelOptions: kernelOptions,
Legacy: legacy,
}
if bootFs != nil {
bootFsUUID := uuid.MustParse(bootFs.UUID)
stageOptions.BootFilesystemUUID = &bootFsUUID
}
if uefi {
stageOptions.UEFI = &osbuild.GRUB2UEFI{
Vendor: vendor,
Install: install,
}
}
if !uefi {
stageOptions.Legacy = legacy
}
if kernel != nil {
if kernel.Append != "" {
stageOptions.KernelOptions += " " + kernel.Append
}
stageOptions.SavedEntry = "ffffffffffffffffffffffffffffffff-" + kernelVer
}
return &stageOptions
}
// sfdiskStageOptions creates the options and devices properties for an
// org.osbuild.sfdisk stage based on a partition table description
func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
@ -430,38 +383,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {
panic("failed to find boot or root partition for grub2.inst stage")
}
bootPart := pt.Partitions[bootPartIndex]
prefixPath := "/boot/grub2"
if bootPart.Payload.Mountpoint == "/boot" {
prefixPath = "/grub2"
}
core := osbuild.CoreMkImage{
Type: "mkimage",
PartLabel: pt.Type,
Filesystem: pt.Partitions[bootPartIndex].Payload.Type,
}
prefix := osbuild.PrefixPartition{
Type: "partition",
PartLabel: pt.Type,
Number: uint(bootPartIndex),
Path: prefixPath,
}
return &osbuild.Grub2InstStageOptions{
Filename: filename,
Platform: platform,
Location: pt.BytesToSectors(pt.Partitions[0].Start),
Core: core,
Prefix: prefix,
}
}
func ziplInstStageOptions(kernel string, pt *disk.PartitionTable) *osbuild.ZiplInstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -991,7 +991,7 @@ func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, ker
uefi := t.supportsUEFI()
legacy := t.arch.legacy
options := grub2StageOptions(partitionTable.RootFilesystem(), partitionTable.BootFilesystem(), kernelOptions, kernel, kernelVer, uefi, legacy, t.arch.distro.vendor, install)
options := osbuild.NewGrub2StageOptions(&partitionTable, kernelOptions, kernel, kernelVer, uefi, legacy, t.arch.distro.vendor, install)
options.Greenboot = greenboot
return osbuild.NewGRUB2Stage(options)
@ -1000,7 +1000,7 @@ func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, ker
func bootloaderInstStage(filename string, pt *disk.PartitionTable, arch *architecture, kernelVer string, devices *osbuild.Devices, mounts *osbuild.Mounts, disk *osbuild.Device) *osbuild.Stage {
platform := arch.legacy
if platform != "" {
return osbuild.NewGrub2InstStage(grub2InstStageOptions(filename, pt, platform))
return osbuild.NewGrub2InstStage(osbuild.NewGrub2InstStageOption(filename, pt, platform))
}
if arch.name == distro.S390xArchName {

View file

@ -5,8 +5,6 @@ import (
"os"
"path/filepath"
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/crypt"
@ -363,52 +361,6 @@ func xorrisofsStageOptions(filename, isolabel, arch string, isolinux bool) *osbu
return options
}
func grub2StageOptions(rootFs *disk.Filesystem,
bootFs *disk.Filesystem,
kernelOptions string,
kernel *blueprint.KernelCustomization,
kernelVer string,
uefi bool,
legacy string,
vendor string,
install bool) *osbuild.GRUB2StageOptions {
if rootFs == nil {
panic("root filesystem must be defined for grub2 stage, this is a programming error")
}
stageOptions := osbuild.GRUB2StageOptions{
RootFilesystemUUID: uuid.MustParse(rootFs.UUID),
KernelOptions: kernelOptions,
Legacy: legacy,
}
if bootFs != nil {
bootFsUUID := uuid.MustParse(bootFs.UUID)
stageOptions.BootFilesystemUUID = &bootFsUUID
}
if uefi {
stageOptions.UEFI = &osbuild.GRUB2UEFI{
Vendor: vendor,
Install: install,
Unified: legacy == "", // force unified grub scheme for pure efi systems
}
}
if !uefi {
stageOptions.Legacy = legacy
}
if kernel != nil {
if kernel.Append != "" {
stageOptions.KernelOptions += " " + kernel.Append
}
stageOptions.SavedEntry = "ffffffffffffffffffffffffffffffff-" + kernelVer
}
return &stageOptions
}
// sfdiskStageOptions creates the options and devices properties for an
// org.osbuild.sfdisk stage based on a partition table description
func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
@ -431,38 +383,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {
panic("failed to find boot or root partition for grub2.inst stage")
}
bootPart := pt.Partitions[bootPartIndex]
prefixPath := "/boot/grub2"
if bootPart.Payload.Mountpoint == "/boot" {
prefixPath = "/grub2"
}
core := osbuild.CoreMkImage{
Type: "mkimage",
PartLabel: pt.Type,
Filesystem: pt.Partitions[bootPartIndex].Payload.Type,
}
prefix := osbuild.PrefixPartition{
Type: "partition",
PartLabel: pt.Type,
Number: uint(bootPartIndex),
Path: prefixPath,
}
return &osbuild.Grub2InstStageOptions{
Filename: filename,
Platform: platform,
Location: pt.BytesToSectors(pt.Partitions[0].Start),
Core: core,
Prefix: prefix,
}
}
func ziplInstStageOptions(kernel string, pt *disk.PartitionTable) *osbuild.ZiplInstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -1081,13 +1081,13 @@ func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, ker
kernelOptions := t.kernelOptions
uefi := t.supportsUEFI()
legacy := t.arch.legacy
return osbuild.NewGRUB2Stage(grub2StageOptions(partitionTable.RootFilesystem(), partitionTable.BootFilesystem(), kernelOptions, kernel, kernelVer, uefi, legacy))
return osbuild.NewGRUB2Stage(osbuild.NewGrub2StageOptions(&partitionTable, kernelOptions, kernel, kernelVer, uefi, legacy, "redhat", false))
}
func bootloaderInstStage(filename string, pt *disk.PartitionTable, arch *architecture, kernelVer string, devices *osbuild.Devices, mounts *osbuild.Mounts, disk *osbuild.Device) *osbuild.Stage {
platform := arch.legacy
if platform != "" {
return osbuild.NewGrub2InstStage(grub2InstStageOptions(filename, pt, platform))
return osbuild.NewGrub2InstStage(osbuild.NewGrub2InstStageOption(filename, pt, platform))
}
if arch.name == distro.S390xArchName {

View file

@ -4,8 +4,6 @@ import (
"fmt"
"path/filepath"
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/crypt"
"github.com/osbuild/osbuild-composer/internal/disk"
@ -308,44 +306,6 @@ func xorrisofsStageOptions(filename string, arch string) *osbuild.XorrisofsStage
}
}
func grub2StageOptions(rootFs *disk.Filesystem, bootFs *disk.Filesystem, kernelOptions string,
kernel *blueprint.KernelCustomization, kernelVer string, uefi bool, legacy string) *osbuild.GRUB2StageOptions {
if rootFs == nil {
panic("root filesystem must be defined for grub2 stage, this is a programming error")
}
stageOptions := osbuild.GRUB2StageOptions{
RootFilesystemUUID: uuid.MustParse(rootFs.UUID),
KernelOptions: kernelOptions,
Legacy: legacy,
}
if bootFs != nil {
bootFsUUID := uuid.MustParse(bootFs.UUID)
stageOptions.BootFilesystemUUID = &bootFsUUID
}
if uefi {
stageOptions.UEFI = &osbuild.GRUB2UEFI{
Vendor: "redhat",
Unified: legacy == "", // force unified grub scheme for pure efi systems
}
}
if !uefi {
stageOptions.Legacy = legacy
}
if kernel != nil {
if kernel.Append != "" {
stageOptions.KernelOptions += " " + kernel.Append
}
stageOptions.SavedEntry = "ffffffffffffffffffffffffffffffff-" + kernelVer
}
return &stageOptions
}
// sfdiskStageOptions creates the options and devices properties for an
// org.osbuild.sfdisk stage based on a partition table description
func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
@ -368,33 +328,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {
panic("failed to find boot or root partition for grub2.inst stage")
}
core := osbuild.CoreMkImage{
Type: "mkimage",
PartLabel: pt.Type,
Filesystem: pt.Partitions[bootPartIndex].Payload.Type,
}
prefix := osbuild.PrefixPartition{
Type: "partition",
PartLabel: pt.Type,
Number: uint(bootPartIndex),
Path: "/boot/grub2",
}
return &osbuild.Grub2InstStageOptions{
Filename: filename,
Platform: platform,
Location: pt.BytesToSectors(pt.Partitions[0].Start),
Core: core,
Prefix: prefix,
}
}
func ziplInstStageOptions(kernel string, pt *disk.PartitionTable) *osbuild.ZiplInstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -3,6 +3,8 @@ package osbuild2
import (
"encoding/json"
"fmt"
"github.com/osbuild/osbuild-composer/internal/disk"
)
// Install the grub2 boot loader for non-UEFI systems or hybrid boot
@ -92,3 +94,58 @@ func (options Grub2InstStageOptions) MarshalJSON() ([]byte, error) {
return json.Marshal(g2options)
}
func NewGrub2InstStageOption(filename string, pt *disk.PartitionTable, platform string) *Grub2InstStageOptions {
bootIdx := -1
rootIdx := -1
for idx := range pt.Partitions {
// NOTE: we only support having /boot at the top level of the partition
// table (e.g., not in LUKS or LVM), so we don't need to descend into
// VolumeContainer types. If /boot is on the root partition, then the
// root partition needs to be at the top level.
partition := &pt.Partitions[idx]
if partition.Payload == nil {
continue
}
if partition.Payload.GetMountpoint() == "/boot" {
bootIdx = idx
} else if partition.Payload.GetMountpoint() == "/" {
rootIdx = idx
}
}
if bootIdx == -1 {
// if there's no boot partition, fall back to root
if rootIdx == -1 {
// no root either!?
panic("failed to find boot or root partition for grub2.inst stage")
}
bootIdx = rootIdx
}
bootPart := pt.Partitions[bootIdx]
bootPayload := bootPart.Payload
prefixPath := "/boot/grub2"
if bootPayload.GetMountpoint() == "/boot" {
prefixPath = "/grub2"
}
core := CoreMkImage{
Type: "mkimage",
PartLabel: pt.Type,
Filesystem: bootPayload.GetFSType(),
}
prefix := PrefixPartition{
Type: "partition",
PartLabel: pt.Type,
Number: uint(bootIdx),
Path: prefixPath,
}
return &Grub2InstStageOptions{
Filename: filename,
Platform: platform,
Location: pt.BytesToSectors(pt.Partitions[0].Start),
Core: core,
Prefix: prefix,
}
}

View file

@ -1,6 +1,10 @@
package osbuild2
import "github.com/google/uuid"
import (
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/disk"
)
// The GRUB2StageOptions describes the bootloader configuration.
//
@ -35,3 +39,66 @@ func NewGRUB2Stage(options *GRUB2StageOptions) *Stage {
Options: options,
}
}
func NewGrub2StageOptions(pt *disk.PartitionTable,
kernelOptions string,
kernel *blueprint.KernelCustomization,
kernelVer string,
uefi bool,
legacy string,
vendor string,
install bool) *GRUB2StageOptions {
var bootFs, rootFs disk.Mountable
for idx := range pt.Partitions {
// NOTE: we only support having /boot at the top level of the partition
// table (e.g., not in LUKS or LVM), so we don't need to descend into
// VolumeContainer types. If /boot is on the root partition, then the
// root partition needs to be at the top level.
partition := &pt.Partitions[idx]
if partition.Payload == nil {
continue
}
if partition.Payload.GetMountpoint() == "/boot" {
bootFs = partition.Payload
} else if partition.Payload.GetMountpoint() == "/" {
rootFs = partition.Payload
}
}
if rootFs == nil {
panic("root filesystem must be defined for grub2 stage, this is a programming error")
}
stageOptions := GRUB2StageOptions{
RootFilesystemUUID: uuid.MustParse(rootFs.GetFSSpec().UUID),
KernelOptions: kernelOptions,
Legacy: legacy,
}
if bootFs != nil {
bootFsUUID := uuid.MustParse(bootFs.GetFSSpec().UUID)
stageOptions.BootFilesystemUUID = &bootFsUUID
}
if uefi {
stageOptions.UEFI = &GRUB2UEFI{
Vendor: vendor,
Install: install,
Unified: legacy == "", // force unified grub scheme for pure efi systems
}
}
if !uefi {
stageOptions.Legacy = legacy
}
if kernel != nil {
if kernel.Append != "" {
stageOptions.KernelOptions += " " + kernel.Append
}
stageOptions.SavedEntry = "ffffffffffffffffffffffffffffffff-" + kernelVer
}
return &stageOptions
}