distro/rhel85: automatically convert to LVM on fs customizations

Whenever we create a new mountpoint due to a user customization,
ensure the layout uses LVM, i.e. convert plain layouts to it, if
needed. This does not apply to rpm-ostree based systems.
Add "lvm2" to the build pipeline and thus generate new manifests
and image infos.
Adjust the existing tests that assumed we can not create more
than 4 partitions on mbr layouts, since that is now not true
anymore.
This is a port from rhel86, commit 63aa155

The change in osPipeline() is required now to fix the Prefix for the
bootloader specification when LVM is used. The unspecified Prefix, which
was previously used for all cases, defaults to "/boot". When the layout
is converted to LVM, a boot partition is created and the BLS Prefix
should be set to "".

In the case where we don't have a partition table, the BLS stage is not
needed, but it was done unconditionally before, so keep the default
image definitions unchanged.

Co-Authored-By: Achilleas Koutsou <achilleas@koutsou.net>
This commit is contained in:
Christian Kellner 2022-04-13 21:53:51 +02:00 committed by Tom Gundersen
parent bd6b8e7128
commit 98b491fcac
40 changed files with 3507 additions and 6164 deletions

View file

@ -268,6 +268,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}
@ -331,8 +349,9 @@ func (t *imageType) getPartitionTable(
}
imageSize := t.Size(options.Size)
lvmify := !t.rpmOstree
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, false, rng)
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, lvmify, rng)
}
func (t *imageType) PartitionType() string {

View file

@ -704,13 +704,10 @@ func TestDistro_MountpointsWithArbitraryDepthAllowed(t *testing.T) {
imgType, _ := arch.GetImageType(imgTypeName)
testPackageSpecSets := distro_test_common.GetTestingImagePackageSpecSets("kernel", imgType)
_, 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)
}
}
}

View file

@ -21,6 +21,7 @@ func distroBuildPackageSet(t *imageType) rpmmd.PackageSet {
"glibc",
"lorax-templates-generic",
"lorax-templates-rhel",
"lvm2",
"policycoreutils",
"python36",
"python3-iniparse",

View file

@ -19,12 +19,12 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options)
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
if err != nil {
return nil, err
}
@ -76,12 +76,11 @@ func prependKernelCmdlineStage(pipeline *osbuild.Pipeline, t *imageType, pt *dis
func vhdPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options)
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
if err != nil {
return nil, err
}
@ -107,12 +106,12 @@ func vhdPipelines(t *imageType, customizations *blueprint.Customizations, option
func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options)
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
if err != nil {
return nil, err
}
@ -138,12 +137,12 @@ func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, optio
func openstackPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options)
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options, partitionTable)
if err != nil {
return nil, err
}
@ -896,7 +895,7 @@ func tarPipelines(t *imageType, customizations *blueprint.Customizations, option
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options, nil)
if err != nil {
return nil, err
}
@ -936,7 +935,7 @@ func imageInstallerPipelines(t *imageType, customizations *blueprint.Customizati
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey]))
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], customizations, options, nil)
if err != nil {
return nil, err
}
@ -1064,12 +1063,21 @@ func osPipeline(t *imageType,
repos []rpmmd.RepoConfig,
packages []rpmmd.PackageSpec,
c *blueprint.Customizations,
options distro.ImageOptions) (*osbuild.Pipeline, error) {
options distro.ImageOptions,
pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
p := new(osbuild.Pipeline)
p.Name = "os"
p.Build = "name:build"
p.AddStage(osbuild.NewRPMStage(osbuild.NewRPMStageOptions(repos), osbuild.NewRpmStageSourceFilesInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
// If the /boot is on a separate partition, the prefix for the BLS stage must be ""
if pt == nil || pt.FindMountable("/boot") == nil {
// NOTE(akoutsou): this is technically not needed when pt == nil, but
// it was done unconditionally before, so we should keep the image
// definitions the same
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
} else {
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{Prefix: common.StringToPtr("")}))
}
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))