diff --git a/internal/disk/partition_table.go b/internal/disk/partition_table.go index aa1385f1f..339d608c3 100644 --- a/internal/disk/partition_table.go +++ b/internal/disk/partition_table.go @@ -26,7 +26,10 @@ func NewPartitionTable(basePT *PartitionTable, mountpoints []blueprint.Filesyste resizeEntityBranch(path, size) } else { if lvmify { - newPT.ensureLVM() + err := newPT.ensureLVM() + if err != nil { + return nil, err + } } if err := newPT.createFilesystem(mnt.Mountpoint, size); err != nil { return nil, err @@ -458,17 +461,24 @@ func (pt *PartitionTable) GenUUID(rng *rand.Rand) { // 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() { +func (pt *PartitionTable) ensureLVM() error { rootPath := entityPath(pt, "/") if rootPath == nil { panic("no root mountpoint for PartitionTable") } + // we need a /boot partition to boot LVM, ensure one exists + bootPath := entityPath(pt, "/boot") + if bootPath == nil { + _, err := pt.CreateMountpoint("/boot", 512*1024*1024) + return err + } + parent := rootPath[1] // NB: entityPath has reversed order if _, ok := parent.(*LVMLogicalVolume); ok { - return + return nil } else if part, ok := parent.(*Partition); ok { filesystem := part.Payload @@ -496,4 +506,6 @@ func (pt *PartitionTable) ensureLVM() { } else { panic("unsupported parent for LVM") } + + return nil } diff --git a/internal/distro/rhel86/distro.go b/internal/distro/rhel86/distro.go index 82c9e30ee..2271e349f 100644 --- a/internal/distro/rhel86/distro.go +++ b/internal/distro/rhel86/distro.go @@ -331,6 +331,24 @@ func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.Package bpPackages = append(bpPackages, "chrony") } + // if we have file system customization that will need to a new mount point + // the layout is converted to LVM so we need to corresponding packages + if !t.rpmOstree { + archName := t.arch.Name() + pt := t.basePartitionTables[archName] + haveNewMountpoint := false + + if fs := bp.Customizations.GetFilesystems(); fs != nil { + for i := 0; !haveNewMountpoint && i < len(fs); i++ { + haveNewMountpoint = !pt.ContainsMountpoint(fs[i].Mountpoint) + } + } + + if haveNewMountpoint { + bpPackages = append(bpPackages, "lvm2") + } + } + // depsolve bp packages separately // bp packages aren't restricted by exclude lists mergedSets[blueprintPkgsKey] = rpmmd.PackageSet{Include: bpPackages} @@ -394,7 +412,9 @@ func (t *imageType) getPartitionTable( imageSize := t.Size(options.Size) - return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, false, rng) + lvmify := !t.rpmOstree + + return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, lvmify, rng) } func (t *imageType) getDefaultImageConfig() *distro.ImageConfig { diff --git a/internal/distro/rhel86/distro_test.go b/internal/distro/rhel86/distro_test.go index e9a1a45c3..1f0032e3d 100644 --- a/internal/distro/rhel86/distro_test.go +++ b/internal/distro/rhel86/distro_test.go @@ -704,13 +704,10 @@ func TestDistro_MountpointsWithArbitraryDepthAllowed(t *testing.T) { imgType, _ := arch.GetImageType(imgTypeName) testPackageSpecSets := distro_test_common.GetTestingPackageSpecSets("kernel", arch.Name(), imgType.PayloadPackageSets()) _, err := imgType.Manifest(bp.Customizations, distro.ImageOptions{}, nil, testPackageSpecSets, 0) - layout := imgType.PartitionType() - if layout == "" || strings.HasPrefix(imgTypeName, "edge-") { + if strings.HasPrefix(imgTypeName, "edge-") { continue - } else if layout == "gpt" { - assert.NoError(t, err) } else { - assert.EqualError(t, err, "failed creating volume: maximum number of partitions reached (4)") + assert.NoError(t, err) } } }