osbuild2: deduplicate copyFSTreeOptions() function

Use a single GenCopyFSTreeOptions() function from osbuild2 instead of
implementing it multiple times in distros.

Co-Authored-By: Christian Kellner <christian@kellner.me>
This commit is contained in:
Achilleas Koutsou 2022-02-08 21:01:25 +01:00 committed by Tom Gundersen
parent 86118960b9
commit b871a77f09
9 changed files with 87 additions and 299 deletions

View file

@ -978,7 +978,7 @@ func simplifiedInstallerBootISOTreePipeline(archivePipelineName, kver string) *o
inputName := "root-tree"
copyInputs := osbuild.NewCopyStagePipelineTreeInputs(inputName, "efiboot-tree")
copyOptions, copyDevices, copyMounts := copyFSTreeOptions(inputName, "efiboot-tree", &pt, loopback)
copyOptions, copyDevices, copyMounts := osbuild.GenCopyFSTreeOptions(inputName, "efiboot-tree", &pt, loopback)
p.AddStage(osbuild.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
inputName = "coi"
@ -1232,7 +1232,7 @@ func liveImagePipeline(inputPipelineName string, outputFilename string, pt *disk
}
inputName := "root-tree"
copyOptions, copyDevices, copyMounts := copyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyOptions, copyDevices, copyMounts := osbuild.GenCopyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyInputs := osbuild.NewCopyStagePipelineTreeInputs(inputName, inputPipelineName)
p.AddStage(osbuild.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
p.AddStage(bootloaderInstStage(outputFilename, pt, arch, kernelVer, copyDevices, copyMounts, loopback))

View file

@ -4,7 +4,6 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"github.com/google/uuid"
@ -390,78 +389,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
// copyFSTreeOptions creates the options, inputs, devices, and mounts properties
// for an org.osbuild.copy stage for a given source tree using a partition
// table description to define the mounts
func copyFSTreeOptions(inputName, inputPipeline string, pt *disk.PartitionTable, device *osbuild.Device) (
*osbuild.CopyStageOptions,
*osbuild.Devices,
*osbuild.Mounts,
) {
// assume loopback device for simplicity since it's the only one currently supported
// panic if the conversion fails
devOptions, ok := device.Options.(*osbuild.LoopbackDeviceOptions)
if !ok {
panic("copyStageOptions: failed to convert device options to loopback options")
}
devices := make(map[string]osbuild.Device, len(pt.Partitions))
mounts := make([]osbuild.Mount, 0, len(pt.Partitions))
for _, p := range pt.Partitions {
if p.Payload == nil {
// no filesystem for partition (e.g., BIOS boot)
continue
}
name := filepath.Base(p.Payload.Mountpoint)
if name == "/" {
name = "root"
}
devices[name] = *osbuild.NewLoopbackDevice(
&osbuild.LoopbackDeviceOptions{
Filename: devOptions.Filename,
Start: pt.BytesToSectors(p.Start),
Size: pt.BytesToSectors(p.Size),
},
)
var mount *osbuild.Mount
switch p.Payload.Type {
case "xfs":
mount = osbuild.NewXfsMount(name, name, p.Payload.Mountpoint)
case "vfat":
mount = osbuild.NewFATMount(name, name, p.Payload.Mountpoint)
case "ext4":
mount = osbuild.NewExt4Mount(name, name, p.Payload.Mountpoint)
case "btrfs":
mount = osbuild.NewBtrfsMount(name, name, p.Payload.Mountpoint)
default:
panic("unknown fs type " + p.Type)
}
mounts = append(mounts, *mount)
}
// sort the mounts, using < should just work because:
// - a parent directory should be always before its children:
// / < /boot
// - the order of siblings doesn't matter
sort.Slice(mounts, func(i, j int) bool {
return mounts[i].Target < mounts[j].Target
})
stageMounts := osbuild.Mounts(mounts)
stageDevices := osbuild.Devices(devices)
options := osbuild.CopyStageOptions{
Paths: []osbuild.CopyStagePath{
{
From: fmt.Sprintf("input://%s/", inputName),
To: "mount://root/",
},
},
}
return &options, &stageDevices, &stageMounts
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -716,7 +716,7 @@ func simplifiedInstallerBootISOTreePipeline(archivePipelineName, kver string) *o
inputName := "root-tree"
copyInputs := osbuild.NewCopyStagePipelineTreeInputs(inputName, "efiboot-tree")
copyOptions, copyDevices, copyMounts := copyFSTreeOptions(inputName, "efiboot-tree", &pt, loopback)
copyOptions, copyDevices, copyMounts := osbuild.GenCopyFSTreeOptions(inputName, "efiboot-tree", &pt, loopback)
p.AddStage(osbuild.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
inputName = "coi"
@ -956,7 +956,7 @@ func liveImagePipeline(inputPipelineName string, outputFilename string, pt *disk
}
inputName := "root-tree"
copyOptions, copyDevices, copyMounts := copyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyOptions, copyDevices, copyMounts := osbuild.GenCopyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyInputs := osbuild.NewCopyStagePipelineTreeInputs(inputName, inputPipelineName)
p.AddStage(osbuild.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
p.AddStage(bootloaderInstStage(outputFilename, pt, arch, kernelVer, copyDevices, copyMounts, loopback))

View file

@ -4,7 +4,6 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"github.com/google/uuid"
@ -431,78 +430,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
// copyFSTreeOptions creates the options, inputs, devices, and mounts properties
// for an org.osbuild.copy stage for a given source tree using a partition
// table description to define the mounts
func copyFSTreeOptions(inputName, inputPipeline string, pt *disk.PartitionTable, device *osbuild.Device) (
*osbuild.CopyStageOptions,
*osbuild.Devices,
*osbuild.Mounts,
) {
// assume loopback device for simplicity since it's the only one currently supported
// panic if the conversion fails
devOptions, ok := device.Options.(*osbuild.LoopbackDeviceOptions)
if !ok {
panic("copyStageOptions: failed to convert device options to loopback options")
}
devices := make(map[string]osbuild.Device, len(pt.Partitions))
mounts := make([]osbuild.Mount, 0, len(pt.Partitions))
for _, p := range pt.Partitions {
if p.Payload == nil {
// no filesystem for partition (e.g., BIOS boot)
continue
}
name := filepath.Base(p.Payload.Mountpoint)
if name == "/" {
name = "root"
}
devices[name] = *osbuild.NewLoopbackDevice(
&osbuild.LoopbackDeviceOptions{
Filename: devOptions.Filename,
Start: pt.BytesToSectors(p.Start),
Size: pt.BytesToSectors(p.Size),
},
)
var mount *osbuild.Mount
switch p.Payload.Type {
case "xfs":
mount = osbuild.NewXfsMount(name, name, p.Payload.Mountpoint)
case "vfat":
mount = osbuild.NewFATMount(name, name, p.Payload.Mountpoint)
case "ext4":
mount = osbuild.NewExt4Mount(name, name, p.Payload.Mountpoint)
case "btrfs":
mount = osbuild.NewBtrfsMount(name, name, p.Payload.Mountpoint)
default:
panic("unknown fs type " + p.Type)
}
mounts = append(mounts, *mount)
}
// sort the mounts, using < should just work because:
// - a parent directory should be always before its children:
// / < /boot
// - the order of siblings doesn't matter
sort.Slice(mounts, func(i, j int) bool {
return mounts[i].Target < mounts[j].Target
})
stageMounts := osbuild.Mounts(mounts)
stageDevices := osbuild.Devices(devices)
options := osbuild.CopyStageOptions{
Paths: []osbuild.CopyStagePath{
{
From: fmt.Sprintf("input://%s/", inputName),
To: "mount://root/",
},
},
}
return &options, &stageDevices, &stageMounts
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -712,7 +712,7 @@ func simplifiedInstallerBootISOTreePipeline(archivePipelineName, kver string, rn
inputName := "root-tree"
copyInputs := osbuild.NewCopyStagePipelineTreeInputs(inputName, "efiboot-tree")
copyOptions, copyDevices, copyMounts := copyFSTreeOptions(inputName, "efiboot-tree", &pt, loopback)
copyOptions, copyDevices, copyMounts := osbuild.GenCopyFSTreeOptions(inputName, "efiboot-tree", &pt, loopback)
p.AddStage(osbuild.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
inputName = "coi"
@ -952,7 +952,7 @@ func liveImagePipeline(inputPipelineName string, outputFilename string, pt *disk
}
inputName := "root-tree"
copyOptions, copyDevices, copyMounts := copyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyOptions, copyDevices, copyMounts := osbuild.GenCopyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyInputs := osbuild.NewCopyStagePipelineTreeInputs(inputName, inputPipelineName)
p.AddStage(osbuild.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
p.AddStage(bootloaderInstStage(outputFilename, pt, arch, kernelVer, copyDevices, copyMounts, loopback))

View file

@ -4,7 +4,6 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"github.com/google/uuid"
@ -432,78 +431,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
// copyFSTreeOptions creates the options, inputs, devices, and mounts properties
// for an org.osbuild.copy stage for a given source tree using a partition
// table description to define the mounts
func copyFSTreeOptions(inputName, inputPipeline string, pt *disk.PartitionTable, device *osbuild.Device) (
*osbuild.CopyStageOptions,
*osbuild.Devices,
*osbuild.Mounts,
) {
// assume loopback device for simplicity since it's the only one currently supported
// panic if the conversion fails
devOptions, ok := device.Options.(*osbuild.LoopbackDeviceOptions)
if !ok {
panic("copyStageOptions: failed to convert device options to loopback options")
}
devices := make(map[string]osbuild.Device, len(pt.Partitions))
mounts := make([]osbuild.Mount, 0, len(pt.Partitions))
for _, p := range pt.Partitions {
if p.Payload == nil {
// no filesystem for partition (e.g., BIOS boot)
continue
}
name := filepath.Base(p.Payload.Mountpoint)
if name == "/" {
name = "root"
}
devices[name] = *osbuild.NewLoopbackDevice(
&osbuild.LoopbackDeviceOptions{
Filename: devOptions.Filename,
Start: pt.BytesToSectors(p.Start),
Size: pt.BytesToSectors(p.Size),
},
)
var mount *osbuild.Mount
switch p.Payload.Type {
case "xfs":
mount = osbuild.NewXfsMount(name, name, p.Payload.Mountpoint)
case "vfat":
mount = osbuild.NewFATMount(name, name, p.Payload.Mountpoint)
case "ext4":
mount = osbuild.NewExt4Mount(name, name, p.Payload.Mountpoint)
case "btrfs":
mount = osbuild.NewBtrfsMount(name, name, p.Payload.Mountpoint)
default:
panic("unknown fs type " + p.Type)
}
mounts = append(mounts, *mount)
}
// sort the mounts, using < should just work because:
// - a parent directory should be always before its children:
// / < /boot
// - the order of siblings doesn't matter
sort.Slice(mounts, func(i, j int) bool {
return mounts[i].Target < mounts[j].Target
})
stageMounts := osbuild.Mounts(mounts)
stageDevices := osbuild.Devices(devices)
options := osbuild.CopyStageOptions{
Paths: []osbuild.CopyStagePath{
{
From: fmt.Sprintf("input://%s/", inputName),
To: "mount://root/",
},
},
}
return &options, &stageDevices, &stageMounts
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -1043,7 +1043,7 @@ func liveImagePipeline(inputPipelineName string, outputFilename string, pt *disk
}
inputName := "root-tree"
copyOptions, copyDevices, copyMounts := copyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyOptions, copyDevices, copyMounts := osbuild.GenCopyFSTreeOptions(inputName, inputPipelineName, pt, loopback)
copyInputs := osbuild.NewCopyStagePipelineTreeInputs(inputName, inputPipelineName)
p.AddStage(osbuild.NewCopyStage(copyOptions, copyInputs, copyDevices, copyMounts))
p.AddStage(bootloaderInstStage(outputFilename, pt, arch, kernelVer, copyDevices, copyMounts, loopback))

View file

@ -3,7 +3,6 @@ package rhel90beta
import (
"fmt"
"path/filepath"
"sort"
"github.com/google/uuid"
@ -369,78 +368,6 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *osbuild.SfdiskStageOptions {
return stageOptions
}
// copyFSTreeOptions creates the options, inputs, devices, and mounts properties
// for an org.osbuild.copy stage for a given source tree using a partition
// table description to define the mounts
func copyFSTreeOptions(inputName, inputPipeline string, pt *disk.PartitionTable, device *osbuild.Device) (
*osbuild.CopyStageOptions,
*osbuild.Devices,
*osbuild.Mounts,
) {
// assume loopback device for simplicity since it's the only one currently supported
// panic if the conversion fails
devOptions, ok := device.Options.(*osbuild.LoopbackDeviceOptions)
if !ok {
panic("copyStageOptions: failed to convert device options to loopback options")
}
devices := make(map[string]osbuild.Device, len(pt.Partitions))
mounts := make([]osbuild.Mount, 0, len(pt.Partitions))
for _, p := range pt.Partitions {
if p.Payload == nil {
// no filesystem for partition (e.g., BIOS boot)
continue
}
name := filepath.Base(p.Payload.Mountpoint)
if name == "/" {
name = "root"
}
devices[name] = *osbuild.NewLoopbackDevice(
&osbuild.LoopbackDeviceOptions{
Filename: devOptions.Filename,
Start: pt.BytesToSectors(p.Start),
Size: pt.BytesToSectors(p.Size),
},
)
var mount *osbuild.Mount
switch p.Payload.Type {
case "xfs":
mount = osbuild.NewXfsMount(name, name, p.Payload.Mountpoint)
case "vfat":
mount = osbuild.NewFATMount(name, name, p.Payload.Mountpoint)
case "ext4":
mount = osbuild.NewExt4Mount(name, name, p.Payload.Mountpoint)
case "btrfs":
mount = osbuild.NewBtrfsMount(name, name, p.Payload.Mountpoint)
default:
panic("unknown fs type " + p.Type)
}
mounts = append(mounts, *mount)
}
// sort the mounts, using < should just work because:
// - a parent directory should be always before its children:
// / < /boot
// - the order of siblings doesn't matter
sort.Slice(mounts, func(i, j int) bool {
return mounts[i].Target < mounts[j].Target
})
stageMounts := osbuild.Mounts(mounts)
stageDevices := osbuild.Devices(devices)
options := osbuild.CopyStageOptions{
Paths: []osbuild.CopyStagePath{
{
From: fmt.Sprintf("input://%s/", inputName),
To: "mount://root/",
},
},
}
return &options, &stageDevices, &stageMounts
}
func grub2InstStageOptions(filename string, pt *disk.PartitionTable, platform string) *osbuild.Grub2InstStageOptions {
bootPartIndex := pt.BootPartitionIndex()
if bootPartIndex == -1 {

View file

@ -1,5 +1,13 @@
package osbuild2
import (
"fmt"
"path/filepath"
"sort"
"github.com/osbuild/osbuild-composer/internal/disk"
)
// Stage to copy items from inputs to mount points or the tree. Multiple items
// can be copied. The source and destination is a URL.
@ -66,3 +74,75 @@ func NewCopyStagePipelineTreeInputs(inputName, inputPipeline string) *CopyStageI
treeInput.References = []string{"name:" + inputPipeline}
return &CopyStageInputs{inputName: treeInput}
}
// GenCopyFSTreeOptions creates the options, inputs, devices, and mounts properties
// for an org.osbuild.copy stage for a given source tree using a partition
// table description to define the mounts
func GenCopyFSTreeOptions(inputName, inputPipeline string, pt *disk.PartitionTable, device *Device) (
*CopyStageOptions,
*Devices,
*Mounts,
) {
// assume loopback device for simplicity since it's the only one currently supported
// panic if the conversion fails
devOptions, ok := device.Options.(*LoopbackDeviceOptions)
if !ok {
panic("GenCopyStageOptions: failed to convert device options to loopback options")
}
devices := make(map[string]Device, len(pt.Partitions))
mounts := make([]Mount, 0, len(pt.Partitions))
for _, p := range pt.Partitions {
if p.Payload == nil {
// no filesystem for partition (e.g., BIOS boot)
continue
}
name := filepath.Base(p.Payload.Mountpoint)
if name == "/" {
name = "root"
}
devices[name] = *NewLoopbackDevice(
&LoopbackDeviceOptions{
Filename: devOptions.Filename,
Start: pt.BytesToSectors(p.Start),
Size: pt.BytesToSectors(p.Size),
},
)
var mount *Mount
switch p.Payload.Type {
case "xfs":
mount = NewXfsMount(name, name, p.Payload.Mountpoint)
case "vfat":
mount = NewFATMount(name, name, p.Payload.Mountpoint)
case "ext4":
mount = NewExt4Mount(name, name, p.Payload.Mountpoint)
case "btrfs":
mount = NewBtrfsMount(name, name, p.Payload.Mountpoint)
default:
panic("unknown fs type " + p.Type)
}
mounts = append(mounts, *mount)
}
// sort the mounts, using < should just work because:
// - a parent directory should be always before its children:
// / < /boot
// - the order of siblings doesn't matter
sort.Slice(mounts, func(i, j int) bool {
return mounts[i].Target < mounts[j].Target
})
stageMounts := Mounts(mounts)
stageDevices := Devices(devices)
options := CopyStageOptions{
Paths: []CopyStagePath{
{
From: fmt.Sprintf("input://%s/", inputName),
To: "mount://root/",
},
},
}
return &options, &stageDevices, &stageMounts
}