go.mod,vendor: run go get -u github.com/osbuild/images

This commit updates the "images" dependency.
This commit is contained in:
Michael Vogt 2025-01-10 16:00:57 +01:00 committed by Tomáš Hozza
parent a18ec71dc8
commit 9dd8b2c50f
87 changed files with 1266 additions and 706 deletions

View file

@ -14,13 +14,15 @@ import (
)
type DiskCustomization struct {
// TODO: Add partition table type: gpt or dos
// Type of the partition table: gpt or dos.
// Optional, the default depends on the distro and image type.
Type string
MinSize uint64
Partitions []PartitionCustomization
}
type diskCustomizationMarshaler struct {
// TODO: Add partition table type: gpt or dos
Type string `json:"type,omitempty" toml:"type,omitempty"`
MinSize datasizes.Size `json:"minsize,omitempty" toml:"minsize,omitempty"`
Partitions []PartitionCustomization `json:"partitions,omitempty" toml:"partitions,omitempty"`
}
@ -30,6 +32,7 @@ func (dc *DiskCustomization) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &dcm); err != nil {
return err
}
dc.Type = dcm.Type
dc.MinSize = dcm.MinSize.Uint64()
dc.Partitions = dcm.Partitions
@ -345,6 +348,21 @@ func (p *DiskCustomization) Validate() error {
return nil
}
switch p.Type {
case "gpt", "":
case "dos":
// dos/mbr only supports 4 partitions
// Unfortunately, at this stage it's unknown whether we will need extra
// partitions (bios boot, root, esp), so this check is just to catch
// obvious invalid customizations early. The final partition table is
// checked after it's created.
if len(p.Partitions) > 4 {
return fmt.Errorf("invalid partitioning customizations: \"dos\" partition table type only supports up to 4 partitions: got %d", len(p.Partitions))
}
default:
return fmt.Errorf("unknown partition table type: %s (valid: gpt, dos)", p.Type)
}
mountpoints := make(map[string]bool)
vgnames := make(map[string]bool)
var errs []error
@ -470,7 +488,7 @@ func (p *PartitionCustomization) validatePlain(mountpoints map[string]bool) erro
}
// TODO: allow empty fstype with default from distro
if !slices.Contains(validPlainFSTypes, p.FSType) {
return fmt.Errorf("unknown or invalid filesystem type for mountpoint %q: %s", p.Mountpoint, p.FSType)
return fmt.Errorf("unknown or invalid filesystem type (fs_type) for mountpoint %q: %s", p.Mountpoint, p.FSType)
}
if err := validateFilesystemType(p.Mountpoint, p.FSType); err != nil {
return err
@ -523,7 +541,7 @@ func (p *PartitionCustomization) validateLVM(mountpoints, vgnames map[string]boo
// TODO: allow empty fstype with default from distro
if !slices.Contains(validPlainFSTypes, lv.FSType) {
return fmt.Errorf("unknown or invalid filesystem type for logical volume with mountpoint %q: %s", lv.Mountpoint, lv.FSType)
return fmt.Errorf("unknown or invalid filesystem type (fs_type) for logical volume with mountpoint %q: %s", lv.Mountpoint, lv.FSType)
}
}
return nil

View file

@ -40,7 +40,7 @@ const (
// rounded to the next MiB.
DefaultGrainBytes = uint64(1048576) // 1 MiB
// UUIDs
// UUIDs for GPT disks
BIOSBootPartitionGUID = "21686148-6449-6E6F-744E-656564454649"
BIOSBootPartitionUUID = "FAC7F1FB-3E8D-4137-A512-961DE09A5549"
@ -61,31 +61,42 @@ const (
// Extended Boot Loader Partition
XBootLDRPartitionGUID = "BC13C2FF-59E6-4262-A352-B275FD6F7172"
// DosFat16B used for the ESP-System partition
DosFat16B = "06"
// Partition type IDs for DOS disks
// Partition type ID for BIOS boot partition on dos.
// Type ID is for 'empty'.
// TODO: drop this completely when we convert the bios BOOT space to a
// partitionless gap/offset.
BIOSBootPartitionDOSID = "00"
// Partition type ID for any native Linux filesystem on dos
DosLinuxTypeID = "83"
FilesystemLinuxDOSID = "83"
// Partition type ID for BIOS boot partition on dos
DosBIOSBootID = "ef02"
// FAT16BDOSID used for the ESP-System partition
FAT16BDOSID = "06"
// Partition type ID for LVM on dos
LVMPartitionDOSID = "8e"
// Partition type ID for ESP on dos
DosESPID = "ef00"
EFISystemPartitionDOSID = "ef"
// Partition type ID for swap
DosSwapID = "82"
SwapPartitionDOSID = "82"
// Partition type ID for PRep on dos
PRepPartitionDOSID = "41"
)
// pt type -> type -> ID mapping for convenience
var idMap = map[PartitionTableType]map[string]string{
PT_DOS: {
"bios": DosBIOSBootID,
"boot": DosLinuxTypeID,
"data": DosLinuxTypeID,
"esp": DosESPID,
"lvm": DosLinuxTypeID,
"swap": DosSwapID,
"bios": BIOSBootPartitionDOSID,
"boot": FilesystemLinuxDOSID,
"data": FilesystemLinuxDOSID,
"esp": EFISystemPartitionDOSID,
"lvm": LVMPartitionDOSID,
"swap": SwapPartitionDOSID,
},
PT_GPT: {
"bios": BIOSBootPartitionGUID,

View file

@ -87,7 +87,7 @@ func (p *Partition) IsBIOSBoot() bool {
return false
}
return p.Type == BIOSBootPartitionGUID
return p.Type == BIOSBootPartitionGUID || p.Type == BIOSBootPartitionDOSID
}
func (p *Partition) IsPReP() bool {
@ -95,7 +95,7 @@ func (p *Partition) IsPReP() bool {
return false
}
return p.Type == "41" || p.Type == PRePartitionGUID
return p.Type == PRepPartitionDOSID || p.Type == PRePartitionGUID
}
func (p *Partition) MarshalJSON() ([]byte, error) {

View file

@ -731,36 +731,36 @@ func (pt *PartitionTable) ensureLVM() error {
if _, ok := parent.(*LVMLogicalVolume); ok {
return nil
} else if part, ok := parent.(*Partition); ok {
filesystem := part.Payload
vg := &LVMVolumeGroup{
Name: "rootvg",
Description: "created via lvm2 and osbuild",
}
// create root logical volume on the new volume group with the same
// size and filesystem as the previous root partition
_, err := vg.CreateLogicalVolume("rootlv", part.Size, filesystem)
if err != nil {
panic(fmt.Sprintf("Could not create LV: %v", err))
}
// replace the top-level partition payload with the new volume group
part.Payload = vg
// reset the vg partition size - it will be grown later
part.Size = 0
if pt.Type == PT_GPT {
part.Type = LVMPartitionGUID
} else {
part.Type = "8e"
}
} else {
}
part, ok := parent.(*Partition)
if !ok {
return fmt.Errorf("Unsupported parent for LVM")
}
filesystem := part.Payload
vg := &LVMVolumeGroup{
Name: "rootvg",
Description: "created via lvm2 and osbuild",
}
// create root logical volume on the new volume group with the same
// size and filesystem as the previous root partition
_, err := vg.CreateLogicalVolume("rootlv", part.Size, filesystem)
if err != nil {
panic(fmt.Sprintf("Could not create LV: %v", err))
}
// replace the top-level partition payload with the new volume group
part.Payload = vg
// reset the vg partition size - it will be grown later
part.Size = 0
if pt.Type == PT_GPT {
part.Type = LVMPartitionGUID
} else {
part.Type = LVMPartitionDOSID
}
return nil
}
@ -789,44 +789,44 @@ func (pt *PartitionTable) ensureBtrfs() error {
if _, ok := parent.(*Btrfs); ok {
return nil
} else if part, ok := parent.(*Partition); ok {
rootMountable, ok := rootPath[0].(Mountable)
if !ok {
return fmt.Errorf("root entity is not mountable: %T, this is a violation of entityPath() contract", rootPath[0])
}
opts, err := rootMountable.GetFSTabOptions()
if err != nil {
return err
}
btrfs := &Btrfs{
Label: "root",
Subvolumes: []BtrfsSubvolume{
{
Name: "root",
Mountpoint: "/",
Compress: DefaultBtrfsCompression,
ReadOnly: opts.ReadOnly(),
Size: part.Size,
},
},
}
// replace the top-level partition payload with a new btrfs filesystem
part.Payload = btrfs
// reset the btrfs partition size - it will be grown later
part.Size = 0
part.Type, err = getPartitionTypeIDfor(pt.Type, "data")
if err != nil {
return fmt.Errorf("error converting partition table to btrfs: %w", err)
}
} else {
}
part, ok := parent.(*Partition)
if !ok {
return fmt.Errorf("unsupported parent for btrfs: %T", parent)
}
rootMountable, ok := rootPath[0].(Mountable)
if !ok {
return fmt.Errorf("root entity is not mountable: %T, this is a violation of entityPath() contract", rootPath[0])
}
opts, err := rootMountable.GetFSTabOptions()
if err != nil {
return err
}
btrfs := &Btrfs{
Label: "root",
Subvolumes: []BtrfsSubvolume{
{
Name: "root",
Mountpoint: "/",
Compress: DefaultBtrfsCompression,
ReadOnly: opts.ReadOnly(),
Size: part.Size,
},
},
}
// replace the top-level partition payload with a new btrfs filesystem
part.Payload = btrfs
// reset the btrfs partition size - it will be grown later
part.Size = 0
part.Type, err = getPartitionTypeIDfor(pt.Type, "data")
if err != nil {
return fmt.Errorf("error converting partition table to btrfs: %w", err)
}
return nil
}
@ -1232,15 +1232,24 @@ func NewCustomPartitionTable(customizations *blueprint.DiskCustomization, option
pt := &PartitionTable{}
// TODO: Handle partition table type in customizations
switch options.PartitionTableType {
case PT_GPT, PT_DOS:
pt.Type = options.PartitionTableType
case PT_NONE:
// default to "gpt"
switch customizations.Type {
case "dos":
pt.Type = PT_DOS
case "gpt":
pt.Type = PT_GPT
case "":
// partition table type not specified, determine the default
switch options.PartitionTableType {
case PT_GPT, PT_DOS:
pt.Type = options.PartitionTableType
case PT_NONE:
// default to "gpt"
pt.Type = PT_GPT
default:
return nil, fmt.Errorf("%s invalid partition table type enum value: %d", errPrefix, options.PartitionTableType)
}
default:
return nil, fmt.Errorf("%s invalid partition table type enum value: %d", errPrefix, options.PartitionTableType)
return nil, fmt.Errorf("%s invalid partition table type: %s", errPrefix, customizations.Type)
}
// add any partition(s) that are needed for booting (like /boot/efi)
@ -1266,7 +1275,9 @@ func NewCustomPartitionTable(customizations *blueprint.DiskCustomization, option
return nil, fmt.Errorf("%s %w", errPrefix, err)
}
case "btrfs":
addBtrfsPartition(pt, part)
if err := addBtrfsPartition(pt, part); err != nil {
return nil, fmt.Errorf("%s %w", errPrefix, err)
}
default:
return nil, fmt.Errorf("%s invalid partition type: %s", errPrefix, part.Type)
}
@ -1283,6 +1294,16 @@ func NewCustomPartitionTable(customizations *blueprint.DiskCustomization, option
pt.relayout(customizations.MinSize)
pt.GenerateUUIDs(rng)
// One thing not caught by the customization validation is if a final "dos"
// partition table has more than 4 partitions. This is not possible to
// predict with customizations alone because it depends on the boot type
// (which comes from the image type) which controls automatic partition
// creation. We should therefore always check the final partition table for
// this rule.
if pt.Type == PT_DOS && len(pt.Partitions) > 4 {
return nil, fmt.Errorf("%s invalid partition table: \"dos\" partition table type only supports up to 4 partitions: got %d after creating the partition table with all necessary partitions", errPrefix, len(pt.Partitions))
}
return pt, nil
}
@ -1387,8 +1408,12 @@ func addLVMPartition(pt *PartitionTable, partition blueprint.PartitionCustomizat
}
// create partition for volume group
partType, err := getPartitionTypeIDfor(pt.Type, "lvm")
if err != nil {
return fmt.Errorf("error creating lvm partition %q: %w", vgname, err)
}
newpart := Partition{
Type: LVMPartitionGUID,
Type: partType,
Size: partition.MinSize,
Bootable: false,
Payload: newvg,
@ -1397,7 +1422,7 @@ func addLVMPartition(pt *PartitionTable, partition blueprint.PartitionCustomizat
return nil
}
func addBtrfsPartition(pt *PartitionTable, partition blueprint.PartitionCustomization) {
func addBtrfsPartition(pt *PartitionTable, partition blueprint.PartitionCustomization) error {
subvols := make([]BtrfsSubvolume, len(partition.Subvolumes))
for idx, subvol := range partition.Subvolumes {
newsubvol := BtrfsSubvolume{
@ -1412,14 +1437,19 @@ func addBtrfsPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
}
// create partition for btrfs volume
partType, err := getPartitionTypeIDfor(pt.Type, "data")
if err != nil {
return fmt.Errorf("error creating btrfs partition: %w", err)
}
newpart := Partition{
Type: FilesystemDataGUID,
Type: partType,
Bootable: false,
Payload: newvol,
Size: partition.MinSize,
}
pt.Partitions = append(pt.Partitions, newpart)
return nil
}
// Determine if a boot partition is needed based on the customizations. A boot

View file

@ -1,6 +1,8 @@
package distro
import (
"time"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/disk"
@ -120,7 +122,9 @@ type ImageType interface {
// specified in the given blueprint; it also returns any warnings (e.g.
// deprecation notices) generated by the manifest.
// The packageSpecSets must be labelled in the same way as the originating PackageSets.
Manifest(bp *blueprint.Blueprint, options ImageOptions, repos []rpmmd.RepoConfig, seed int64) (*manifest.Manifest, []string, error)
// A custom seed for the rng can be specified, if nil the seed will
// be random.
Manifest(bp *blueprint.Blueprint, options ImageOptions, repos []rpmmd.RepoConfig, seed *int64) (*manifest.Manifest, []string, error)
}
// The ImageOptions specify options for a specific image build
@ -155,3 +159,10 @@ func ExportsFallback() []string {
func PayloadPackageSets() []string {
return []string{}
}
func SeedFrom(p *int64) int64 {
if p == nil {
return time.Now().UnixNano()
}
return *p
}

View file

@ -100,7 +100,7 @@ var (
// We don't know the variant of the OS pipeline being installed
isoLabel: getISOLabelFunc("Unknown"),
buildPipelines: []string{"build"},
payloadPipelines: []string{"anaconda-tree", "rootfs-image", "efiboot-tree", "os", "bootiso-tree", "bootiso"},
payloadPipelines: []string{"anaconda-tree", "efiboot-tree", "os", "bootiso-tree", "bootiso"},
exports: []string{"bootiso"},
requiredPartitionSizes: requiredDirectorySizes,
}
@ -119,7 +119,7 @@ var (
image: liveInstallerImage,
isoLabel: getISOLabelFunc("Workstation"),
buildPipelines: []string{"build"},
payloadPipelines: []string{"anaconda-tree", "rootfs-image", "efiboot-tree", "bootiso-tree", "bootiso"},
payloadPipelines: []string{"anaconda-tree", "efiboot-tree", "bootiso-tree", "bootiso"},
exports: []string{"bootiso"},
requiredPartitionSizes: requiredDirectorySizes,
}
@ -200,7 +200,7 @@ var (
image: iotInstallerImage,
isoLabel: getISOLabelFunc("IoT"),
buildPipelines: []string{"build"},
payloadPipelines: []string{"anaconda-tree", "rootfs-image", "efiboot-tree", "bootiso-tree", "bootiso"},
payloadPipelines: []string{"anaconda-tree", "efiboot-tree", "bootiso-tree", "bootiso"},
exports: []string{"bootiso"},
requiredPartitionSizes: requiredDirectorySizes,
}

View file

@ -403,6 +403,10 @@ func liveInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
}
return img, nil
}
@ -456,8 +460,6 @@ func imageInstallerImage(workload workload.Workload,
img.ExtraBasePackages = packageSets[installerPkgsKey]
img.SquashfsCompression = "lz4"
d := t.arch.distro
img.Product = d.product
@ -477,6 +479,11 @@ func imageInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
img.SquashfsCompression = "lz4"
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
}
return img, nil
}
@ -660,8 +667,6 @@ func iotInstallerImage(workload workload.Workload,
anaconda.ModuleUsers,
}...)
img.SquashfsCompression = "lz4"
img.Product = d.product
img.Variant = "IoT"
img.OSVersion = d.osVersion
@ -675,6 +680,11 @@ func iotInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
img.SquashfsCompression = "lz4"
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
}
return img, nil
}

View file

@ -207,7 +207,8 @@ func (t *imageType) PartitionType() disk.PartitionTableType {
func (t *imageType) Manifest(bp *blueprint.Blueprint,
options distro.ImageOptions,
repos []rpmmd.RepoConfig,
seed int64) (*manifest.Manifest, []string, error) {
seedp *int64) (*manifest.Manifest, []string, error) {
seed := distro.SeedFrom(seedp)
warnings, err := t.checkOptions(bp, options)
if err != nil {

View file

@ -112,7 +112,7 @@ var defaultBasePartitionTables = distro.BasePartitionTableMap{
Partitions: []disk.Partition{
{
Size: 4 * datasizes.MebiByte,
Type: "41",
Type: disk.PRepPartitionDOSID,
Bootable: true,
},
{
@ -224,7 +224,7 @@ var minimalrawPartitionTables = distro.BasePartitionTableMap{
Partitions: []disk.Partition{
{
Size: 200 * datasizes.MebiByte,
Type: disk.DosFat16B,
Type: disk.FAT16BDOSID,
Bootable: true,
Payload: &disk.Filesystem{
Type: "vfat",
@ -238,7 +238,7 @@ var minimalrawPartitionTables = distro.BasePartitionTableMap{
},
{
Size: 1 * datasizes.GibiByte,
Type: disk.DosLinuxTypeID,
Type: disk.FilesystemLinuxDOSID,
Payload: &disk.Filesystem{
Type: "ext4",
Mountpoint: "/boot",
@ -250,7 +250,7 @@ var minimalrawPartitionTables = distro.BasePartitionTableMap{
},
{
Size: 2 * datasizes.GibiByte,
Type: disk.DosLinuxTypeID,
Type: disk.FilesystemLinuxDOSID,
Payload: &disk.Filesystem{
Type: "ext4",
Label: "root",
@ -319,7 +319,7 @@ var iotBasePartitionTables = distro.BasePartitionTableMap{
Partitions: []disk.Partition{
{
Size: 501 * datasizes.MebiByte,
Type: disk.DosFat16B,
Type: disk.FAT16BDOSID,
Bootable: true,
Payload: &disk.Filesystem{
Type: "vfat",
@ -333,7 +333,7 @@ var iotBasePartitionTables = distro.BasePartitionTableMap{
},
{
Size: 1 * datasizes.GibiByte,
Type: disk.DosLinuxTypeID,
Type: disk.FilesystemLinuxDOSID,
Payload: &disk.Filesystem{
Type: "ext4",
Mountpoint: "/boot",
@ -345,7 +345,7 @@ var iotBasePartitionTables = distro.BasePartitionTableMap{
},
{
Size: 2569 * datasizes.MebiByte,
Type: disk.DosLinuxTypeID,
Type: disk.FilesystemLinuxDOSID,
Payload: &disk.Filesystem{
Type: "ext4",
Label: "root",

View file

@ -2,3 +2,7 @@ package fedora
const VERSION_BRANCHED = "42"
const VERSION_RAWHIDE = "42"
// Fedora version 41 and later use a plain squashfs rootfs on the iso instead of
// compressing an ext4 filesystem.
const VERSION_ROOTFS_SQUASHFS = "41"

View file

@ -496,6 +496,9 @@ func EdgeInstallerImage(workload workload.Workload,
img.Kickstart.Timezone, _ = customizations.GetTimezoneSettings()
img.SquashfsCompression = "xz"
if t.Arch().Distro().Releasever() == "10" {
img.RootfsType = manifest.SquashfsRootfs
}
installerConfig, err := t.getDefaultInstallerConfig()
if err != nil {
@ -714,6 +717,9 @@ func ImageInstallerImage(workload workload.Workload,
img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, anaconda.ModuleUsers)
img.SquashfsCompression = "xz"
if t.Arch().Distro().Releasever() == "10" {
img.RootfsType = manifest.SquashfsRootfs
}
// put the kickstart file in the root of the iso
img.ISORootKickstart = true

View file

@ -258,7 +258,8 @@ func (t *ImageType) PartitionType() disk.PartitionTableType {
func (t *ImageType) Manifest(bp *blueprint.Blueprint,
options distro.ImageOptions,
repos []rpmmd.RepoConfig,
seed int64) (*manifest.Manifest, []string, error) {
seedp *int64) (*manifest.Manifest, []string, error) {
seed := distro.SeedFrom(seedp)
if t.Workload != nil {
// For now, if an image type defines its own workload, don't allow any

View file

@ -40,7 +40,7 @@ func mkImageInstallerImgType() *rhel.ImageType {
},
rhel.ImageInstallerImage,
[]string{"build"},
[]string{"anaconda-tree", "rootfs-image", "efiboot-tree", "os", "bootiso-tree", "bootiso"},
[]string{"anaconda-tree", "efiboot-tree", "os", "bootiso-tree", "bootiso"},
[]string{"bootiso"},
)

View file

@ -90,7 +90,7 @@ func defaultBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
Partitions: []disk.Partition{
{
Size: 4 * datasizes.MebiByte,
Type: "41",
Type: disk.PRepPartitionDOSID,
Bootable: true,
},
{

View file

@ -91,7 +91,7 @@ func defaultBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
Partitions: []disk.Partition{
{
Size: 4 * datasizes.MebiByte,
Type: "41",
Type: disk.PRepPartitionDOSID,
Bootable: true,
},
{

View file

@ -173,7 +173,7 @@ func defaultBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
Partitions: []disk.Partition{
{
Size: 4 * datasizes.MebiByte,
Type: "41",
Type: disk.PRepPartitionDOSID,
Bootable: true,
},
{

View file

@ -232,7 +232,7 @@ func (t *TestImageType) Exports() []string {
return distro.ExportsFallback()
}
func (t *TestImageType) Manifest(b *blueprint.Blueprint, options distro.ImageOptions, repos []rpmmd.RepoConfig, seed int64) (*manifest.Manifest, []string, error) {
func (t *TestImageType) Manifest(b *blueprint.Blueprint, options distro.ImageOptions, repos []rpmmd.RepoConfig, seedp *int64) (*manifest.Manifest, []string, error) {
var bpPkgs []string
if b != nil {
mountpoints := b.Customizations.GetFilesystems()

View file

@ -23,6 +23,7 @@ type AnacondaContainerInstaller struct {
ExtraBasePackages rpmmd.PackageSet
SquashfsCompression string
RootfsType manifest.RootfsType
ISOLabel string
Product string
@ -98,8 +99,13 @@ func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest,
}
anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers
rootfsImagePipeline := manifest.NewISORootfsImg(buildPipeline, anacondaPipeline)
rootfsImagePipeline.Size = 4 * datasizes.GibiByte
var rootfsImagePipeline *manifest.ISORootfsImg
switch img.RootfsType {
case manifest.SquashfsExt4Rootfs:
rootfsImagePipeline = manifest.NewISORootfsImg(buildPipeline, anacondaPipeline)
rootfsImagePipeline.Size = 4 * datasizes.GibiByte
default:
}
bootTreePipeline := manifest.NewEFIBootTree(buildPipeline, img.Product, img.OSVersion)
bootTreePipeline.Platform = img.Platform

View file

@ -23,6 +23,9 @@ type AnacondaLiveInstaller struct {
ExtraBasePackages rpmmd.PackageSet
SquashfsCompression string
RootfsType manifest.RootfsType
ISOLabel string
Product string
Variant string
@ -70,8 +73,13 @@ func (img *AnacondaLiveInstaller) InstantiateManifest(m *manifest.Manifest,
livePipeline.Checkpoint()
rootfsImagePipeline := manifest.NewISORootfsImg(buildPipeline, livePipeline)
rootfsImagePipeline.Size = 8 * datasizes.GibiByte
var rootfsImagePipeline *manifest.ISORootfsImg
switch img.RootfsType {
case manifest.SquashfsExt4Rootfs:
rootfsImagePipeline = manifest.NewISORootfsImg(buildPipeline, livePipeline)
rootfsImagePipeline.Size = 8 * datasizes.GibiByte
default:
}
bootTreePipeline := manifest.NewEFIBootTree(buildPipeline, img.Product, img.OSVersion)
bootTreePipeline.Platform = img.Platform
@ -99,6 +107,8 @@ func (img *AnacondaLiveInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.KernelOpts = kernelOpts
isoTreePipeline.ISOLinux = isoLinuxEnabled
isoTreePipeline.SquashfsCompression = img.SquashfsCompression
isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel)
isoPipeline.SetFilename(img.Filename)
isoPipeline.ISOLinux = isoLinuxEnabled

View file

@ -29,6 +29,7 @@ type AnacondaOSTreeInstaller struct {
Subscription *subscription.ImageOptions
SquashfsCompression string
RootfsType manifest.RootfsType
ISOLabel string
Product string
@ -101,8 +102,13 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
anacondaPipeline.DisabledAnacondaModules = img.DisabledAnacondaModules
anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers
rootfsImagePipeline := manifest.NewISORootfsImg(buildPipeline, anacondaPipeline)
rootfsImagePipeline.Size = 4 * datasizes.GibiByte
var rootfsImagePipeline *manifest.ISORootfsImg
switch img.RootfsType {
case manifest.SquashfsExt4Rootfs:
rootfsImagePipeline = manifest.NewISORootfsImg(buildPipeline, anacondaPipeline)
rootfsImagePipeline.Size = 4 * datasizes.GibiByte
default:
}
bootTreePipeline := manifest.NewEFIBootTree(buildPipeline, img.Product, img.OSVersion)
bootTreePipeline.Platform = img.Platform

View file

@ -57,6 +57,7 @@ type AnacondaTarInstaller struct {
Kickstart *kickstart.Options
SquashfsCompression string
RootfsType manifest.RootfsType
ISOLabel string
Product string
@ -153,8 +154,13 @@ func (img *AnacondaTarInstaller) InstantiateManifest(m *manifest.Manifest,
anacondaPipeline.Checkpoint()
rootfsImagePipeline := manifest.NewISORootfsImg(buildPipeline, anacondaPipeline)
rootfsImagePipeline.Size = 5 * datasizes.GibiByte
var rootfsImagePipeline *manifest.ISORootfsImg
switch img.RootfsType {
case manifest.SquashfsExt4Rootfs:
rootfsImagePipeline = manifest.NewISORootfsImg(buildPipeline, anacondaPipeline)
rootfsImagePipeline.Size = 5 * datasizes.GibiByte
default:
}
bootTreePipeline := manifest.NewEFIBootTree(buildPipeline, img.Product, img.OSVersion)
bootTreePipeline.Platform = img.Platform

View file

@ -17,6 +17,14 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
type RootfsType uint64
// These constants are used by the ISO images to control the style of the root filesystem
const ( // Rootfs type enum
SquashfsExt4Rootfs RootfsType = iota // Create an EXT4 rootfs compressed by Squashfs
SquashfsRootfs // Create a plain squashfs rootfs
)
// An AnacondaInstallerISOTree represents a tree containing the anaconda installer,
// configuration in terms of a kickstart file, as well as an embedded
// payload to be installed, this payload can either be an ostree
@ -30,7 +38,7 @@ type AnacondaInstallerISOTree struct {
PartitionTable *disk.PartitionTable
anacondaPipeline *AnacondaInstaller
rootfsPipeline *ISORootfsImg
rootfsPipeline *ISORootfsImg // May be nil for plain squashfs rootfs
bootTreePipeline *EFIBootTree
// The path where the payload (tarball, ostree repo, or container) will be stored.
@ -68,7 +76,7 @@ type AnacondaInstallerISOTree struct {
func NewAnacondaInstallerISOTree(buildPipeline Build, anacondaPipeline *AnacondaInstaller, rootfsPipeline *ISORootfsImg, bootTreePipeline *EFIBootTree) *AnacondaInstallerISOTree {
// the three pipelines should all belong to the same manifest
if anacondaPipeline.Manifest() != rootfsPipeline.Manifest() ||
if (rootfsPipeline != nil && anacondaPipeline.Manifest() != rootfsPipeline.Manifest()) ||
anacondaPipeline.Manifest() != bootTreePipeline.Manifest() {
panic("pipelines from different manifests")
}
@ -278,7 +286,14 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
}
}
squashfsStage := osbuild.NewSquashfsStage(&squashfsOptions, p.rootfsPipeline.Name())
// The iso's rootfs can either be an ext4 filesystem compressed with squashfs, or
// a squashfs of the plain directory tree
var squashfsStage *osbuild.Stage
if p.rootfsPipeline != nil {
squashfsStage = osbuild.NewSquashfsStage(&squashfsOptions, p.rootfsPipeline.Name())
} else {
squashfsStage = osbuild.NewSquashfsStage(&squashfsOptions, p.anacondaPipeline.Name())
}
pipeline.AddStage(squashfsStage)
if p.ISOLinux {

View file

@ -1,5 +1,11 @@
package osbuild
import (
"fmt"
"github.com/osbuild/images/pkg/disk"
)
// Partition a target using sfdisk(8)
type SfdiskStageOptions struct {
@ -36,7 +42,18 @@ type SfdiskPartition struct {
UUID string `json:"uuid,omitempty"`
}
func (o SfdiskStageOptions) validate() error {
if o.Label == disk.PT_DOS.String() && len(o.Partitions) > 4 {
return fmt.Errorf("sfdisk stage creation failed: \"dos\" partition table only supports up to 4 partitions: got %d", len(o.Partitions))
}
return nil
}
func NewSfdiskStage(options *SfdiskStageOptions, device *Device) *Stage {
if err := options.validate(); err != nil {
panic(err)
}
return &Stage{
Type: "org.osbuild.sfdisk",
Options: options,