RHEL-90: introduce default image config data structure

Introduce a new data structure `ImageConfig` holding the default OS
configuration applied when building an image. The structure can be used
to hold the default image configuration on the distribution level with
possible overrides defined on the image-type level.

As a starting point, move hard-coded default values and configuration
common for `osPipeline`, `ec2BaseTreePipeline` and `ostreeTreePipeline`
to the distribution and image-type default image configuration. This is
preparing the ground for merging all of these three pipeline functions
into `osPipeline`, which will produce the appropriate OS pipeline based
on the image-type configuration and the fact if it is rpmOstree or not.

Regenerate affected EC2 and AMI manifests. There is however no change in
the resulting image configuration and image-info report.

Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
Tomas Hozza 2021-12-16 13:37:39 +01:00 committed by Tomáš Hozza
parent 3c729be3c5
commit b200fa8fcd
10 changed files with 526 additions and 243 deletions

View file

@ -0,0 +1,48 @@
package distro
import "github.com/osbuild/osbuild-composer/internal/osbuild2"
// ImageConfig represents a (default) configuration applied to the image
type ImageConfig struct {
Timezone string
TimeSynchronization *osbuild2.ChronyStageOptions
Locale string
Keyboard *osbuild2.KeymapStageOptions
EnabledServices []string
DisabledServices []string
DefaultTarget string
Sysconfig []*osbuild2.SysconfigStageOptions
}
// InheritFrom inherits unset values from the provided parent configuration and
// returns a new structure instance, which is a result of the inheritance.
func (c *ImageConfig) InheritFrom(parentConfig *ImageConfig) *ImageConfig {
finalConfig := ImageConfig(*c)
if parentConfig != nil {
if finalConfig.Timezone == "" {
finalConfig.Timezone = parentConfig.Timezone
}
if finalConfig.TimeSynchronization == nil {
finalConfig.TimeSynchronization = parentConfig.TimeSynchronization
}
if finalConfig.Locale == "" {
finalConfig.Locale = parentConfig.Locale
}
if finalConfig.Keyboard == nil {
finalConfig.Keyboard = parentConfig.Keyboard
}
if finalConfig.EnabledServices == nil {
finalConfig.EnabledServices = parentConfig.EnabledServices
}
if finalConfig.DisabledServices == nil {
finalConfig.DisabledServices = parentConfig.DisabledServices
}
if finalConfig.DefaultTarget == "" {
finalConfig.DefaultTarget = parentConfig.DefaultTarget
}
if finalConfig.Sysconfig == nil {
finalConfig.Sysconfig = parentConfig.Sysconfig
}
}
return &finalConfig
}

View file

@ -0,0 +1,167 @@
package distro
import (
"testing"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/osbuild2"
"github.com/stretchr/testify/assert"
)
func TestImageConfigInheritFrom(t *testing.T) {
tests := []struct {
name string
distroConfig *ImageConfig
imageConfig *ImageConfig
expectedConfig *ImageConfig
}{
{
name: "inheritance with overridden values",
distroConfig: &ImageConfig{
Timezone: "America/New_York",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Timeservers: []string{"127.0.0.1"},
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
imageConfig: &ImageConfig{
Timezone: "UTC",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Servers: []osbuild2.ChronyConfigServer{
{
Hostname: "169.254.169.123",
Prefer: common.BoolToPtr(true),
Iburst: common.BoolToPtr(true),
Minpoll: common.IntToPtr(4),
Maxpoll: common.IntToPtr(4),
},
},
LeapsecTz: common.StringToPtr(""),
},
},
expectedConfig: &ImageConfig{
Timezone: "UTC",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Servers: []osbuild2.ChronyConfigServer{
{
Hostname: "169.254.169.123",
Prefer: common.BoolToPtr(true),
Iburst: common.BoolToPtr(true),
Minpoll: common.IntToPtr(4),
Maxpoll: common.IntToPtr(4),
},
},
LeapsecTz: common.StringToPtr(""),
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
},
{
name: "empty image type configuration",
distroConfig: &ImageConfig{
Timezone: "America/New_York",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Timeservers: []string{"127.0.0.1"},
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
imageConfig: &ImageConfig{},
expectedConfig: &ImageConfig{
Timezone: "America/New_York",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Timeservers: []string{"127.0.0.1"},
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
},
{
name: "empty distro configuration",
distroConfig: &ImageConfig{},
imageConfig: &ImageConfig{
Timezone: "America/New_York",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Timeservers: []string{"127.0.0.1"},
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
expectedConfig: &ImageConfig{
Timezone: "America/New_York",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Timeservers: []string{"127.0.0.1"},
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
},
{
name: "empty distro configuration",
distroConfig: nil,
imageConfig: &ImageConfig{
Timezone: "America/New_York",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Timeservers: []string{"127.0.0.1"},
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
expectedConfig: &ImageConfig{
Timezone: "America/New_York",
TimeSynchronization: &osbuild2.ChronyStageOptions{
Timeservers: []string{"127.0.0.1"},
},
Locale: "en_US.UTF-8",
Keyboard: &osbuild2.KeymapStageOptions{
Keymap: "us",
},
EnabledServices: []string{"sshd"},
DisabledServices: []string{"named"},
DefaultTarget: "multi-user.target",
},
},
}
for idx, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.expectedConfig, tt.imageConfig.InheritFrom(tt.distroConfig), "test case %q failed (idx %d)", tt.name, idx)
})
}
}

View file

@ -10,6 +10,7 @@ import (
"strings"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/disk"
"github.com/osbuild/osbuild-composer/internal/distro"
osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2"
@ -40,41 +41,62 @@ var mountpointAllowList = []string{
}
type distribution struct {
name string
product string
osVersion string
releaseVersion string
modulePlatformID string
vendor string
ostreeRefTmpl string
isolabelTmpl string
runner string
arches map[string]distro.Arch
name string
product string
osVersion string
releaseVersion string
modulePlatformID string
vendor string
ostreeRefTmpl string
isolabelTmpl string
runner string
arches map[string]distro.Arch
defaultImageConfig *distro.ImageConfig
}
// RHEL-based OS image configuration defaults
var defaultDistroImageConfig = &distro.ImageConfig{
Timezone: "America/New_York",
Locale: "en_US.UTF-8",
Sysconfig: []*osbuild.SysconfigStageOptions{
{
Kernel: &osbuild.SysconfigKernelOptions{
UpdateDefault: true,
DefaultKernel: "kernel",
},
Network: &osbuild.SysconfigNetworkOptions{
Networking: true,
NoZeroConf: true,
},
},
},
}
// distribution objects without the arches > image types
var distroMap = map[string]distribution{
"rhel-90": {
name: "rhel-90",
product: "Red Hat Enterprise Linux",
osVersion: "9.0",
releaseVersion: "9",
modulePlatformID: "platform:el9",
vendor: "redhat",
ostreeRefTmpl: "rhel/9/%s/edge",
isolabelTmpl: "RHEL-9-0-0-BaseOS-%s",
runner: "org.osbuild.rhel90",
name: "rhel-90",
product: "Red Hat Enterprise Linux",
osVersion: "9.0",
releaseVersion: "9",
modulePlatformID: "platform:el9",
vendor: "redhat",
ostreeRefTmpl: "rhel/9/%s/edge",
isolabelTmpl: "RHEL-9-0-0-BaseOS-%s",
runner: "org.osbuild.rhel90",
defaultImageConfig: defaultDistroImageConfig,
},
"centos-9": {
name: "centos-9",
product: "CentOS Stream",
osVersion: "9-stream",
releaseVersion: "9",
modulePlatformID: "platform:el9",
vendor: "centos",
ostreeRefTmpl: "centos/9/%s/edge",
isolabelTmpl: "CentOS-Stream-9-%s-dvd",
runner: "org.osbuild.centos9",
name: "centos-9",
product: "CentOS Stream",
osVersion: "9-stream",
releaseVersion: "9",
modulePlatformID: "platform:el9",
vendor: "centos",
ostreeRefTmpl: "centos/9/%s/edge",
isolabelTmpl: "CentOS-Stream-9-%s-dvd",
runner: "org.osbuild.centos9",
defaultImageConfig: defaultDistroImageConfig,
},
}
@ -128,6 +150,10 @@ func (d *distribution) isRHEL() bool {
return strings.HasPrefix(d.name, "rhel")
}
func (d *distribution) getDefaultImageConfig() *distro.ImageConfig {
return d.defaultImageConfig
}
type architecture struct {
distro *distribution
name string
@ -194,21 +220,19 @@ type pipelinesFunc func(t *imageType, customizations *blueprint.Customizations,
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
arch *architecture
name string
nameAliases []string
filename string
mimeType string
packageSets map[string]packageSetFunc
defaultImageConfig *distro.ImageConfig
kernelOptions string
defaultSize uint64
buildPipelines []string
payloadPipelines []string
exports []string
pipelines pipelinesFunc
// bootISO: installable ISO
bootISO bool
@ -359,6 +383,15 @@ func (t *imageType) getPartitionTable(
return disk.CreatePartitionTable(mountpoints, options.Size, basePartitionTable, rng), nil
}
func (t *imageType) getDefaultImageConfig() *distro.ImageConfig {
// ensure that image always returns non-nil default config
imageConfig := t.defaultImageConfig
if imageConfig == nil {
imageConfig = &distro.ImageConfig{}
}
return imageConfig.InheritFrom(t.arch.distro.getDefaultImageConfig())
}
// local type for ostree commit metadata used to define commit sources
type ostreeCommit struct {
Checksum string
@ -569,7 +602,9 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: edgeBuildPackageSet,
osPkgsKey: edgeCommitPackageSet,
},
enabledServices: edgeServices,
defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
rpmOstree: true,
pipelines: edgeCommitPipelines,
buildPipelines: []string{"build"},
@ -591,7 +626,9 @@ func newDistro(distroName string) distro.Distro {
}
},
},
enabledServices: edgeServices,
defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
rpmOstree: true,
bootISO: false,
pipelines: edgeContainerPipelines,
@ -636,7 +673,9 @@ func newDistro(distroName string) distro.Distro {
osPkgsKey: edgeCommitPackageSet,
installerPkgsKey: edgeInstallerPackageSet,
},
enabledServices: edgeServices,
defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
rpmOstree: true,
bootISO: true,
pipelines: edgeInstallerPipelines,
@ -661,7 +700,9 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: edgeInstallerBuildPackageSet,
installerPkgsKey: edgeSimplifiedInstallerPackageSet,
},
enabledServices: edgeServices,
defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
defaultSize: 10 * GigaByte,
rpmOstree: true,
bootable: true,
@ -677,12 +718,14 @@ func newDistro(distroName string) distro.Distro {
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,
},
defaultImageConfig: &distro.ImageConfig{
DefaultTarget: "multi-user.target",
},
bootable: true,
defaultSize: 10 * GigaByte,
pipelines: qcow2Pipelines,
@ -700,11 +743,13 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: distroBuildPackageSet,
osPkgsKey: vhdCommonPackageSet,
},
enabledServices: []string{
"sshd",
"waagent",
defaultImageConfig: &distro.ImageConfig{
EnabledServices: []string{
"sshd",
"waagent",
},
DefaultTarget: "multi-user.target",
},
defaultTarget: "multi-user.target",
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
bootable: true,
defaultSize: 4 * GigaByte,
@ -751,18 +796,66 @@ func newDistro(distroName string) distro.Distro {
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",
"tuned",
// default EC2 images config
defaultEc2ImageConfig := &distro.ImageConfig{
Timezone: "UTC",
TimeSynchronization: &osbuild.ChronyStageOptions{
Servers: []osbuild.ChronyConfigServer{
{
Hostname: "169.254.169.123",
Prefer: common.BoolToPtr(true),
Iburst: common.BoolToPtr(true),
Minpoll: common.IntToPtr(4),
Maxpoll: common.IntToPtr(4),
},
},
// empty string will remove any occurrences of the option from the configuration
LeapsecTz: common.StringToPtr(""),
},
Keyboard: &osbuild.KeymapStageOptions{
Keymap: "us",
X11Keymap: &osbuild.X11KeymapOptions{
Layouts: []string{"us"},
},
},
EnabledServices: []string{
"sshd",
"NetworkManager",
"nm-cloud-setup.service",
"nm-cloud-setup.timer",
"cloud-init",
"cloud-init-local",
"cloud-config",
"cloud-final",
"reboot.target",
"tuned",
},
DefaultTarget: "multi-user.target",
Sysconfig: []*osbuild.SysconfigStageOptions{
{
Kernel: &osbuild.SysconfigKernelOptions{
UpdateDefault: true,
DefaultKernel: "kernel",
},
Network: &osbuild.SysconfigNetworkOptions{
Networking: true,
NoZeroConf: true,
},
NetworkScripts: &osbuild.NetworkScriptsOptions{
IfcfgFiles: map[string]osbuild.IfcfgFile{
"eth0": {
Device: "eth0",
Bootproto: osbuild.IfcfgBootprotoDHCP,
OnBoot: common.BoolToPtr(true),
Type: osbuild.IfcfgTypeEthernet,
UserCtl: common.BoolToPtr(true),
PeerDNS: common.BoolToPtr(true),
IPv6Init: common.BoolToPtr(false),
},
},
},
},
},
}
amiImgTypeX86_64 := imageType{
@ -773,8 +866,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: ec2CommonPackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
defaultImageConfig: defaultEc2ImageConfig,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true,
bootType: distro.LegacyBootType,
@ -794,8 +886,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: ec2CommonPackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
defaultImageConfig: defaultEc2ImageConfig,
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,
@ -814,8 +905,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2PackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
defaultImageConfig: defaultEc2ImageConfig,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true,
bootType: distro.LegacyBootType,
@ -835,8 +925,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2PackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
defaultImageConfig: defaultEc2ImageConfig,
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,
@ -855,8 +944,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2HaPackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
defaultImageConfig: defaultEc2ImageConfig,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true,
bootType: distro.LegacyBootType,
@ -876,8 +964,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2SapPackageSet,
},
defaultTarget: "multi-user.target",
enabledServices: ec2EnabledServices,
defaultImageConfig: defaultEc2ImageConfig,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto processor.max_cstate=1 intel_idle.max_cstate=1",
bootable: true,
bootType: distro.LegacyBootType,

View file

@ -24,7 +24,7 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
return nil, err
}
treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable)
if err != nil {
return nil, err
}
@ -77,7 +77,7 @@ func vhdPipelines(t *imageType, customizations *blueprint.Customizations, option
return nil, err
}
treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable)
if err != nil {
return nil, err
}
@ -107,7 +107,7 @@ func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, optio
return nil, err
}
treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable)
if err != nil {
return nil, err
}
@ -137,7 +137,7 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations,
return nil, err
}
treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable)
if err != nil {
return nil, err
}
@ -169,16 +169,17 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations,
// as the last one to the returned pipeline. The stage is not appended on purpose, to allow caller to append
// any additional stages to the pipeline, but before the SELinuxStage, which must be always the last one.
func ec2BaseTreePipeline(
t *imageType,
repos []rpmmd.RepoConfig,
packages []rpmmd.PackageSpec,
bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations,
options distro.ImageOptions,
enabledServices, disabledServices []string,
defaultTarget string,
withRHUI, isRHEL bool,
withRHUI bool,
pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
// COMMON WITH osPipeline - START
imageConfig := t.getDefaultImageConfig()
p := new(osbuild.Pipeline)
p.Name = "os"
p.Build = "name:build"
@ -196,17 +197,12 @@ func ec2BaseTreePipeline(
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
} else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"}))
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: imageConfig.Locale}))
}
if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
} else {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{
Keymap: "us",
X11Keymap: &osbuild.X11KeymapOptions{
Layouts: []string{"us"},
},
}))
} else if imageConfig.Keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(imageConfig.Keyboard))
}
if hostname := c.GetHostname(); hostname != nil {
@ -217,25 +213,13 @@ func ec2BaseTreePipeline(
if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
} else {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "UTC"}))
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone}))
}
if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers}))
} else {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{
Servers: []osbuild.ChronyConfigServer{
{
Hostname: "169.254.169.123",
Prefer: common.BoolToPtr(true),
Iburst: common.BoolToPtr(true),
Minpoll: common.IntToPtr(4),
Maxpoll: common.IntToPtr(4),
},
},
// empty string will remove any occurrences of the option from the configuration
LeapsecTz: common.StringToPtr(""),
}))
} else if imageConfig.TimeSynchronization != nil {
p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization))
}
if groups := c.GetGroups(); len(groups) > 0 {
@ -250,14 +234,25 @@ func ec2BaseTreePipeline(
p.AddStage(osbuild.NewUsersStage(userOptions))
}
if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget)))
if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil ||
imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(
imageConfig.EnabledServices,
imageConfig.DisabledServices,
services,
imageConfig.DefaultTarget,
)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall)))
}
for _, sysconfigConfig := range imageConfig.Sysconfig {
p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig))
}
// COMMON WITH osPipeline - END
p.AddStage(osbuild.NewSystemdLogindStage(&osbuild.SystemdLogindStageOptions{
Filename: "00-getty-fixes.conf",
Config: osbuild.SystemdLogindConfigDropin{
@ -268,30 +263,6 @@ func ec2BaseTreePipeline(
},
}))
p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{
Kernel: &osbuild.SysconfigKernelOptions{
UpdateDefault: true,
DefaultKernel: "kernel",
},
Network: &osbuild.SysconfigNetworkOptions{
Networking: true,
NoZeroConf: true,
},
NetworkScripts: &osbuild.NetworkScriptsOptions{
IfcfgFiles: map[string]osbuild.IfcfgFile{
"eth0": {
Device: "eth0",
Bootproto: osbuild.IfcfgBootprotoDHCP,
OnBoot: common.BoolToPtr(true),
Type: osbuild.IfcfgTypeEthernet,
UserCtl: common.BoolToPtr(true),
PeerDNS: common.BoolToPtr(true),
IPv6Init: common.BoolToPtr(false),
},
},
},
}))
p.AddStage(osbuild.NewCloudInitStage(&osbuild.CloudInitStageOptions{
Filename: "00-rhel-default-user.cfg",
Config: osbuild.CloudInitConfigFile{
@ -332,7 +303,7 @@ func ec2BaseTreePipeline(
Profile: "sssd",
}))
if isRHEL {
if t.arch.distro.isRHEL() {
if options.Subscription != nil {
commands := []string{
fmt.Sprintf("/usr/sbin/subscription-manager register --org=%s --activationkey=%s --serverurl %s --baseurl %s", options.Subscription.Organization, options.Subscription.ActivationKey, options.Subscription.ServerUrl, options.Subscription.BaseUrl),
@ -375,11 +346,10 @@ func ec2BaseTreePipeline(
return p, nil
}
func ec2X86_64BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string,
defaultTarget string, withRHUI, isRHEL bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
func ec2X86_64BaseTreePipeline(t *imageType, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, options distro.ImageOptions, withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
treePipeline, err := ec2BaseTreePipeline(repos, packages, bpPackages, c, options, enabledServices, disabledServices, defaultTarget, withRHUI, isRHEL, pt)
treePipeline, err := ec2BaseTreePipeline(t, repos, packages, bpPackages, c, options, withRHUI, pt)
if err != nil {
return nil, err
}
@ -415,10 +385,10 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations,
switch arch := t.arch.Name(); arch {
// rhel-ec2-x86_64, rhel-ha-ec2
case distro.X86_64ArchName:
treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, t.arch.distro.isRHEL(), &partitionTable)
treePipeline, err = ec2X86_64BaseTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, withRHUI, &partitionTable)
// rhel-ec2-aarch64
case distro.Aarch64ArchName:
treePipeline, err = ec2BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, t.arch.distro.isRHEL(), &partitionTable)
treePipeline, err = ec2BaseTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, withRHUI, &partitionTable)
default:
return nil, fmt.Errorf("ec2CommonPipelines: unsupported image architecture: %q", arch)
}
@ -454,7 +424,7 @@ func ec2SapPipelines(t *imageType, customizations *blueprint.Customizations, opt
switch arch := t.arch.Name(); arch {
// rhel-sap-ec2
case distro.X86_64ArchName:
treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, t.arch.distro.isRHEL(), &partitionTable)
treePipeline, err = ec2X86_64BaseTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, withRHUI, &partitionTable)
default:
return nil, fmt.Errorf("ec2SapPipelines: unsupported image architecture: %q", arch)
}
@ -619,7 +589,7 @@ func tarPipelines(t *imageType, customizations *blueprint.Customizations, option
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner))
treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, nil)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, nil)
if err != nil {
return nil, err
}
@ -662,7 +632,7 @@ func tarInstallerPipelines(t *imageType, customizations *blueprint.Customization
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner))
treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, nil)
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, nil)
if err != nil {
return nil, err
}
@ -700,7 +670,7 @@ func edgeCorePipelines(t *imageType, customizations *blueprint.Customizations, o
pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner))
treePipeline, err := ostreeTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget)
treePipeline, err := ostreeTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options)
if err != nil {
return nil, err
}
@ -789,34 +759,39 @@ func buildPipeline(repos []rpmmd.RepoConfig, buildPackageSpecs []rpmmd.PackageSp
return p
}
func osPipeline(repos []rpmmd.RepoConfig,
func osPipeline(t *imageType,
repos []rpmmd.RepoConfig,
packages []rpmmd.PackageSpec,
bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations,
options distro.ImageOptions,
enabledServices, disabledServices []string,
defaultTarget string,
pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
imageConfig := t.getDefaultImageConfig()
p := new(osbuild.Pipeline)
p.Name = "os"
p.Build = "name:build"
packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
// If the /boot is on a separate partition, the prefix for the BLS stage must be ""
if pt == nil || pt.BootPartition() == nil {
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}))
} else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"}))
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: imageConfig.Locale}))
}
if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
} else if imageConfig.Keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(imageConfig.Keyboard))
}
if hostname := c.GetHostname(); hostname != nil {
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
}
@ -825,11 +800,13 @@ func osPipeline(repos []rpmmd.RepoConfig,
if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
} else {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"}))
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone}))
}
if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers}))
} else if imageConfig.TimeSynchronization != nil {
p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization))
}
if groups := c.GetGroups(); len(groups) > 0 {
@ -844,25 +821,23 @@ func osPipeline(repos []rpmmd.RepoConfig,
p.AddStage(osbuild.NewUsersStage(userOptions))
}
if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget)))
if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil ||
imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(
imageConfig.EnabledServices,
imageConfig.DisabledServices,
services,
imageConfig.DefaultTarget,
)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall)))
}
// These are the current defaults for the sysconfig stage. This can be changed to be image type exclusive if different configs are needed.
p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{
Kernel: &osbuild.SysconfigKernelOptions{
UpdateDefault: true,
DefaultKernel: "kernel",
},
Network: &osbuild.SysconfigNetworkOptions{
Networking: true,
NoZeroConf: true,
},
}))
for _, sysconfigConfig := range imageConfig.Sysconfig {
p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig))
}
if options.Subscription != nil {
commands := []string{
@ -881,7 +856,8 @@ func osPipeline(repos []rpmmd.RepoConfig,
return p, nil
}
func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string, defaultTarget string) (*osbuild.Pipeline, error) {
func ostreeTreePipeline(t *imageType, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, c *blueprint.Customizations, options distro.ImageOptions) (*osbuild.Pipeline, error) {
imageConfig := t.getDefaultImageConfig()
p := new(osbuild.Pipeline)
p.Name = "ostree-tree"
p.Build = "name:build"
@ -894,15 +870,19 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
} else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"}))
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: imageConfig.Locale}))
}
if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
} else if imageConfig.Keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(imageConfig.Keyboard))
}
if hostname := c.GetHostname(); hostname != nil {
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
}
@ -911,11 +891,13 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
} else {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"}))
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone}))
}
if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers}))
} else if imageConfig.TimeSynchronization != nil {
p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization))
}
if groups := c.GetGroups(); len(groups) > 0 {
@ -931,25 +913,23 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
p.AddStage(osbuild.NewFirstBootStage(usersFirstBootOptions(userOptions)))
}
if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget)))
if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil ||
imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(
imageConfig.EnabledServices,
imageConfig.DisabledServices,
services,
imageConfig.DefaultTarget,
)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall)))
}
// These are the current defaults for the sysconfig stage. This can be changed to be image type exclusive if different configs are needed.
p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{
Kernel: &osbuild.SysconfigKernelOptions{
UpdateDefault: true,
DefaultKernel: "kernel",
},
Network: &osbuild.SysconfigNetworkOptions{
Networking: true,
NoZeroConf: true,
},
}))
for _, sysconfigConfig := range imageConfig.Sysconfig {
p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig))
}
if options.Subscription != nil {
commands := []string{
@ -975,6 +955,7 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
}))
return p, nil
}
func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuild.Pipeline {
p := new(osbuild.Pipeline)
p.Name = "ostree-commit"

View file

@ -876,17 +876,6 @@
"default_target": "multi-user.target"
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.sysconfig",
"options": {
@ -913,6 +902,17 @@
}
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.cloud-init",
"options": {

View file

@ -887,17 +887,6 @@
"default_target": "multi-user.target"
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.sysconfig",
"options": {
@ -924,6 +913,17 @@
}
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.cloud-init",
"options": {

View file

@ -859,17 +859,6 @@
"default_target": "multi-user.target"
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.sysconfig",
"options": {
@ -896,6 +885,17 @@
}
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.cloud-init",
"options": {

View file

@ -872,17 +872,6 @@
"default_target": "multi-user.target"
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.sysconfig",
"options": {
@ -909,6 +898,17 @@
}
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.cloud-init",
"options": {

View file

@ -1066,17 +1066,6 @@
"default_target": "multi-user.target"
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.sysconfig",
"options": {
@ -1103,6 +1092,17 @@
}
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.cloud-init",
"options": {

View file

@ -1120,17 +1120,6 @@
"default_target": "multi-user.target"
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.sysconfig",
"options": {
@ -1157,6 +1146,17 @@
}
}
},
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{
"type": "org.osbuild.cloud-init",
"options": {