disk: NewPartitionTable can wrap plain partitions in LVM
Add a new parameter `lvmify` to `NewPartitionTable` that, if set to `true`, will cause the root partition to be wrapped in LVM in case it is not in a LVM volume group. Set this to `false` for now so no actual change should happen anywhere. Layouts where the root is directly on a LUKS container are not yet supported. Add tests for this.
This commit is contained in:
parent
bd2849340c
commit
e57cccc3fe
8 changed files with 85 additions and 10 deletions
|
|
@ -66,7 +66,7 @@ func TestDisk_DynamicallyResizePartitionTable(t *testing.T) {
|
|||
// math/rand is good enough in this case
|
||||
/* #nosec G404 */
|
||||
rng := rand.New(rand.NewSource(0))
|
||||
newpt, err := NewPartitionTable(&pt, mountpoints, 1024, rng)
|
||||
newpt, err := NewPartitionTable(&pt, mountpoints, 1024, false, rng)
|
||||
assert.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, newpt.Size, expectedSize)
|
||||
}
|
||||
|
|
@ -358,7 +358,7 @@ func TestCreatePartitionTable(t *testing.T) {
|
|||
rng := rand.New(rand.NewSource(13))
|
||||
for name := range testPartitionTables {
|
||||
pt := testPartitionTables[name]
|
||||
mpt, err := NewPartitionTable(&pt, bp, uint64(13*1024*1024), rng)
|
||||
mpt, err := NewPartitionTable(&pt, bp, uint64(13*1024*1024), false, rng)
|
||||
assert.NoError(err, "Partition table generation failed: %s (%s)", name, err)
|
||||
assert.NotNil(mpt, "Partition table generation failed: %s (nil partition table)", name)
|
||||
assert.Greater(mpt.GetSize(), uint64(37*1024*1024*1024))
|
||||
|
|
@ -369,3 +369,33 @@ func TestCreatePartitionTable(t *testing.T) {
|
|||
assert.NotNil(mnt, "Partition table '%s': failed to find root mountable", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePartitionTableLVMify(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
// math/rand is good enough in this case
|
||||
/* #nosec G404 */
|
||||
rng := rand.New(rand.NewSource(13))
|
||||
for name := range testPartitionTables {
|
||||
pt := testPartitionTables[name]
|
||||
|
||||
if name == "btrfs" || name == "luks" {
|
||||
assert.Panics(func() {
|
||||
_, _ = NewPartitionTable(&pt, bp, uint64(13*1024*1024), true, rng)
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
mpt, err := NewPartitionTable(&pt, bp, uint64(13*1024*1024), true, rng)
|
||||
assert.NoError(err, "Partition table generation failed: %s (%s)", name, err)
|
||||
|
||||
rootPath := entityPath(mpt, "/")
|
||||
if rootPath == nil {
|
||||
panic("no root mountpoint for PartitionTable")
|
||||
}
|
||||
|
||||
parent := rootPath[1]
|
||||
_, ok := parent.(*LVMLogicalVolume)
|
||||
assert.True(ok, "Partition table '%s': root's parent (%q) is not an LVM logical volume", name, parent)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,16 @@ type PartitionTable struct {
|
|||
ExtraPadding uint64 // Extra space at the end of the partition table (sectors)
|
||||
}
|
||||
|
||||
func NewPartitionTable(basePT *PartitionTable, mountpoints []blueprint.FilesystemCustomization, imageSize uint64, rng *rand.Rand) (*PartitionTable, error) {
|
||||
func NewPartitionTable(basePT *PartitionTable, mountpoints []blueprint.FilesystemCustomization, imageSize uint64, lvmify bool, rng *rand.Rand) (*PartitionTable, error) {
|
||||
newPT := basePT.Clone().(*PartitionTable)
|
||||
for _, mnt := range mountpoints {
|
||||
size := newPT.AlignUp(clampFSSize(mnt.Mountpoint, mnt.MinSize))
|
||||
if path := entityPath(newPT, mnt.Mountpoint); len(path) != 0 {
|
||||
resizeEntityBranch(path, size)
|
||||
} else {
|
||||
if lvmify {
|
||||
newPT.ensureLVM()
|
||||
}
|
||||
if err := newPT.createFilesystem(mnt.Mountpoint, size); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -484,3 +487,45 @@ func (pt *PartitionTable) GenUUID(rng *rand.Rand) {
|
|||
pt.UUID = uuid.Must(newRandomUUIDFromReader(rng)).String()
|
||||
}
|
||||
}
|
||||
|
||||
// ensureLVM will ensure that the root partition is on an LVM volume, i.e. if
|
||||
// it currently is not, it will wrap it in one
|
||||
func (pt *PartitionTable) ensureLVM() {
|
||||
|
||||
rootPath := entityPath(pt, "/")
|
||||
if rootPath == nil {
|
||||
panic("no root mountpoint for PartitionTable")
|
||||
}
|
||||
|
||||
parent := rootPath[1] // NB: entityPath has reversed order
|
||||
|
||||
if _, ok := parent.(*LVMLogicalVolume); ok {
|
||||
return
|
||||
} else if part, ok := parent.(*Partition); ok {
|
||||
filesystem := part.Payload
|
||||
|
||||
part.Payload = &LVMVolumeGroup{
|
||||
Name: "rootvg",
|
||||
Description: "created via lvm2 and osbuild",
|
||||
LogicalVolumes: []LVMLogicalVolume{
|
||||
{
|
||||
Size: part.Size,
|
||||
Name: "rootlv",
|
||||
Payload: filesystem,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// reset it so it will be grown later
|
||||
part.Size = 0
|
||||
|
||||
if pt.Type == "gpt" {
|
||||
part.Type = LVMPartitionGUID
|
||||
} else {
|
||||
part.Type = "8e"
|
||||
}
|
||||
|
||||
} else {
|
||||
panic("unsupported parent for LVM")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ func (t *imageType) getPartitionTable(
|
|||
|
||||
imageSize := t.Size(options.Size)
|
||||
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, rng)
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, false, rng)
|
||||
}
|
||||
|
||||
func (t *imageType) PartitionType() string {
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ func (t *imageType) getPartitionTable(
|
|||
|
||||
imageSize := t.Size(options.Size)
|
||||
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, rng)
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, false, rng)
|
||||
}
|
||||
|
||||
func (t *imageType) getDefaultImageConfig() *distro.ImageConfig {
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ func (t *imageType) getPartitionTable(
|
|||
|
||||
imageSize := t.Size(options.Size)
|
||||
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, rng)
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, false, rng)
|
||||
}
|
||||
|
||||
func (t *imageType) getDefaultImageConfig() *distro.ImageConfig {
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ func (t *imageType) getPartitionTable(
|
|||
|
||||
imageSize := t.Size(options.Size)
|
||||
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, rng)
|
||||
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, false, rng)
|
||||
}
|
||||
|
||||
func (t *imageType) PartitionType() string {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func TestGenDeviceCreationStages(t *testing.T) {
|
|||
|
||||
luks_lvm := testPartitionTables["luks+lvm"]
|
||||
|
||||
pt, err := disk.NewPartitionTable(&luks_lvm, []blueprint.FilesystemCustomization{}, 0, rng)
|
||||
pt, err := disk.NewPartitionTable(&luks_lvm, []blueprint.FilesystemCustomization{}, 0, false, rng)
|
||||
assert.NoError(err)
|
||||
|
||||
stages := GenDeviceCreationStages(pt, "image.raw")
|
||||
|
|
@ -81,7 +81,7 @@ func TestGenDeviceFinishStages(t *testing.T) {
|
|||
|
||||
luks_lvm := testPartitionTables["luks+lvm"]
|
||||
|
||||
pt, err := disk.NewPartitionTable(&luks_lvm, []blueprint.FilesystemCustomization{}, 0, rng)
|
||||
pt, err := disk.NewPartitionTable(&luks_lvm, []blueprint.FilesystemCustomization{}, 0, false, rng)
|
||||
assert.NoError(err)
|
||||
|
||||
stages := GenDeviceFinishStages(pt, "image.raw")
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func TestGenImageKernelOptions(t *testing.T) {
|
|||
|
||||
luks_lvm := testPartitionTables["luks+lvm"]
|
||||
|
||||
pt, err := disk.NewPartitionTable(&luks_lvm, []blueprint.FilesystemCustomization{}, 0, rng)
|
||||
pt, err := disk.NewPartitionTable(&luks_lvm, []blueprint.FilesystemCustomization{}, 0, false, rng)
|
||||
assert.NoError(err)
|
||||
|
||||
var uuid string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue