osbuild2: new GenDeviceFinishStages method

This should be called at the end of the pipeline that creates an
image, to add stages that are needed to finish up the image.
Currently the only stage that will be added is the `lvm2.metadata`
stage in the case the partition layout contains LVM2.

Co-Authored-By: Achilleas Koutsou <achilleas@koutsou.net>
This commit is contained in:
Christian Kellner 2022-02-11 11:55:34 +00:00 committed by Tom Gundersen
parent 3c6e34aeb3
commit 670b936e6b
2 changed files with 74 additions and 0 deletions

View file

@ -85,6 +85,37 @@ func GenDeviceCreationStages(pt *disk.PartitionTable, filename string) []*Stage
return stages
}
func GenDeviceFinishStages(pt *disk.PartitionTable, filename string) []*Stage {
stages := make([]*Stage, 0)
genStages := func(e disk.Entity, path []disk.Entity) error {
switch ent := e.(type) {
case *disk.LVMVolumeGroup:
// do not include us when getting the devices
stageDevices, lastName := getDevices(path[:len(path)-1], filename)
// "org.osbuild.lvm2.metadata" expects a "device" to rename the VG,
// thus rename the last device to "device"
lastDevice := stageDevices[lastName]
delete(stageDevices, lastName)
stageDevices["device"] = lastDevice
stage := NewLVM2MetadataStage(
&LVM2MetadataStageOptions{
VGName: ent.Name,
}, stageDevices)
stages = append(stages, stage)
}
return nil
}
_ = pt.ForEachEntity(genStages)
return stages
}
func deviceName(p disk.Entity) string {
if p == nil {
panic("device is nil; this is a programming error")

View file

@ -71,3 +71,46 @@ func TestGenDeviceCreationStages(t *testing.T) {
assert.Equal(parent.Type, "org.osbuild.loopback")
}
func TestGenDeviceFinishStages(t *testing.T) {
assert := assert.New(t)
// math/rand is good enough in this case
/* #nosec G404 */
rng := rand.New(rand.NewSource(13))
luks_lvm := testPartitionTables["luks+lvm"]
pt, err := disk.NewPartitionTable(&luks_lvm, []blueprint.FilesystemCustomization{}, 0, rng)
assert.NoError(err)
stages := GenDeviceFinishStages(pt, "image.raw")
// we should have one stage
assert.Equal(1, len(stages))
// it should be a "org.osbuild.lvm2.metadata"
lvm := stages[0]
assert.Equal("org.osbuild.lvm2.metadata", lvm.Type)
// it should have two devices
assert.Equal(2, len(lvm.Devices))
// this is the target one, which should be the luks one
device, ok := lvm.Devices["device"]
assert.True(ok, "Need device called `device`")
assert.Equal("org.osbuild.luks2", device.Type)
assert.NotEmpty(device.Parent, "Need a parent device for LUKS on loopback")
luksOptions, ok := device.Options.(*LUKS2DeviceOptions)
assert.True(ok, "Need LUKS2DeviceOptions for luks device")
assert.Equal("osbuild", luksOptions.Passphrase)
parent, ok := lvm.Devices[device.Parent]
assert.True(ok, "Need device called `device`")
assert.Equal("org.osbuild.loopback", parent.Type)
opts, ok := lvm.Options.(*LVM2MetadataStageOptions)
assert.True(ok, "Need LVM2MetadataStageOptions for org.osbuild.lvm2.metadata")
assert.Equal("root", opts.VGName)
}