Update osbuild/images to v0.105.0

This brings a lot of new stuff, among others:
 - Internal image types for RHEL-10 (COMPOSER-2357)
 - Support for Swap partitions in DiskCustomizations (COMPOSER-2400)
 - Support for new partitioning customizations for CS and RHEL
 - Fix for RHEL 8 and 9 AMI boot mode (RHEL-69628)

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
This commit is contained in:
Tomáš Hozza 2024-12-06 11:20:10 +01:00 committed by Ondřej Budai
parent 73f3aa22a2
commit fdff0a903e
36 changed files with 1527 additions and 524 deletions

View file

@ -155,6 +155,10 @@ func (bs *BtrfsSubvolume) GetMountpoint() string {
return bs.Mountpoint
}
func (bs *BtrfsSubvolume) GetFSFile() string {
return bs.GetMountpoint()
}
func (bs *BtrfsSubvolume) GetFSType() string {
return "btrfs"
}

View file

@ -56,6 +56,8 @@ const (
RootPartitionUUID = "6264D520-3FB9-423F-8AB8-7A0A8E3D3562"
SwapPartitionGUID = "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F"
// Extended Boot Loader Partition
XBootLDRPartitionGUID = "BC13C2FF-59E6-4262-A352-B275FD6F7172"
@ -70,6 +72,9 @@ const (
// Partition type ID for ESP on dos
DosESPID = "ef00"
// Partition type ID for swap
DosSwapID = "82"
)
// pt type -> type -> ID mapping for convenience
@ -80,6 +85,7 @@ var idMap = map[PartitionTableType]map[string]string{
"data": DosLinuxTypeID,
"esp": DosESPID,
"lvm": DosLinuxTypeID,
"swap": DosSwapID,
},
PT_GPT: {
"bios": BIOSBootPartitionGUID,
@ -87,6 +93,7 @@ var idMap = map[PartitionTableType]map[string]string{
"data": FilesystemDataGUID,
"esp": EFISystemPartitionGUID,
"lvm": LVMPartitionGUID,
"swap": SwapPartitionGUID,
},
}
@ -248,13 +255,21 @@ type Mountable interface {
// GetMountPoint returns the path of the mount point.
GetMountpoint() string
// GetFSType returns the file system type, e.g. 'xfs'.
GetFSType() string
FSTabEntity
}
// GetFSSpec returns the file system spec information.
// FSTabEntity describes any entity that can appear in the fstab file.
type FSTabEntity interface {
// FSSpec for the entity (UUID and Label); the first field of fstab(5).
GetFSSpec() FSSpec
// GetFSTabOptions returns options for mounting the entity.
// The mount point (target) for a filesystem or "none" for swap areas; the second field of fstab(5).
GetFSFile() string
// The type of the filesystem or swap for swap areas; the third field of fstab(5).
GetFSType() string
// The mount options, freq, and passno for the entity; the fourth fifth, and sixth fields of fstab(5) respectively.
GetFSTabOptions() (FSTabOptions, error)
}

View file

@ -55,6 +55,10 @@ func (fs *Filesystem) GetMountpoint() string {
return fs.Mountpoint
}
func (fs *Filesystem) GetFSFile() string {
return fs.GetMountpoint()
}
func (fs *Filesystem) GetFSType() string {
if fs == nil {
return ""

View file

@ -110,12 +110,15 @@ func (vg *LVMVolumeGroup) CreateLogicalVolume(lvName string, size uint64, payloa
if lvName == "" {
// generate a name based on the payload's mountpoint
mntble, ok := payload.(Mountable)
if !ok {
return nil, fmt.Errorf("could not create logical volume: no name provided and payload is not mountable")
switch ent := payload.(type) {
case Mountable:
lvName = ent.GetMountpoint()
case *Swap:
lvName = "swap"
default:
return nil, fmt.Errorf("could not create logical volume: no name provided and payload %T is not mountable or swap", payload)
}
mountpoint := mntble.GetMountpoint()
autoName, err := vg.genLVName(mountpoint)
autoName, err := vg.genLVName(lvName)
if err != nil {
return nil, err
}
@ -133,8 +136,7 @@ func (vg *LVMVolumeGroup) CreateLogicalVolume(lvName string, size uint64, payloa
return &vg.LogicalVolumes[len(vg.LogicalVolumes)-1], nil
}
func (vg *LVMVolumeGroup) AlignUp(size uint64) uint64 {
func alignUp(size uint64) uint64 {
if size%LVMDefaultExtentSize != 0 {
size += LVMDefaultExtentSize - size%LVMDefaultExtentSize
}
@ -142,6 +144,10 @@ func (vg *LVMVolumeGroup) AlignUp(size uint64) uint64 {
return size
}
func (vg *LVMVolumeGroup) AlignUp(size uint64) uint64 {
return alignUp(size)
}
func (vg *LVMVolumeGroup) MetadataSize() uint64 {
if vg == nil {
return 0
@ -211,7 +217,7 @@ func (lv *LVMLogicalVolume) EnsureSize(s uint64) bool {
panic("LVMLogicalVolume.EnsureSize: nil entity")
}
if s > lv.Size {
lv.Size = s
lv.Size = alignUp(s)
return true
}
return false

View file

@ -590,6 +590,32 @@ func (pt *PartitionTable) ForEachMountable(cb MountableCallback) error {
return forEachMountable(pt, []Entity{pt}, cb)
}
type FSTabEntityCallback func(mnt FSTabEntity, path []Entity) error
func forEachFSTabEntity(c Container, path []Entity, cb FSTabEntityCallback) error {
for idx := uint(0); idx < c.GetItemCount(); idx++ {
child := c.GetChild(idx)
childPath := append(path, child)
var err error
switch ent := child.(type) {
case FSTabEntity:
err = cb(ent, childPath)
case Container:
err = forEachFSTabEntity(ent, childPath, cb)
}
if err != nil {
return err
}
}
return nil
}
// ForEachFSTabEntity runs the provided callback function on each FSTabEntity
// in the PartitionTable.
func (pt *PartitionTable) ForEachFSTabEntity(cb FSTabEntityCallback) error {
return forEachFSTabEntity(pt, []Entity{pt}, cb)
}
// FindMountable returns the Mountable entity with the given mountpoint in the
// PartitionTable. Returns nil if no Entity has the target as a Mountpoint.
func (pt *PartitionTable) FindMountable(mountpoint string) Mountable {
@ -812,18 +838,23 @@ type partitionTableFeatures struct {
FAT bool
EXT4 bool
LUKS bool
Swap bool
}
// features examines all of the PartitionTable entities
// and returns a struct with flags set for each feature used
// features examines all of the PartitionTable entities and returns a struct
// with flags set for each feature used. The meaning of "feature" here is quite
// broad. Most disk Entity types are represented by a feature and the existence
// of at least one type in the partition table means the feature is
// represented. For Filesystem entities, there is a separate feature for each
// filesystem type
func (pt *PartitionTable) features() partitionTableFeatures {
var ptFeatures partitionTableFeatures
introspectPT := func(e Entity, path []Entity) error {
switch ent := e.(type) {
case *LVMLogicalVolume:
case *LVMVolumeGroup, *LVMLogicalVolume:
ptFeatures.LVM = true
case *Btrfs:
case *Btrfs, *BtrfsSubvolume:
ptFeatures.Btrfs = true
case *Filesystem:
switch ent.GetFSType() {
@ -836,8 +867,14 @@ func (pt *PartitionTable) features() partitionTableFeatures {
case "ext4":
ptFeatures.EXT4 = true
}
case *Swap:
ptFeatures.Swap = true
case *LUKSContainer:
ptFeatures.LUKS = true
case *PartitionTable, *Partition:
// nothing to do
default:
panic(fmt.Errorf("unknown entity type %T", e))
}
return nil
}
@ -1254,25 +1291,43 @@ func addPlainPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
if err != nil {
return fmt.Errorf("error creating partition with mountpoint %q: %w", partition.Mountpoint, err)
}
// all user-defined partitions are data partitions except boot
typeName := "data"
if partition.Mountpoint == "/boot" {
// all user-defined partitions are data partitions except boot and swap
var typeName string
switch {
case partition.Mountpoint == "/boot":
typeName = "boot"
case fstype == "swap":
typeName = "swap"
default:
typeName = "data"
}
partType, err := getPartitionTypeIDfor(pt.Type, typeName)
if err != nil {
return fmt.Errorf("error getting partition type ID for %q: %w", partition.Mountpoint, err)
}
newpart := Partition{
Type: partType,
Bootable: false,
Size: partition.MinSize,
Payload: &Filesystem{
var payload PayloadEntity
switch typeName {
case "swap":
payload = &Swap{
Label: partition.Label,
FSTabOptions: "defaults", // TODO: add customization
}
default:
payload = &Filesystem{
Type: fstype,
Label: partition.Label,
Mountpoint: partition.Mountpoint,
FSTabOptions: "defaults", // TODO: add customization
},
}
}
newpart := Partition{
Type: partType,
Size: partition.MinSize,
Payload: payload,
}
pt.Partitions = append(pt.Partitions, newpart)
return nil
@ -1310,11 +1365,21 @@ func addLVMPartition(pt *PartitionTable, partition blueprint.PartitionCustomizat
if err != nil {
return fmt.Errorf("error creating logical volume %q (%s): %w", lv.Name, lv.Mountpoint, err)
}
newfs := &Filesystem{
Type: fstype,
Label: lv.Label,
Mountpoint: lv.Mountpoint,
FSTabOptions: "defaults", // TODO: add customization
var newfs PayloadEntity
switch fstype {
case "swap":
newfs = &Swap{
Label: lv.Label,
FSTabOptions: "defaults", // TODO: add customization
}
default:
newfs = &Filesystem{
Type: fstype,
Label: lv.Label,
Mountpoint: lv.Mountpoint,
FSTabOptions: "defaults", // TODO: add customization
}
}
if _, err := newvg.CreateLogicalVolume(lv.Name, lv.MinSize, newfs); err != nil {
return fmt.Errorf("error creating logical volume %q (%s): %w", lv.Name, lv.Mountpoint, err)

77
vendor/github.com/osbuild/images/pkg/disk/swap.go generated vendored Normal file
View file

@ -0,0 +1,77 @@
package disk
import (
"math/rand"
"reflect"
"github.com/google/uuid"
)
// Swap defines the payload for a swap partition. It's similar to a
// [Filesystem] but with fewer fields. It is a [PayloadEntity] and also a
// [FSTabEntity].
type Swap struct {
UUID string
Label string
// The fourth field of fstab(5); fs_mntops
FSTabOptions string
}
func init() {
payloadEntityMap["swap"] = reflect.TypeOf(Swap{})
}
func (s *Swap) EntityName() string {
return "swap"
}
func (s *Swap) Clone() Entity {
if s == nil {
return nil
}
return &Swap{
UUID: s.UUID,
Label: s.Label,
FSTabOptions: s.FSTabOptions,
}
}
// For swap, the fs_file entry in the fstab is always "none".
func (s *Swap) GetFSFile() string {
return "none"
}
// For swap, the fs_vfstype entry in the fstab is always "swap".
func (s *Swap) GetFSType() string {
return "swap"
}
func (s *Swap) GetFSSpec() FSSpec {
if s == nil {
return FSSpec{}
}
return FSSpec{
UUID: s.UUID,
Label: s.Label,
}
}
// For swap, the Freq and PassNo are always 0.
func (s *Swap) GetFSTabOptions() (FSTabOptions, error) {
if s == nil {
return FSTabOptions{}, nil
}
return FSTabOptions{
MntOps: s.FSTabOptions,
Freq: 0,
PassNo: 0,
}, nil
}
func (s *Swap) GenUUID(rng *rand.Rand) {
if s.UUID == "" {
s.UUID = uuid.Must(newRandomUUIDFromReader(rng)).String()
}
}