Specifying the boot partition filesystem UUID in grub2 stage is required in case the `/boot` mountpoint is on a separate partition. This is the case of RHEL-8.5 and RHEL-9.0 `ami` and `ec2` images. Extend `disk.PartitionTable` with a new `BootPartition` method, which returns a pointer to partition with FS mountpoint `/boot` if there is such partition, or `nil` otherwise. Extend the RHEL-8.5 and RHEL-9.0 code creating options structure for grub2 osbuild stage to include the boot partition in case it has been provided. Signed-off-by: Tomas Hozza <thozza@redhat.com>
185 lines
4.8 KiB
Go
185 lines
4.8 KiB
Go
// Disk package contains abstract data-types to define disk-related entities.
|
|
//
|
|
// PartitionTable, Partition and Filesystem types are currently defined.
|
|
// All of them can be 1:1 converted to osbuild.QEMUAssemblerOptions.
|
|
package disk
|
|
|
|
import (
|
|
"sort"
|
|
|
|
osbuild "github.com/osbuild/osbuild-composer/internal/osbuild1"
|
|
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
|
)
|
|
|
|
type PartitionTable struct {
|
|
// Size of the disk.
|
|
Size uint64
|
|
UUID string
|
|
// Partition table type, e.g. dos, gpt.
|
|
Type string
|
|
Partitions []Partition
|
|
}
|
|
|
|
type Partition struct {
|
|
Start uint64
|
|
Size uint64
|
|
Type string
|
|
Bootable bool
|
|
// ID of the partition, dos doesn't use traditional UUIDs, therefore this
|
|
// is just a string.
|
|
UUID string
|
|
// If nil, the partition is raw; It doesn't contain a filesystem.
|
|
Filesystem *Filesystem
|
|
}
|
|
|
|
type Filesystem struct {
|
|
Type string
|
|
// ID of the filesystem, vfat doesn't use traditional UUIDs, therefore this
|
|
// is just a string.
|
|
UUID string
|
|
Label string
|
|
Mountpoint string
|
|
// The fourth field of fstab(5); fs_mntops
|
|
FSTabOptions string
|
|
// The fifth field of fstab(5); fs_freq
|
|
FSTabFreq uint64
|
|
// The sixth field of fstab(5); fs_passno
|
|
FSTabPassNo uint64
|
|
}
|
|
|
|
// Converts PartitionTable to osbuild.QEMUAssemblerOptions that encode
|
|
// the same partition table.
|
|
func (pt PartitionTable) QEMUAssemblerOptions() osbuild.QEMUAssemblerOptions {
|
|
var partitions []osbuild.QEMUPartition
|
|
for _, p := range pt.Partitions {
|
|
partitions = append(partitions, p.QEMUPartition())
|
|
}
|
|
|
|
return osbuild.QEMUAssemblerOptions{
|
|
Size: pt.Size,
|
|
PTUUID: pt.UUID,
|
|
PTType: pt.Type,
|
|
Partitions: partitions,
|
|
}
|
|
}
|
|
|
|
// Generates org.osbuild.fstab stage options from this partition table.
|
|
func (pt PartitionTable) FSTabStageOptions() *osbuild.FSTabStageOptions {
|
|
var options osbuild.FSTabStageOptions
|
|
for _, p := range pt.Partitions {
|
|
fs := p.Filesystem
|
|
if fs == nil {
|
|
continue
|
|
}
|
|
|
|
options.AddFilesystem(fs.UUID, fs.Type, fs.Mountpoint, fs.FSTabOptions, fs.FSTabFreq, fs.FSTabPassNo)
|
|
}
|
|
|
|
// sort the entries by PassNo to maintain backward compatibility
|
|
sort.Slice(options.FileSystems, func(i, j int) bool {
|
|
return options.FileSystems[i].PassNo < options.FileSystems[j].PassNo
|
|
})
|
|
|
|
return &options
|
|
}
|
|
|
|
// Generates org.osbuild.fstab stage options from this partition table.
|
|
func (pt PartitionTable) FSTabStageOptionsV2() *osbuild2.FSTabStageOptions {
|
|
var options osbuild2.FSTabStageOptions
|
|
for _, p := range pt.Partitions {
|
|
fs := p.Filesystem
|
|
if fs == nil {
|
|
continue
|
|
}
|
|
|
|
options.AddFilesystem(fs.UUID, fs.Type, fs.Mountpoint, fs.FSTabOptions, fs.FSTabFreq, fs.FSTabPassNo)
|
|
}
|
|
|
|
// sort the entries by PassNo to maintain backward compatibility
|
|
sort.Slice(options.FileSystems, func(i, j int) bool {
|
|
return options.FileSystems[i].PassNo < options.FileSystems[j].PassNo
|
|
})
|
|
|
|
return &options
|
|
}
|
|
|
|
// Returns the root partition (the partition whose filesystem has / as
|
|
// a mountpoint) of the partition table. Nil is returned if there's no such
|
|
// partition.
|
|
func (pt PartitionTable) RootPartition() *Partition {
|
|
for _, p := range pt.Partitions {
|
|
if p.Filesystem == nil {
|
|
continue
|
|
}
|
|
|
|
if p.Filesystem.Mountpoint == "/" {
|
|
return &p
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Returns the /boot partition (the partition whose filesystem has /boot as
|
|
// a mountpoint) of the partition table. Nil is returned if there's no such
|
|
// partition.
|
|
func (pt PartitionTable) BootPartition() *Partition {
|
|
for _, p := range pt.Partitions {
|
|
if p.Filesystem == nil {
|
|
continue
|
|
}
|
|
|
|
if p.Filesystem.Mountpoint == "/boot" {
|
|
return &p
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Returns the index of the boot partition: the partition whose filesystem has
|
|
// /boot as a mountpoint. If there is no explicit boot partition, the root
|
|
// partition is returned.
|
|
// If neither boot nor root partitions are found, returns -1.
|
|
func (pt PartitionTable) BootPartitionIndex() int {
|
|
// find partition with '/boot' mountpoint and fallback to '/'
|
|
rootIdx := -1
|
|
for idx, part := range pt.Partitions {
|
|
if part.Filesystem == nil {
|
|
continue
|
|
}
|
|
if part.Filesystem.Mountpoint == "/boot" {
|
|
return idx
|
|
} else if part.Filesystem.Mountpoint == "/" {
|
|
rootIdx = idx
|
|
}
|
|
}
|
|
return rootIdx
|
|
}
|
|
|
|
// Converts Partition to osbuild.QEMUPartition that encodes the same partition.
|
|
func (p Partition) QEMUPartition() osbuild.QEMUPartition {
|
|
var fs *osbuild.QEMUFilesystem
|
|
if p.Filesystem != nil {
|
|
f := p.Filesystem.QEMUFilesystem()
|
|
fs = &f
|
|
}
|
|
return osbuild.QEMUPartition{
|
|
Start: p.Start,
|
|
Size: p.Size,
|
|
Type: p.Type,
|
|
Bootable: p.Bootable,
|
|
UUID: p.UUID,
|
|
Filesystem: fs,
|
|
}
|
|
}
|
|
|
|
// Converts Filesystem to osbuild.QEMUFilesystem that encodes the same fs.
|
|
func (fs Filesystem) QEMUFilesystem() osbuild.QEMUFilesystem {
|
|
return osbuild.QEMUFilesystem{
|
|
Type: fs.Type,
|
|
UUID: fs.UUID,
|
|
Label: fs.Label,
|
|
Mountpoint: fs.Mountpoint,
|
|
}
|
|
}
|