Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add erofs support #1117

Merged
merged 7 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/distro/fedora/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ func imageInstallerImage(workload workload.Workload,

img.Filename = t.Filename()

img.SquashfsCompression = "lz4"
img.RootfsCompression = "lz4"
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
}
Expand Down Expand Up @@ -680,7 +680,7 @@ func iotInstallerImage(workload workload.Workload,

img.Filename = t.Filename()

img.SquashfsCompression = "lz4"
img.RootfsCompression = "lz4"
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/distro/rhel/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ func EdgeInstallerImage(workload workload.Workload,
// kickstart though kickstart does support setting them
img.Kickstart.Timezone, _ = customizations.GetTimezoneSettings()

img.SquashfsCompression = "xz"
img.RootfsCompression = "xz"
if t.Arch().Distro().Releasever() == "10" {
img.RootfsType = manifest.SquashfsRootfs
}
Expand Down Expand Up @@ -716,7 +716,7 @@ func ImageInstallerImage(workload workload.Workload,
}
img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, anaconda.ModuleUsers)

img.SquashfsCompression = "xz"
img.RootfsCompression = "xz"
if t.Arch().Distro().Releasever() == "10" {
img.RootfsType = manifest.SquashfsRootfs
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/image/anaconda_container_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ type AnacondaContainerInstaller struct {
Platform platform.Platform
ExtraBasePackages rpmmd.PackageSet

SquashfsCompression string
RootfsType manifest.RootfsType
RootfsCompression string
RootfsType manifest.RootfsType

ISOLabel string
Product string
Expand Down Expand Up @@ -132,7 +132,8 @@ func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.Release = img.Release
isoTreePipeline.Kickstart = img.Kickstart

isoTreePipeline.SquashfsCompression = img.SquashfsCompression
isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType

// For ostree installers, always put the kickstart file in the root of the ISO
isoTreePipeline.PayloadPath = "/container"
Expand Down
7 changes: 4 additions & 3 deletions pkg/image/anaconda_live_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ type AnacondaLiveInstaller struct {

ExtraBasePackages rpmmd.PackageSet

SquashfsCompression string
RootfsType manifest.RootfsType
RootfsCompression string
RootfsType manifest.RootfsType

ISOLabel string
Product string
Expand Down Expand Up @@ -107,7 +107,8 @@ func (img *AnacondaLiveInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.KernelOpts = kernelOpts
isoTreePipeline.ISOLinux = isoLinuxEnabled

isoTreePipeline.SquashfsCompression = img.SquashfsCompression
isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType

isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel)
isoPipeline.SetFilename(img.Filename)
Expand Down
7 changes: 4 additions & 3 deletions pkg/image/anaconda_ostree_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ type AnacondaOSTreeInstaller struct {
// Subscription options to include
Subscription *subscription.ImageOptions

SquashfsCompression string
RootfsType manifest.RootfsType
RootfsCompression string
RootfsType manifest.RootfsType

ISOLabel string
Product string
Expand Down Expand Up @@ -139,7 +139,8 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.PartitionTable = efiBootPartitionTable(rng)
isoTreePipeline.Release = img.Release
isoTreePipeline.Kickstart = img.Kickstart
isoTreePipeline.SquashfsCompression = img.SquashfsCompression
isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType

isoTreePipeline.PayloadPath = "/ostree/repo"

Expand Down
7 changes: 4 additions & 3 deletions pkg/image/anaconda_tar_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ type AnacondaTarInstaller struct {
ISORootKickstart bool
Kickstart *kickstart.Options

SquashfsCompression string
RootfsType manifest.RootfsType
RootfsCompression string
RootfsType manifest.RootfsType

ISOLabel string
Product string
Expand Down Expand Up @@ -195,7 +195,8 @@ func (img *AnacondaTarInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.Kickstart.Path = img.Kickstart.Path
}

isoTreePipeline.SquashfsCompression = img.SquashfsCompression
isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType

isoTreePipeline.OSPipeline = osPipeline
isoTreePipeline.KernelOpts = img.AdditionalKernelOpts
Expand Down
119 changes: 83 additions & 36 deletions pkg/manifest/anaconda_installer_iso_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type RootfsType uint64
const ( // Rootfs type enum
SquashfsExt4Rootfs RootfsType = iota // Create an EXT4 rootfs compressed by Squashfs
SquashfsRootfs // Create a plain squashfs rootfs
ErofsRootfs // Create a plain erofs rootfs
bcl marked this conversation as resolved.
Show resolved Hide resolved
)

// An AnacondaInstallerISOTree represents a tree containing the anaconda installer,
Expand All @@ -49,7 +50,8 @@ type AnacondaInstallerISOTree struct {

isoLabel string

SquashfsCompression string
RootfsCompression string
RootfsType RootfsType

OSPipeline *OS
OSTreeCommitSource *ostree.SourceSpec
Expand Down Expand Up @@ -135,8 +137,13 @@ func (p *AnacondaInstallerISOTree) getInline() []string {
return inlineData
}
func (p *AnacondaInstallerISOTree) getBuildPackages(_ Distro) []string {
packages := []string{
"squashfs-tools",
var packages []string
switch p.RootfsType {
case SquashfsExt4Rootfs, SquashfsRootfs:
packages = []string{"squashfs-tools"}
case ErofsRootfs:
packages = []string{"erofs-utils"}
default:
}

if p.OSTreeCommitSource != nil {
Expand All @@ -154,6 +161,72 @@ func (p *AnacondaInstallerISOTree) getBuildPackages(_ Distro) []string {
return packages
}

// NewSquashfsStage returns an osbuild stage configured to build
// the squashfs root filesystem for the ISO.
func (p *AnacondaInstallerISOTree) NewSquashfsStage() *osbuild.Stage {
var squashfsOptions osbuild.SquashfsStageOptions

if p.anacondaPipeline.Type == AnacondaInstallerTypePayload {
squashfsOptions = osbuild.SquashfsStageOptions{
Filename: "images/install.img",
}
} else if p.anacondaPipeline.Type == AnacondaInstallerTypeLive {
squashfsOptions = osbuild.SquashfsStageOptions{
Filename: "LiveOS/squashfs.img",
}
}

if p.RootfsCompression != "" {
squashfsOptions.Compression.Method = p.RootfsCompression
} else {
// default to xz if not specified
squashfsOptions.Compression.Method = "xz"
}

if squashfsOptions.Compression.Method == "xz" {
squashfsOptions.Compression.Options = &osbuild.FSCompressionOptions{
BCJ: osbuild.BCJOption(p.anacondaPipeline.platform.GetArch().String()),
}
}

// The iso's rootfs can either be an ext4 filesystem compressed with squashfs, or
// a squashfs of the plain directory tree
if p.RootfsType == SquashfsExt4Rootfs && p.rootfsPipeline != nil {
return osbuild.NewSquashfsStage(&squashfsOptions, p.rootfsPipeline.Name())
}
return osbuild.NewSquashfsStage(&squashfsOptions, p.anacondaPipeline.Name())
bcl marked this conversation as resolved.
Show resolved Hide resolved
}

// NewErofsStage returns an osbuild stage configured to build
// the erofs root filesystem for the ISO.
func (p *AnacondaInstallerISOTree) NewErofsStage() *osbuild.Stage {
var erofsOptions osbuild.ErofsStageOptions

if p.anacondaPipeline.Type == AnacondaInstallerTypePayload {
erofsOptions = osbuild.ErofsStageOptions{
Filename: "images/install.img",
}
} else if p.anacondaPipeline.Type == AnacondaInstallerTypeLive {
erofsOptions = osbuild.ErofsStageOptions{
Filename: "LiveOS/squashfs.img",
}
}

var compression osbuild.ErofsCompression
if p.RootfsCompression != "" {
compression.Method = p.RootfsCompression
} else {
// default to zstd if not specified
compression.Method = "zstd"
}
compression.Level = common.ToPtr(8)
erofsOptions.Compression = &compression
erofsOptions.ExtendedOptions = []string{"all-fragments", "dedupe"}
erofsOptions.ClusterSize = common.ToPtr(131072)

return osbuild.NewErofsStage(&erofsOptions, p.anacondaPipeline.Name())
}

func (p *AnacondaInstallerISOTree) serializeStart(_ []rpmmd.PackageSpec, containers []container.Spec, commits []ostree.CommitSpec, _ []rpmmd.RepoConfig) {
if p.ostreeCommitSpec != nil || p.containerSpec != nil {
panic("double call to serializeStart()")
Expand Down Expand Up @@ -261,40 +334,14 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
copyStage := osbuild.NewCopyStageSimple(copyStageOptions, copyStageInputs)
pipeline.AddStage(copyStage)

var squashfsOptions osbuild.SquashfsStageOptions

if p.anacondaPipeline.Type == AnacondaInstallerTypePayload {
squashfsOptions = osbuild.SquashfsStageOptions{
Filename: "images/install.img",
}
} else if p.anacondaPipeline.Type == AnacondaInstallerTypeLive {
squashfsOptions = osbuild.SquashfsStageOptions{
Filename: "LiveOS/squashfs.img",
}
}

if p.SquashfsCompression != "" {
squashfsOptions.Compression.Method = p.SquashfsCompression
} else {
// default to xz if not specified
squashfsOptions.Compression.Method = "xz"
}

if squashfsOptions.Compression.Method == "xz" {
squashfsOptions.Compression.Options = &osbuild.FSCompressionOptions{
BCJ: osbuild.BCJOption(p.anacondaPipeline.platform.GetArch().String()),
}
}

// 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())
// Add the selected roofs stage
switch p.RootfsType {
case SquashfsExt4Rootfs, SquashfsRootfs:
pipeline.AddStage(p.NewSquashfsStage())
case ErofsRootfs:
pipeline.AddStage(p.NewErofsStage())
default:
}
pipeline.AddStage(squashfsStage)

if p.ISOLinux {
isoLinuxOptions := &osbuild.ISOLinuxStageOptions{
Expand Down
Loading
Loading