debian-forge-composer/internal/distro/rhel85/distro.go
Christian Kellner 98b491fcac 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>
2022-04-30 12:37:50 +01:00

972 lines
29 KiB
Go

package rhel85
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"path"
"sort"
"strings"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/disk"
"github.com/osbuild/osbuild-composer/internal/distro"
osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
const defaultName = "rhel-85"
const osVersion = "8.5"
const releaseVersion = "8"
const modulePlatformID = "platform:el8"
const ostreeRef = "rhel/8/%s/edge"
const (
// package set names
// build package set name
buildPkgsKey = "build"
// main/common os image package set name
osPkgsKey = "packages"
// container package set name
containerPkgsKey = "container"
// installer package set name
installerPkgsKey = "installer"
// blueprint package set name
blueprintPkgsKey = "blueprint"
)
var mountpointAllowList = []string{
"/", "/var", "/opt", "/srv", "/usr", "/app", "/data", "/home",
}
type distribution struct {
name string
modulePlatformID string
ostreeRef string
arches map[string]distro.Arch
}
func (d *distribution) Name() string {
return d.name
}
func (d *distribution) Releasever() string {
return releaseVersion
}
func (d *distribution) ModulePlatformID() string {
return d.modulePlatformID
}
func (d *distribution) OSTreeRef() string {
return d.ostreeRef
}
func (d *distribution) ListArches() []string {
archNames := make([]string, 0, len(d.arches))
for name := range d.arches {
archNames = append(archNames, name)
}
sort.Strings(archNames)
return archNames
}
func (d *distribution) GetArch(name string) (distro.Arch, error) {
arch, exists := d.arches[name]
if !exists {
return nil, errors.New("invalid architecture: " + name)
}
return arch, nil
}
func (d *distribution) addArches(arches ...architecture) {
if d.arches == nil {
d.arches = map[string]distro.Arch{}
}
// Do not make copies of architectures, as opposed to image types,
// because architecture definitions are not used by more than a single
// distro definition.
for idx := range arches {
d.arches[arches[idx].name] = &arches[idx]
}
}
func (d *distribution) isRHEL() bool {
return strings.HasPrefix(d.name, "rhel")
}
type architecture struct {
distro *distribution
name string
imageTypes map[string]distro.ImageType
imageTypeAliases map[string]string
legacy string
bootType distro.BootType
}
func (a *architecture) Name() string {
return a.name
}
func (a *architecture) ListImageTypes() []string {
itNames := make([]string, 0, len(a.imageTypes))
for name := range a.imageTypes {
itNames = append(itNames, name)
}
sort.Strings(itNames)
return itNames
}
func (a *architecture) GetImageType(name string) (distro.ImageType, error) {
t, exists := a.imageTypes[name]
if !exists {
aliasForName, exists := a.imageTypeAliases[name]
if !exists {
return nil, errors.New("invalid image type: " + name)
}
t, exists = a.imageTypes[aliasForName]
if !exists {
panic(fmt.Sprintf("image type '%s' is an alias to a non-existing image type '%s'", name, aliasForName))
}
}
return t, nil
}
func (a *architecture) addImageTypes(imageTypes ...imageType) {
if a.imageTypes == nil {
a.imageTypes = map[string]distro.ImageType{}
}
for idx := range imageTypes {
it := imageTypes[idx]
it.arch = a
a.imageTypes[it.name] = &it
for _, alias := range it.nameAliases {
if a.imageTypeAliases == nil {
a.imageTypeAliases = map[string]string{}
}
if existingAliasFor, exists := a.imageTypeAliases[alias]; exists {
panic(fmt.Sprintf("image type alias '%s' for '%s' is already defined for another image type '%s'", alias, it.name, existingAliasFor))
}
a.imageTypeAliases[alias] = it.name
}
}
}
func (a *architecture) Distro() distro.Distro {
return a.distro
}
type pipelinesFunc func(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error)
type packageSetFunc func(t *imageType) rpmmd.PackageSet
type imageType struct {
arch *architecture
name string
nameAliases []string
filename string
mimeType string
packageSets map[string]packageSetFunc
enabledServices []string
disabledServices []string
defaultTarget string
kernelOptions string
defaultSize uint64
buildPipelines []string
payloadPipelines []string
exports []string
pipelines pipelinesFunc
// bootISO: installable ISO
bootISO bool
// rpmOstree: edge/ostree
rpmOstree bool
// bootable image
bootable bool
// If set to a value, it is preferred over the architecture value
bootType distro.BootType
// List of valid arches for the image type
basePartitionTables distro.BasePartitionTableMap
}
func (t *imageType) Name() string {
return t.name
}
func (t *imageType) Arch() distro.Arch {
return t.arch
}
func (t *imageType) Filename() string {
return t.filename
}
func (t *imageType) MIMEType() string {
return t.mimeType
}
func (t *imageType) OSTreeRef() string {
if t.rpmOstree {
return fmt.Sprintf(ostreeRef, t.arch.name)
}
return ""
}
func (t *imageType) Size(size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if t.name == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
}
if size == 0 {
size = t.defaultSize
}
return size
}
func (t *imageType) getPackages(name string) rpmmd.PackageSet {
getter := t.packageSets[name]
if getter == nil {
return rpmmd.PackageSet{}
}
return getter(t)
}
func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.PackageSet {
// merge package sets that appear in the image type with the package sets
// of the same name from the distro and arch
mergedSets := make(map[string]rpmmd.PackageSet)
imageSets := t.packageSets
for name := range imageSets {
mergedSets[name] = t.getPackages(name)
}
if _, hasPackages := imageSets[osPkgsKey]; !hasPackages {
// should this be possible??
mergedSets[osPkgsKey] = rpmmd.PackageSet{}
}
// every image type must define a 'build' package set
if _, hasBuild := imageSets[buildPkgsKey]; !hasBuild {
panic(fmt.Sprintf("'%s' image type has no '%s' package set defined", t.name, buildPkgsKey))
}
// blueprint packages
bpPackages := bp.GetPackages()
timezone, _ := bp.Customizations.GetTimezoneSettings()
if timezone != nil {
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}
kernel := bp.Customizations.GetKernel().Name
// add bp kernel to main OS package set to avoid duplicate kernels
mergedSets[osPkgsKey] = mergedSets[osPkgsKey].Append(rpmmd.PackageSet{Include: []string{kernel}})
return mergedSets
}
func (t *imageType) BuildPipelines() []string {
return t.buildPipelines
}
func (t *imageType) PayloadPipelines() []string {
return t.payloadPipelines
}
func (t *imageType) PayloadPackageSets() []string {
return []string{blueprintPkgsKey}
}
func (t *imageType) PackageSetsChains() map[string][]string {
return map[string][]string{osPkgsKey: {osPkgsKey, blueprintPkgsKey}}
}
func (t *imageType) Exports() []string {
return t.exports
}
// getBootType returns the BootType which should be used for this particular
// combination of architecture and image type.
func (t *imageType) getBootType() distro.BootType {
bootType := t.arch.bootType
if t.bootType != distro.UnsetBootType {
bootType = t.bootType
}
return bootType
}
func (t *imageType) supportsUEFI() bool {
bootType := t.getBootType()
if bootType == distro.HybridBootType || bootType == distro.UEFIBootType {
return true
}
return false
}
func (t *imageType) getPartitionTable(
mountpoints []blueprint.FilesystemCustomization,
options distro.ImageOptions,
rng *rand.Rand,
) (*disk.PartitionTable, error) {
archName := t.arch.Name()
basePartitionTable, exists := t.basePartitionTables[archName]
if !exists {
return nil, fmt.Errorf("unknown arch: " + archName)
}
imageSize := t.Size(options.Size)
lvmify := !t.rpmOstree
return disk.NewPartitionTable(&basePartitionTable, mountpoints, imageSize, lvmify, rng)
}
func (t *imageType) PartitionType() string {
archName := t.arch.Name()
basePartitionTable, exists := t.basePartitionTables[archName]
if !exists {
return ""
}
return basePartitionTable.Type
}
// local type for ostree commit metadata used to define commit sources
type ostreeCommit struct {
Checksum string
URL string
}
func (t *imageType) Manifest(customizations *blueprint.Customizations,
options distro.ImageOptions,
repos []rpmmd.RepoConfig,
packageSpecSets map[string][]rpmmd.PackageSpec,
seed int64) (distro.Manifest, error) {
if err := t.checkOptions(customizations, options); err != nil {
return distro.Manifest{}, err
}
source := rand.NewSource(seed)
// math/rand is good enough in this case
/* #nosec G404 */
rng := rand.New(source)
pipelines, err := t.pipelines(t, customizations, options, repos, packageSpecSets, rng)
if err != nil {
return distro.Manifest{}, err
}
// flatten spec sets for sources
allPackageSpecs := make([]rpmmd.PackageSpec, 0)
for _, specs := range packageSpecSets {
allPackageSpecs = append(allPackageSpecs, specs...)
}
var commits []ostreeCommit
if options.OSTree.Parent != "" && options.OSTree.URL != "" {
commits = []ostreeCommit{{Checksum: options.OSTree.Parent, URL: options.OSTree.URL}}
}
return json.Marshal(
osbuild.Manifest{
Version: "2",
Pipelines: pipelines,
Sources: t.sources(allPackageSpecs, commits),
},
)
}
func (t *imageType) sources(packages []rpmmd.PackageSpec, ostreeCommits []ostreeCommit) osbuild.Sources {
sources := osbuild.Sources{}
curl := &osbuild.CurlSource{
Items: make(map[string]osbuild.CurlSourceItem),
}
for _, pkg := range packages {
item := new(osbuild.URLWithSecrets)
item.URL = pkg.RemoteLocation
if pkg.Secrets == "org.osbuild.rhsm" {
item.Secrets = &osbuild.URLSecrets{
Name: "org.osbuild.rhsm",
}
}
curl.Items[pkg.Checksum] = item
}
if len(curl.Items) > 0 {
sources["org.osbuild.curl"] = curl
}
ostree := &osbuild.OSTreeSource{
Items: make(map[string]osbuild.OSTreeSourceItem),
}
for _, commit := range ostreeCommits {
item := new(osbuild.OSTreeSourceItem)
item.Remote.URL = commit.URL
ostree.Items[commit.Checksum] = *item
}
if len(ostree.Items) > 0 {
sources["org.osbuild.ostree"] = ostree
}
return sources
}
func isMountpointAllowed(mountpoint string) bool {
for _, allowed := range mountpointAllowList {
match, _ := path.Match(allowed, mountpoint)
if match {
return true
}
// ensure that only clean mountpoints
// are valid
if strings.Contains(mountpoint, "//") {
return false
}
match = strings.HasPrefix(mountpoint, allowed+"/")
if allowed != "/" && match {
return true
}
}
return false
}
// checkOptions checks the validity and compatibility of options and customizations for the image type.
func (t *imageType) checkOptions(customizations *blueprint.Customizations, options distro.ImageOptions) error {
if t.bootISO && t.rpmOstree {
if options.OSTree.Parent == "" {
return fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.name)
}
if t.name == "edge-simplified-installer" {
if err := customizations.CheckAllowed("InstallationDevice"); err != nil {
return fmt.Errorf("boot ISO image type %q contains unsupported blueprint customizations: %v", t.name, err)
}
} else if t.name == "edge-installer" {
allowed := []string{"User", "Group"}
if err := customizations.CheckAllowed(allowed...); err != nil {
return fmt.Errorf("unsupported blueprint customizations found for boot ISO image type %q: (allowed: %s)", t.name, strings.Join(allowed, ", "))
}
}
}
if t.name == "edge-raw-image" && options.OSTree.Parent == "" {
return fmt.Errorf("edge raw images require specifying a URL from which to retrieve the OSTree commit")
}
if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.rpmOstree && (!t.bootable || t.bootISO) {
return fmt.Errorf("kernel boot parameter customizations are not supported for ostree types")
}
mountpoints := customizations.GetFilesystems()
if mountpoints != nil && t.rpmOstree {
return fmt.Errorf("Custom mountpoints are not supported for ostree types")
}
invalidMountpoints := []string{}
for _, m := range mountpoints {
if !isMountpointAllowed(m.Mountpoint) {
invalidMountpoints = append(invalidMountpoints, m.Mountpoint)
}
}
if len(invalidMountpoints) > 0 {
return fmt.Errorf("The following custom mountpoints are not supported %+q", invalidMountpoints)
}
return nil
}
// New creates a new distro object, defining the supported architectures and image types
func New() distro.Distro {
return newDistro(defaultName, modulePlatformID, ostreeRef)
}
func NewHostDistro(name, modulePlatformID, ostreeRef string) distro.Distro {
return newDistro(name, modulePlatformID, ostreeRef)
}
func newDistro(name, modulePlatformID, ostreeRef string) distro.Distro {
const GigaByte = 1024 * 1024 * 1024
rd := &distribution{
name: name,
modulePlatformID: modulePlatformID,
ostreeRef: ostreeRef,
}
// Architecture definitions
x86_64 := architecture{
name: distro.X86_64ArchName,
distro: rd,
legacy: "i386-pc",
bootType: distro.HybridBootType,
}
aarch64 := architecture{
name: distro.Aarch64ArchName,
distro: rd,
bootType: distro.UEFIBootType,
}
ppc64le := architecture{
distro: rd,
name: distro.Ppc64leArchName,
legacy: "powerpc-ieee1275",
bootType: distro.LegacyBootType,
}
s390x := architecture{
distro: rd,
name: distro.S390xArchName,
bootType: distro.LegacyBootType,
}
// Shared Services
edgeServices := []string{
"NetworkManager.service", "firewalld.service", "sshd.service",
}
// Image Definitions
edgeCommitImgType := imageType{
name: "edge-commit",
nameAliases: []string{"rhel-edge-commit"},
filename: "commit.tar",
mimeType: "application/x-tar",
packageSets: map[string]packageSetFunc{
buildPkgsKey: edgeBuildPackageSet,
osPkgsKey: edgeCommitPackageSet,
},
enabledServices: edgeServices,
rpmOstree: true,
pipelines: edgeCommitPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"ostree-tree", "ostree-commit", "commit-archive"},
exports: []string{"commit-archive"},
}
edgeOCIImgType := imageType{
name: "edge-container",
nameAliases: []string{"rhel-edge-container"},
filename: "container.tar",
mimeType: "application/x-tar",
packageSets: map[string]packageSetFunc{
buildPkgsKey: edgeBuildPackageSet,
osPkgsKey: edgeCommitPackageSet,
containerPkgsKey: func(t *imageType) rpmmd.PackageSet {
return rpmmd.PackageSet{
Include: []string{"nginx"},
}
},
},
enabledServices: edgeServices,
rpmOstree: true,
bootISO: false,
pipelines: edgeContainerPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"ostree-tree", "ostree-commit", "container-tree", "container"},
exports: []string{"container"},
}
edgeRawImgType := imageType{
name: "edge-raw-image",
nameAliases: []string{"rhel-edge-raw-image"},
filename: "image.raw.xz",
mimeType: "application/xz",
packageSets: map[string]packageSetFunc{
buildPkgsKey: edgeRawImageBuildPackageSet,
},
defaultSize: 10 * GigaByte,
rpmOstree: true,
bootable: true,
bootISO: false,
pipelines: edgeRawImagePipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"image-tree", "image", "archive"},
exports: []string{"archive"},
basePartitionTables: edgeBasePartitionTables,
}
edgeInstallerImgType := imageType{
name: "edge-installer",
nameAliases: []string{"rhel-edge-installer"},
filename: "installer.iso",
mimeType: "application/x-iso9660-image",
packageSets: map[string]packageSetFunc{
// TODO: non-arch-specific package set handling for installers
// This image type requires build packages for installers and
// ostree/edge. For now we only have x86-64 installer build
// package sets defined. When we add installer build package sets
// for other architectures, this will need to be moved to the
// architecture and the merging will happen in the PackageSets()
// method like the other sets.
buildPkgsKey: edgeInstallerBuildPackageSet,
osPkgsKey: edgeCommitPackageSet,
installerPkgsKey: edgeInstallerPackageSet,
},
enabledServices: edgeServices,
rpmOstree: true,
bootISO: true,
pipelines: edgeInstallerPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"anaconda-tree", "bootiso-tree", "bootiso"},
exports: []string{"bootiso"},
}
edgeSimplifiedInstallerImgType := imageType{
name: "edge-simplified-installer",
nameAliases: []string{"rhel-edge-simplified-installer"},
filename: "simplified-installer.iso",
mimeType: "application/x-iso9660-image",
packageSets: map[string]packageSetFunc{
// TODO: non-arch-specific package set handling for installers
// This image type requires build packages for installers and
// ostree/edge. For now we only have x86-64 installer build
// package sets defined. When we add installer build package sets
// for other architectures, this will need to be moved to the
// architecture and the merging will happen in the PackageSets()
// method like the other sets.
buildPkgsKey: edgeInstallerBuildPackageSet,
installerPkgsKey: edgeSimplifiedInstallerPackageSet,
},
enabledServices: edgeServices,
defaultSize: 10 * GigaByte,
rpmOstree: true,
bootable: true,
bootISO: true,
pipelines: edgeSimplifiedInstallerPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"image-tree", "image", "archive", "coi-tree", "efiboot-tree", "bootiso-tree", "bootiso"},
exports: []string{"bootiso"},
basePartitionTables: edgeBasePartitionTables,
}
qcow2ImgType := imageType{
name: "qcow2",
filename: "disk.qcow2",
mimeType: "application/x-qemu-disk",
defaultTarget: "multi-user.target",
kernelOptions: "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: qcow2CommonPackageSet,
},
bootable: true,
defaultSize: 10 * GigaByte,
pipelines: qcow2Pipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "qcow2"},
exports: []string{"qcow2"},
basePartitionTables: defaultBasePartitionTables,
}
vhdImgType := imageType{
name: "vhd",
filename: "disk.vhd",
mimeType: "application/x-vhd",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: vhdCommonPackageSet,
},
enabledServices: []string{
"sshd",
"waagent",
},
defaultTarget: "multi-user.target",
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
bootable: true,
defaultSize: 4 * GigaByte,
pipelines: vhdPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "vpc"},
exports: []string{"vpc"},
basePartitionTables: defaultBasePartitionTables,
}
vmdkImgType := imageType{
name: "vmdk",
filename: "disk.vmdk",
mimeType: "application/x-vmdk",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: vmdkCommonPackageSet,
},
kernelOptions: "ro net.ifnames=0",
bootable: true,
defaultSize: 4 * GigaByte,
pipelines: vmdkPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "vmdk"},
exports: []string{"vmdk"},
basePartitionTables: defaultBasePartitionTables,
}
openstackImgType := imageType{
name: "openstack",
filename: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: openstackCommonPackageSet,
},
kernelOptions: "ro net.ifnames=0",
bootable: true,
defaultSize: 4 * GigaByte,
pipelines: openstackPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "qcow2"},
exports: []string{"qcow2"},
basePartitionTables: defaultBasePartitionTables,
}
ociImageType := imageType{
name: "oci",
filename: "disk.qcow2",
mimeType: "application/x-qemu-disk",
defaultTarget: "multi-user.target",
kernelOptions: "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: qcow2CommonPackageSet,
},
bootable: true,
defaultSize: 10 * GigaByte,
pipelines: qcow2Pipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "qcow2"},
exports: []string{"qcow2"},
basePartitionTables: defaultBasePartitionTables,
}
// EC2 services
ec2EnabledServices := []string{
"sshd",
"NetworkManager",
"nm-cloud-setup.service",
"nm-cloud-setup.timer",
"cloud-init",
"cloud-init-local",
"cloud-config",
"cloud-final",
"reboot.target",
}
amiImgTypeX86_64 := imageType{
name: "ami",
filename: "image.raw",
mimeType: "application/octet-stream",
packageSets: map[string]packageSetFunc{
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: ec2CommonPackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true,
bootType: distro.LegacyBootType,
defaultSize: 10 * GigaByte,
pipelines: ec2Pipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image"},
exports: []string{"image"},
basePartitionTables: ec2BasePartitionTables,
}
amiImgTypeAarch64 := imageType{
name: "ami",
filename: "image.raw",
mimeType: "application/octet-stream",
packageSets: map[string]packageSetFunc{
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: ec2CommonPackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto",
bootable: true,
defaultSize: 10 * GigaByte,
pipelines: ec2Pipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image"},
exports: []string{"image"},
basePartitionTables: ec2BasePartitionTables,
}
ec2ImgTypeX86_64 := imageType{
name: "ec2",
filename: "image.raw.xz",
mimeType: "application/xz",
packageSets: map[string]packageSetFunc{
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2PackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true,
bootType: distro.LegacyBootType,
defaultSize: 10 * GigaByte,
pipelines: rhelEc2Pipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "archive"},
exports: []string{"archive"},
basePartitionTables: ec2BasePartitionTables,
}
ec2ImgTypeAarch64 := imageType{
name: "ec2",
filename: "image.raw.xz",
mimeType: "application/xz",
packageSets: map[string]packageSetFunc{
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2PackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto",
bootable: true,
defaultSize: 10 * GigaByte,
pipelines: rhelEc2Pipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "archive"},
exports: []string{"archive"},
basePartitionTables: ec2BasePartitionTables,
}
ec2HaImgTypeX86_64 := imageType{
name: "ec2-ha",
filename: "image.raw.xz",
mimeType: "application/xz",
packageSets: map[string]packageSetFunc{
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2HaPackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true,
bootType: distro.LegacyBootType,
defaultSize: 10 * GigaByte,
pipelines: rhelEc2Pipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "archive"},
exports: []string{"archive"},
basePartitionTables: ec2BasePartitionTables,
}
// This image type does not take the disabled / enabled service definitions
// from this structure definition, but rather from distro.ImageConfig instance
// defined in the gcePipelines() function. The same applies to the default
// target.
gceImgType := imageType{
name: "gce",
filename: "image.tar.gz",
mimeType: "application/gzip",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: gcePackageSet,
},
kernelOptions: "net.ifnames=0 biosdevname=0 scsi_mod.use_blk_mq=Y crashkernel=auto console=ttyS0,38400n8d",
bootable: true,
bootType: distro.UEFIBootType,
defaultSize: 20 * GigaByte,
pipelines: gceByosPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "archive"},
exports: []string{"archive"},
basePartitionTables: defaultBasePartitionTables,
}
gceRhuiImgType := imageType{
name: "gce-rhui",
filename: "image.tar.gz",
mimeType: "application/gzip",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: gceRhuiPackageSet,
},
kernelOptions: "net.ifnames=0 biosdevname=0 scsi_mod.use_blk_mq=Y crashkernel=auto console=ttyS0,38400n8d",
bootable: true,
bootType: distro.UEFIBootType,
defaultSize: 20 * GigaByte,
pipelines: gceRhuiPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "image", "archive"},
exports: []string{"archive"},
basePartitionTables: defaultBasePartitionTables,
}
tarImgType := imageType{
name: "tar",
filename: "root.tar.xz",
mimeType: "application/x-tar",
packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: func(t *imageType) rpmmd.PackageSet {
return rpmmd.PackageSet{
Include: []string{"policycoreutils", "selinux-policy-targeted"},
Exclude: []string{"rng-tools"},
}
},
},
pipelines: tarPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "root-tar"},
exports: []string{"root-tar"},
}
imageInstallerImgTypeX86_64 := imageType{
name: "image-installer",
filename: "installer.iso",
mimeType: "application/x-iso9660-image",
packageSets: map[string]packageSetFunc{
buildPkgsKey: anacondaBuildPackageSet,
osPkgsKey: bareMetalPackageSet,
installerPkgsKey: anacondaPackageSet,
},
rpmOstree: false,
bootISO: true,
bootable: true,
pipelines: imageInstallerPipelines,
buildPipelines: []string{"build"},
payloadPipelines: []string{"os", "anaconda-tree", "bootiso-tree", "bootiso"},
exports: []string{"bootiso"},
}
x86_64.addImageTypes(qcow2ImgType, vhdImgType, vmdkImgType, openstackImgType, amiImgTypeX86_64, ec2ImgTypeX86_64, ec2HaImgTypeX86_64, tarImgType, imageInstallerImgTypeX86_64, edgeCommitImgType, edgeInstallerImgType, edgeOCIImgType, edgeRawImgType, edgeSimplifiedInstallerImgType, ociImageType, gceImgType, gceRhuiImgType)
aarch64.addImageTypes(qcow2ImgType, openstackImgType, amiImgTypeAarch64, ec2ImgTypeAarch64, tarImgType, edgeCommitImgType, edgeInstallerImgType, edgeOCIImgType, edgeRawImgType, edgeSimplifiedInstallerImgType)
ppc64le.addImageTypes(qcow2ImgType, tarImgType)
s390x.addImageTypes(qcow2ImgType, tarImgType)
rd.addArches(x86_64, aarch64, ppc64le, s390x)
return rd
}