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

Fix size calculation for containers without sizeable children [COMPOSER-2086] #293

Merged
merged 4 commits into from
Dec 1, 2023
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
51 changes: 47 additions & 4 deletions pkg/disk/disk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,9 +536,52 @@ func TestCreatePartitionTableLVMOnly(t *testing.T) {
}

// root should always be on a LVM
parent := rootPath[1]
_, ok := parent.(*LVMLogicalVolume)
assert.True(ok, "PT %q BP %q: root's parent (%q) is not an LVM logical volume", ptName, bpName, parent)
rootParent := rootPath[1]
{
_, ok := rootParent.(*LVMLogicalVolume)
assert.True(ok, "PT %q BP %q: root's parent (%+v) is not an LVM logical volume", ptName, bpName, rootParent)
}

// check logical volume sizes against blueprint
var lvsum uint64
for _, mnt := range tbp {
if mnt.Mountpoint == "/boot" {
// not on LVM; skipping
continue
}
mntPath := entityPath(mpt, mnt.Mountpoint)
mntParent := mntPath[1]
mntLV, ok := mntParent.(*LVMLogicalVolume) // the partition's parent should be the logical volume
assert.True(ok, "PT %q BP %q: %s's parent (%+v) is not an LVM logical volume", ptName, bpName, mnt.Mountpoint, mntParent)
assert.GreaterOrEqualf(mntLV.Size, mnt.MinSize, "PT %q BP %q: %s's size (%d) is smaller than the requested minsize (%d)", ptName, bpName, mnt.Mountpoint, mntLV.Size, mnt.MinSize)
lvsum += mntLV.Size
}

// root LV's parent should be the VG
lvParent := rootPath[2]
{
_, ok := lvParent.(*LVMVolumeGroup)
assert.True(ok, "PT %q BP %q: root LV's parent (%+v) is not an LVM volume group", ptName, bpName, lvParent)
}

// the root partition is the second to last entity in the path (the last is the partition table itself)
rootTop := rootPath[len(rootPath)-2]
vgPart, ok := rootTop.(*Partition)

// if the VG is in a LUKS container, check that there's enough space for the header too
{
vgParent := rootPath[3]
luksContainer, ok := vgParent.(*LUKSContainer)
if ok {
// this isn't the lvsum anymore, but the lvsum + the luks
// header, which should regardless be equal to or smaller
// than the partition
lvsum += luksContainer.MetadataSize()
}
}

assert.True(ok, "PT %q BP %q: root VG top level entity (%+v) is not a partition", ptName, bpName, rootTop)
assert.GreaterOrEqualf(vgPart.Size, lvsum, "PT %q BP %q: VG partition's size (%d) is smaller than the sum of logical volumes (%d)", ptName, bpName, vgPart.Size, lvsum)
}
}
}
Expand Down Expand Up @@ -975,7 +1018,7 @@ func TestEnsureDirectorySizes(t *testing.T) {
rootVG := rootLUKS.Payload.(*LVMVolumeGroup)
rootLV := rootVG.LogicalVolumes[0]
homeLV := rootVG.LogicalVolumes[1]
assert.Equal(uint64(17*GiB)+rootVG.MetadataSize(), rootPart.Size)
assert.Equal(uint64(17*GiB)+rootVG.MetadataSize()+rootLUKS.MetadataSize(), rootPart.Size)
assert.Equal(uint64(7*GiB), rootLV.Size)
assert.Equal(uint64(10*GiB), homeLV.Size)

Expand Down
16 changes: 14 additions & 2 deletions pkg/disk/partition_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ func (pt *PartitionTable) applyCustomization(mountpoints []blueprint.FilesystemC

// Dynamically calculate and update the start point for each of the existing
// partitions. Adjusts the overall size of image to either the supplied
// value in `size` or to the sum of all partitions if that is lager.
// value in `size` or to the sum of all partitions if that is larger.
// Will grow the root partition if there is any empty space.
// Returns the updated start point.
func (pt *PartitionTable) relayout(size uint64) uint64 {
Expand All @@ -406,6 +406,8 @@ func (pt *PartitionTable) relayout(size uint64) uint64 {
for idx := range pt.Partitions {
partition := &pt.Partitions[idx]
if len(entityPath(partition, "/")) != 0 {
// keep the root partition index to handle after all the other
// partitions have been moved and resized
rootIdx = idx
continue
}
Expand Down Expand Up @@ -586,6 +588,13 @@ func resizeEntityBranch(path []Entity, size uint64) {
break
}
}
// If containerSize is 0, it means it doesn't have any direct sizeable
// children (e.g., a LUKS container with a VG child). In that case,
// set the containerSize to the desired size for the branch before
// adding any metadata.
if containerSize == 0 {
containerSize = size
}
if vc, ok := element.(VolumeContainer); ok {
containerSize += vc.MetadataSize()
}
Expand Down Expand Up @@ -642,14 +651,17 @@ func (pt *PartitionTable) ensureLVM() error {
Description: "created via lvm2 and osbuild",
}

// create root logical volume on the new volume group with the same
// size and filesystem as the previous root partition
_, err := vg.CreateLogicalVolume("root", part.Size, filesystem)
if err != nil {
panic(fmt.Sprintf("Could not create LV: %v", err))
}

// replace the top-level partition payload with the new volume group
part.Payload = vg

// reset it so it will be grown later
// reset the vg partition size - it will be grown later
part.Size = 0

if pt.Type == "gpt" {
Expand Down
Loading