cloudapi: Disk customization conversion

Convert from cloudapi Disk customizations to the blueprint types.
This commit is contained in:
Achilleas Koutsou 2025-03-17 17:45:46 +01:00 committed by Sanne Raymaekers
parent fe19c87dd9
commit 82ac185e7c
2 changed files with 283 additions and 0 deletions

View file

@ -495,6 +495,12 @@ func (rbp *Blueprint) GetCustomizationsFromBlueprintRequest() (*blueprint.Custom
c.RHSM = bpRhsm
}
disk, err := convertDiskCustomizations(rbpc.Disk)
if err != nil {
return nil, err
}
c.Disk = disk
return c, nil
}
@ -1053,6 +1059,12 @@ func (request *ComposeRequest) GetBlueprintFromCustomizations() (blueprint.Bluep
}
bp.Customizations.RHSM = bpRhsm
}
bp.Customizations.Disk, err = convertDiskCustomizations(request.Customizations.Disk)
if err != nil {
return bp, err
}
if cacerts := request.Customizations.Cacerts; cacerts != nil {
@ -1276,3 +1288,93 @@ func (request *ComposeRequest) GetImageRequests(distroFactory *distrofactory.Fac
}
return irs, nil
}
func convertDiskCustomizations(disk *Disk) (*blueprint.DiskCustomization, error) {
if disk == nil {
return nil, nil
}
bpDisk := &blueprint.DiskCustomization{
MinSize: common.DerefOrDefault(disk.Minsize),
Type: string(common.DerefOrDefault(disk.Type)),
}
for idx, partition := range disk.Partitions {
// partition successfully converts to all three types, so convert to
// filesystem to sniff the type string
sniffer, err := partition.AsFilesystemTyped()
if err != nil {
return nil, fmt.Errorf("failed to deserialize disk customization partition %d", idx)
}
var bpPartition blueprint.PartitionCustomization
switch partType := common.DerefOrDefault(sniffer.Type); string(partType) {
case string(Plain):
fs, err := partition.AsFilesystemTyped()
if err != nil {
return nil, fmt.Errorf("failed to deserialize disk customization partition %d with type %q", idx, partType)
}
bpPartition = blueprint.PartitionCustomization{
Type: string(common.DerefOrDefault(fs.Type)),
PartType: common.DerefOrDefault(fs.PartType),
MinSize: common.DerefOrDefault(fs.Minsize),
FilesystemTypedCustomization: blueprint.FilesystemTypedCustomization{
Mountpoint: fs.Mountpoint,
Label: common.DerefOrDefault(fs.Label),
FSType: string(common.DerefOrDefault(fs.FsType)),
},
}
case string(Btrfs):
btrfsVol, err := partition.AsBtrfsVolume()
if err != nil {
return nil, fmt.Errorf("failed to deserialize disk customization partition %d with type %q", idx, partType)
}
bpPartition = blueprint.PartitionCustomization{
Type: string(common.DerefOrDefault(btrfsVol.Type)),
PartType: common.DerefOrDefault(btrfsVol.PartType),
MinSize: common.DerefOrDefault(btrfsVol.Minsize),
}
for _, subvol := range btrfsVol.Subvolumes {
bpSubvol := blueprint.BtrfsSubvolumeCustomization{
Name: subvol.Name,
Mountpoint: subvol.Mountpoint,
}
bpPartition.Subvolumes = append(bpPartition.Subvolumes, bpSubvol)
}
case string(Lvm):
vg, err := partition.AsVolumeGroup()
if err != nil {
return nil, fmt.Errorf("failed to deserialize disk customization partition %d with type %q", idx, partType)
}
bpPartition = blueprint.PartitionCustomization{
Type: string(common.DerefOrDefault(vg.Type)),
PartType: common.DerefOrDefault(vg.PartType),
MinSize: common.DerefOrDefault(vg.Minsize),
VGCustomization: blueprint.VGCustomization{
Name: common.DerefOrDefault(vg.Name),
},
}
for _, lv := range vg.LogicalVolumes {
bpLV := blueprint.LVCustomization{
Name: common.DerefOrDefault(lv.Name),
MinSize: common.DerefOrDefault(lv.Minsize),
FilesystemTypedCustomization: blueprint.FilesystemTypedCustomization{
Mountpoint: lv.Mountpoint,
Label: common.DerefOrDefault(lv.Label),
FSType: string(common.DerefOrDefault(lv.FsType)),
},
}
bpPartition.LogicalVolumes = append(bpPartition.LogicalVolumes, bpLV)
}
default:
return nil, fmt.Errorf("disk customization partition %d has invalid or unknown type %q", idx, partType)
}
bpDisk.Partitions = append(bpDisk.Partitions, bpPartition)
}
return bpDisk, nil
}

View file

@ -6,6 +6,7 @@ import (
repos "github.com/osbuild/images/data/repositories"
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distrofactory"
"github.com/osbuild/images/pkg/reporegistry"
@ -177,6 +178,60 @@ func GetTestBlueprint() blueprint.Blueprint {
},
},
},
Disk: &blueprint.DiskCustomization{
MinSize: 10,
Partitions: []blueprint.PartitionCustomization{
{
Type: "plain",
FilesystemTypedCustomization: blueprint.FilesystemTypedCustomization{
FSType: "xfs",
Label: "data",
Mountpoint: "/data",
},
},
{
Type: "btrfs",
MinSize: 100 * datasizes.MiB,
BtrfsVolumeCustomization: blueprint.BtrfsVolumeCustomization{
Subvolumes: []blueprint.BtrfsSubvolumeCustomization{
{
Name: "+subvols/db1",
Mountpoint: "/data/db1",
},
{
Name: "+subvols/db2",
Mountpoint: "/data/db2",
},
},
},
},
{
Type: "lvm",
MinSize: 10 * datasizes.GiB,
PartType: "E6D6D379-F507-44C2-A23C-238F2A3DF928",
VGCustomization: blueprint.VGCustomization{
Name: "vg000001",
LogicalVolumes: []blueprint.LVCustomization{
{
Name: "rootlv",
FilesystemTypedCustomization: blueprint.FilesystemTypedCustomization{
Mountpoint: "/",
FSType: "ext4",
},
},
{
Name: "homelv",
MinSize: 3 * datasizes.GiB,
FilesystemTypedCustomization: blueprint.FilesystemTypedCustomization{
Mountpoint: "/home",
Label: "home",
},
},
},
},
},
},
},
}
return expected
@ -210,6 +265,61 @@ func TestGetBlueprintFromCustomizations(t *testing.T) {
var fileGroup File_Group
require.NoError(t, fileGroup.FromFileGroup0("root"))
var plainPart Partition
require.NoError(t, plainPart.FromFilesystemTyped(
FilesystemTyped{
Type: common.ToPtr(Plain),
Minsize: nil,
FsType: common.ToPtr(FilesystemTypedFsTypeXfs),
Label: common.ToPtr("data"),
Mountpoint: "/data",
},
))
var btrfsPart Partition
require.NoError(t, btrfsPart.FromBtrfsVolume(
BtrfsVolume{
Type: common.ToPtr(Btrfs),
Minsize: common.ToPtr(uint64(100 * datasizes.MiB)),
Subvolumes: []BtrfsSubvolume{
{
Mountpoint: "/data/db1",
Name: "+subvols/db1",
},
{
Mountpoint: "/data/db2",
Name: "+subvols/db2",
},
},
},
))
var vgPart Partition
require.NoError(t, vgPart.FromVolumeGroup(
VolumeGroup{
Type: common.ToPtr(Lvm),
Minsize: common.ToPtr(uint64(10 * datasizes.GiB)),
Name: common.ToPtr("vg000001"),
PartType: common.ToPtr("E6D6D379-F507-44C2-A23C-238F2A3DF928"),
LogicalVolumes: []LogicalVolume{
{
FsType: common.ToPtr(LogicalVolumeFsTypeExt4),
Label: nil,
Minsize: nil,
Mountpoint: "/",
Name: common.ToPtr("rootlv"),
},
{
FsType: nil,
Label: common.ToPtr("home"),
Minsize: common.ToPtr(uint64(3) * datasizes.GiB),
Mountpoint: "/home",
Name: common.ToPtr("homelv"),
},
},
},
))
// Construct the compose request with customizations
cr = ComposeRequest{Customizations: &Customizations{
Users: &[]User{
@ -340,6 +450,14 @@ func TestGetBlueprintFromCustomizations(t *testing.T) {
},
},
},
Disk: &Disk{
Minsize: common.ToPtr(uint64(10)),
Partitions: []Partition{
plainPart,
btrfsPart,
vgPart,
},
},
}}
bp, err = cr.GetBlueprintFromCustomizations()
@ -394,6 +512,61 @@ func TestGetBlueprintFromCompose(t *testing.T) {
var fileGroup BlueprintFile_Group
require.NoError(t, fileGroup.FromBlueprintFileGroup0("root"))
var plainPart Partition
require.NoError(t, plainPart.FromFilesystemTyped(
FilesystemTyped{
Type: common.ToPtr(Plain),
Minsize: nil,
FsType: common.ToPtr(FilesystemTypedFsTypeXfs),
Label: common.ToPtr("data"),
Mountpoint: "/data",
},
))
var btrfsPart Partition
require.NoError(t, btrfsPart.FromBtrfsVolume(
BtrfsVolume{
Type: common.ToPtr(Btrfs),
Minsize: common.ToPtr(uint64(100 * datasizes.MiB)),
Subvolumes: []BtrfsSubvolume{
{
Mountpoint: "/data/db1",
Name: "+subvols/db1",
},
{
Mountpoint: "/data/db2",
Name: "+subvols/db2",
},
},
},
))
var vgPart Partition
require.NoError(t, vgPart.FromVolumeGroup(
VolumeGroup{
Type: common.ToPtr(Lvm),
Minsize: common.ToPtr(uint64(10 * datasizes.GiB)),
Name: common.ToPtr("vg000001"),
PartType: common.ToPtr("E6D6D379-F507-44C2-A23C-238F2A3DF928"),
LogicalVolumes: []LogicalVolume{
{
FsType: common.ToPtr(LogicalVolumeFsTypeExt4),
Label: nil,
Minsize: nil,
Mountpoint: "/",
Name: common.ToPtr("rootlv"),
},
{
FsType: nil,
Label: common.ToPtr("home"),
Minsize: common.ToPtr(uint64(3) * datasizes.GiB),
Mountpoint: "/home",
Name: common.ToPtr("homelv"),
},
},
},
))
// Construct the compose request with a blueprint
cr = ComposeRequest{Blueprint: &Blueprint{
Name: "empty blueprint",
@ -526,6 +699,14 @@ func TestGetBlueprintFromCompose(t *testing.T) {
},
},
},
Disk: &Disk{
Minsize: common.ToPtr(uint64(10)),
Partitions: []Partition{
plainPart,
btrfsPart,
vgPart,
},
},
},
}}