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" "strings"
"github.com/osbuild/osbuild-composer/internal/blueprint" "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/disk"
"github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distro"
osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2" osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2"
@ -40,41 +41,62 @@ var mountpointAllowList = []string{
} }
type distribution struct { type distribution struct {
name string name string
product string product string
osVersion string osVersion string
releaseVersion string releaseVersion string
modulePlatformID string modulePlatformID string
vendor string vendor string
ostreeRefTmpl string ostreeRefTmpl string
isolabelTmpl string isolabelTmpl string
runner string runner string
arches map[string]distro.Arch 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 // distribution objects without the arches > image types
var distroMap = map[string]distribution{ var distroMap = map[string]distribution{
"rhel-90": { "rhel-90": {
name: "rhel-90", name: "rhel-90",
product: "Red Hat Enterprise Linux", product: "Red Hat Enterprise Linux",
osVersion: "9.0", osVersion: "9.0",
releaseVersion: "9", releaseVersion: "9",
modulePlatformID: "platform:el9", modulePlatformID: "platform:el9",
vendor: "redhat", vendor: "redhat",
ostreeRefTmpl: "rhel/9/%s/edge", ostreeRefTmpl: "rhel/9/%s/edge",
isolabelTmpl: "RHEL-9-0-0-BaseOS-%s", isolabelTmpl: "RHEL-9-0-0-BaseOS-%s",
runner: "org.osbuild.rhel90", runner: "org.osbuild.rhel90",
defaultImageConfig: defaultDistroImageConfig,
}, },
"centos-9": { "centos-9": {
name: "centos-9", name: "centos-9",
product: "CentOS Stream", product: "CentOS Stream",
osVersion: "9-stream", osVersion: "9-stream",
releaseVersion: "9", releaseVersion: "9",
modulePlatformID: "platform:el9", modulePlatformID: "platform:el9",
vendor: "centos", vendor: "centos",
ostreeRefTmpl: "centos/9/%s/edge", ostreeRefTmpl: "centos/9/%s/edge",
isolabelTmpl: "CentOS-Stream-9-%s-dvd", isolabelTmpl: "CentOS-Stream-9-%s-dvd",
runner: "org.osbuild.centos9", runner: "org.osbuild.centos9",
defaultImageConfig: defaultDistroImageConfig,
}, },
} }
@ -128,6 +150,10 @@ func (d *distribution) isRHEL() bool {
return strings.HasPrefix(d.name, "rhel") return strings.HasPrefix(d.name, "rhel")
} }
func (d *distribution) getDefaultImageConfig() *distro.ImageConfig {
return d.defaultImageConfig
}
type architecture struct { type architecture struct {
distro *distribution distro *distribution
name string name string
@ -194,21 +220,19 @@ type pipelinesFunc func(t *imageType, customizations *blueprint.Customizations,
type packageSetFunc func(t *imageType) rpmmd.PackageSet type packageSetFunc func(t *imageType) rpmmd.PackageSet
type imageType struct { type imageType struct {
arch *architecture arch *architecture
name string name string
nameAliases []string nameAliases []string
filename string filename string
mimeType string mimeType string
packageSets map[string]packageSetFunc packageSets map[string]packageSetFunc
enabledServices []string defaultImageConfig *distro.ImageConfig
disabledServices []string kernelOptions string
defaultTarget string defaultSize uint64
kernelOptions string buildPipelines []string
defaultSize uint64 payloadPipelines []string
buildPipelines []string exports []string
payloadPipelines []string pipelines pipelinesFunc
exports []string
pipelines pipelinesFunc
// bootISO: installable ISO // bootISO: installable ISO
bootISO bool bootISO bool
@ -359,6 +383,15 @@ func (t *imageType) getPartitionTable(
return disk.CreatePartitionTable(mountpoints, options.Size, basePartitionTable, rng), nil 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 // local type for ostree commit metadata used to define commit sources
type ostreeCommit struct { type ostreeCommit struct {
Checksum string Checksum string
@ -569,7 +602,9 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: edgeBuildPackageSet, buildPkgsKey: edgeBuildPackageSet,
osPkgsKey: edgeCommitPackageSet, osPkgsKey: edgeCommitPackageSet,
}, },
enabledServices: edgeServices, defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
rpmOstree: true, rpmOstree: true,
pipelines: edgeCommitPipelines, pipelines: edgeCommitPipelines,
buildPipelines: []string{"build"}, buildPipelines: []string{"build"},
@ -591,7 +626,9 @@ func newDistro(distroName string) distro.Distro {
} }
}, },
}, },
enabledServices: edgeServices, defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
rpmOstree: true, rpmOstree: true,
bootISO: false, bootISO: false,
pipelines: edgeContainerPipelines, pipelines: edgeContainerPipelines,
@ -636,7 +673,9 @@ func newDistro(distroName string) distro.Distro {
osPkgsKey: edgeCommitPackageSet, osPkgsKey: edgeCommitPackageSet,
installerPkgsKey: edgeInstallerPackageSet, installerPkgsKey: edgeInstallerPackageSet,
}, },
enabledServices: edgeServices, defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
rpmOstree: true, rpmOstree: true,
bootISO: true, bootISO: true,
pipelines: edgeInstallerPipelines, pipelines: edgeInstallerPipelines,
@ -661,7 +700,9 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: edgeInstallerBuildPackageSet, buildPkgsKey: edgeInstallerBuildPackageSet,
installerPkgsKey: edgeSimplifiedInstallerPackageSet, installerPkgsKey: edgeSimplifiedInstallerPackageSet,
}, },
enabledServices: edgeServices, defaultImageConfig: &distro.ImageConfig{
EnabledServices: edgeServices,
},
defaultSize: 10 * GigaByte, defaultSize: 10 * GigaByte,
rpmOstree: true, rpmOstree: true,
bootable: true, bootable: true,
@ -677,12 +718,14 @@ func newDistro(distroName string) distro.Distro {
name: "qcow2", name: "qcow2",
filename: "disk.qcow2", filename: "disk.qcow2",
mimeType: "application/x-qemu-disk", mimeType: "application/x-qemu-disk",
defaultTarget: "multi-user.target",
kernelOptions: "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto", kernelOptions: "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto",
packageSets: map[string]packageSetFunc{ packageSets: map[string]packageSetFunc{
buildPkgsKey: distroBuildPackageSet, buildPkgsKey: distroBuildPackageSet,
osPkgsKey: qcow2CommonPackageSet, osPkgsKey: qcow2CommonPackageSet,
}, },
defaultImageConfig: &distro.ImageConfig{
DefaultTarget: "multi-user.target",
},
bootable: true, bootable: true,
defaultSize: 10 * GigaByte, defaultSize: 10 * GigaByte,
pipelines: qcow2Pipelines, pipelines: qcow2Pipelines,
@ -700,11 +743,13 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: distroBuildPackageSet, buildPkgsKey: distroBuildPackageSet,
osPkgsKey: vhdCommonPackageSet, osPkgsKey: vhdCommonPackageSet,
}, },
enabledServices: []string{ defaultImageConfig: &distro.ImageConfig{
"sshd", EnabledServices: []string{
"waagent", "sshd",
"waagent",
},
DefaultTarget: "multi-user.target",
}, },
defaultTarget: "multi-user.target",
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0", kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
bootable: true, bootable: true,
defaultSize: 4 * GigaByte, defaultSize: 4 * GigaByte,
@ -751,18 +796,66 @@ func newDistro(distroName string) distro.Distro {
basePartitionTables: defaultBasePartitionTables, basePartitionTables: defaultBasePartitionTables,
} }
// EC2 services // default EC2 images config
ec2EnabledServices := []string{ defaultEc2ImageConfig := &distro.ImageConfig{
"sshd", Timezone: "UTC",
"NetworkManager", TimeSynchronization: &osbuild.ChronyStageOptions{
"nm-cloud-setup.service", Servers: []osbuild.ChronyConfigServer{
"nm-cloud-setup.timer", {
"cloud-init", Hostname: "169.254.169.123",
"cloud-init-local", Prefer: common.BoolToPtr(true),
"cloud-config", Iburst: common.BoolToPtr(true),
"cloud-final", Minpoll: common.IntToPtr(4),
"reboot.target", Maxpoll: common.IntToPtr(4),
"tuned", },
},
// 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{ amiImgTypeX86_64 := imageType{
@ -773,8 +866,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet, buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: ec2CommonPackageSet, osPkgsKey: ec2CommonPackageSet,
}, },
defaultTarget: "multi-user.target", defaultImageConfig: defaultEc2ImageConfig,
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto", kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true, bootable: true,
bootType: distro.LegacyBootType, bootType: distro.LegacyBootType,
@ -794,8 +886,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet, buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: ec2CommonPackageSet, osPkgsKey: ec2CommonPackageSet,
}, },
defaultTarget: "multi-user.target", defaultImageConfig: defaultEc2ImageConfig,
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto", kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto",
bootable: true, bootable: true,
defaultSize: 10 * GigaByte, defaultSize: 10 * GigaByte,
@ -814,8 +905,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet, buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2PackageSet, osPkgsKey: rhelEc2PackageSet,
}, },
defaultTarget: "multi-user.target", defaultImageConfig: defaultEc2ImageConfig,
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto", kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true, bootable: true,
bootType: distro.LegacyBootType, bootType: distro.LegacyBootType,
@ -835,8 +925,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet, buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2PackageSet, osPkgsKey: rhelEc2PackageSet,
}, },
defaultTarget: "multi-user.target", defaultImageConfig: defaultEc2ImageConfig,
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto", kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto",
bootable: true, bootable: true,
defaultSize: 10 * GigaByte, defaultSize: 10 * GigaByte,
@ -855,8 +944,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet, buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2HaPackageSet, osPkgsKey: rhelEc2HaPackageSet,
}, },
defaultTarget: "multi-user.target", defaultImageConfig: defaultEc2ImageConfig,
enabledServices: ec2EnabledServices,
kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto", kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
bootable: true, bootable: true,
bootType: distro.LegacyBootType, bootType: distro.LegacyBootType,
@ -876,8 +964,7 @@ func newDistro(distroName string) distro.Distro {
buildPkgsKey: ec2BuildPackageSet, buildPkgsKey: ec2BuildPackageSet,
osPkgsKey: rhelEc2SapPackageSet, osPkgsKey: rhelEc2SapPackageSet,
}, },
defaultTarget: "multi-user.target", defaultImageConfig: defaultEc2ImageConfig,
enabledServices: ec2EnabledServices,
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", 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, bootable: true,
bootType: distro.LegacyBootType, bootType: distro.LegacyBootType,

View file

@ -24,7 +24,7 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
@ -77,7 +77,7 @@ func vhdPipelines(t *imageType, customizations *blueprint.Customizations, option
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
@ -107,7 +107,7 @@ func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, optio
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
@ -137,7 +137,7 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations,
return nil, err 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 { if err != nil {
return nil, err 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 // 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. // any additional stages to the pipeline, but before the SELinuxStage, which must be always the last one.
func ec2BaseTreePipeline( func ec2BaseTreePipeline(
t *imageType,
repos []rpmmd.RepoConfig, repos []rpmmd.RepoConfig,
packages []rpmmd.PackageSpec, packages []rpmmd.PackageSpec,
bpPackages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, c *blueprint.Customizations,
options distro.ImageOptions, options distro.ImageOptions,
enabledServices, disabledServices []string, withRHUI bool,
defaultTarget string,
withRHUI, isRHEL bool,
pt *disk.PartitionTable) (*osbuild.Pipeline, error) { pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
// COMMON WITH osPipeline - START
imageConfig := t.getDefaultImageConfig()
p := new(osbuild.Pipeline) p := new(osbuild.Pipeline)
p.Name = "os" p.Name = "os"
p.Build = "name:build" p.Build = "name:build"
@ -196,17 +197,12 @@ func ec2BaseTreePipeline(
if language != nil { if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language})) p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
} else { } else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"})) p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: imageConfig.Locale}))
} }
if keyboard != nil { if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard})) p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
} else { } else if imageConfig.Keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{ p.AddStage(osbuild.NewKeymapStage(imageConfig.Keyboard))
Keymap: "us",
X11Keymap: &osbuild.X11KeymapOptions{
Layouts: []string{"us"},
},
}))
} }
if hostname := c.GetHostname(); hostname != nil { if hostname := c.GetHostname(); hostname != nil {
@ -217,25 +213,13 @@ func ec2BaseTreePipeline(
if timezone != nil { if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone})) p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
} else { } else {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "UTC"})) p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone}))
} }
if len(ntpServers) > 0 { if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers})) p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers}))
} else { } else if imageConfig.TimeSynchronization != nil {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{ p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization))
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(""),
}))
} }
if groups := c.GetGroups(); len(groups) > 0 { if groups := c.GetGroups(); len(groups) > 0 {
@ -250,14 +234,25 @@ func ec2BaseTreePipeline(
p.AddStage(osbuild.NewUsersStage(userOptions)) p.AddStage(osbuild.NewUsersStage(userOptions))
} }
if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" { if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil ||
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget))) imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(
imageConfig.EnabledServices,
imageConfig.DisabledServices,
services,
imageConfig.DefaultTarget,
)))
} }
if firewall := c.GetFirewall(); firewall != nil { if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall))) 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{ p.AddStage(osbuild.NewSystemdLogindStage(&osbuild.SystemdLogindStageOptions{
Filename: "00-getty-fixes.conf", Filename: "00-getty-fixes.conf",
Config: osbuild.SystemdLogindConfigDropin{ 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{ p.AddStage(osbuild.NewCloudInitStage(&osbuild.CloudInitStageOptions{
Filename: "00-rhel-default-user.cfg", Filename: "00-rhel-default-user.cfg",
Config: osbuild.CloudInitConfigFile{ Config: osbuild.CloudInitConfigFile{
@ -332,7 +303,7 @@ func ec2BaseTreePipeline(
Profile: "sssd", Profile: "sssd",
})) }))
if isRHEL { if t.arch.distro.isRHEL() {
if options.Subscription != nil { if options.Subscription != nil {
commands := []string{ 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), 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 return p, nil
} }
func ec2X86_64BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, func ec2X86_64BaseTreePipeline(t *imageType, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string, c *blueprint.Customizations, options distro.ImageOptions, withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
defaultTarget string, withRHUI, isRHEL 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 { if err != nil {
return nil, err return nil, err
} }
@ -415,10 +385,10 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations,
switch arch := t.arch.Name(); arch { switch arch := t.arch.Name(); arch {
// rhel-ec2-x86_64, rhel-ha-ec2 // rhel-ec2-x86_64, rhel-ha-ec2
case distro.X86_64ArchName: 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 // rhel-ec2-aarch64
case distro.Aarch64ArchName: 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: default:
return nil, fmt.Errorf("ec2CommonPipelines: unsupported image architecture: %q", arch) 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 { switch arch := t.arch.Name(); arch {
// rhel-sap-ec2 // rhel-sap-ec2
case distro.X86_64ArchName: 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: default:
return nil, fmt.Errorf("ec2SapPipelines: unsupported image architecture: %q", arch) 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 := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner)) 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 { if err != nil {
return nil, err return nil, err
} }
@ -662,7 +632,7 @@ func tarInstallerPipelines(t *imageType, customizations *blueprint.Customization
pipelines := make([]osbuild.Pipeline, 0) pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner)) 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 { if err != nil {
return nil, err return nil, err
} }
@ -700,7 +670,7 @@ func edgeCorePipelines(t *imageType, customizations *blueprint.Customizations, o
pipelines := make([]osbuild.Pipeline, 0) pipelines := make([]osbuild.Pipeline, 0)
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner)) 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 { if err != nil {
return nil, err return nil, err
} }
@ -789,34 +759,39 @@ func buildPipeline(repos []rpmmd.RepoConfig, buildPackageSpecs []rpmmd.PackageSp
return p return p
} }
func osPipeline(repos []rpmmd.RepoConfig, func osPipeline(t *imageType,
repos []rpmmd.RepoConfig,
packages []rpmmd.PackageSpec, packages []rpmmd.PackageSpec,
bpPackages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec,
c *blueprint.Customizations, c *blueprint.Customizations,
options distro.ImageOptions, options distro.ImageOptions,
enabledServices, disabledServices []string,
defaultTarget string,
pt *disk.PartitionTable) (*osbuild.Pipeline, error) { pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
imageConfig := t.getDefaultImageConfig()
p := new(osbuild.Pipeline) p := new(osbuild.Pipeline)
p.Name = "os" p.Name = "os"
p.Build = "name:build" p.Build = "name:build"
packages = append(packages, bpPackages...) packages = append(packages, bpPackages...)
p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages))) 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 the /boot is on a separate partition, the prefix for the BLS stage must be ""
if pt == nil || pt.BootPartition() == nil { if pt == nil || pt.BootPartition() == nil {
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{})) p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
} else { } else {
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{Prefix: common.StringToPtr("")})) p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{Prefix: common.StringToPtr("")}))
} }
language, keyboard := c.GetPrimaryLocale() language, keyboard := c.GetPrimaryLocale()
if language != nil { if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language})) p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
} else { } else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"})) p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: imageConfig.Locale}))
} }
if keyboard != nil { if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard})) 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 { if hostname := c.GetHostname(); hostname != nil {
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname})) p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
} }
@ -825,11 +800,13 @@ func osPipeline(repos []rpmmd.RepoConfig,
if timezone != nil { if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone})) p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
} else { } else {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"})) p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone}))
} }
if len(ntpServers) > 0 { if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers})) 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 { if groups := c.GetGroups(); len(groups) > 0 {
@ -844,25 +821,23 @@ func osPipeline(repos []rpmmd.RepoConfig,
p.AddStage(osbuild.NewUsersStage(userOptions)) p.AddStage(osbuild.NewUsersStage(userOptions))
} }
if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" { if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil ||
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget))) imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(
imageConfig.EnabledServices,
imageConfig.DisabledServices,
services,
imageConfig.DefaultTarget,
)))
} }
if firewall := c.GetFirewall(); firewall != nil { if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall))) 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. for _, sysconfigConfig := range imageConfig.Sysconfig {
p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{ p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig))
Kernel: &osbuild.SysconfigKernelOptions{ }
UpdateDefault: true,
DefaultKernel: "kernel",
},
Network: &osbuild.SysconfigNetworkOptions{
Networking: true,
NoZeroConf: true,
},
}))
if options.Subscription != nil { if options.Subscription != nil {
commands := []string{ commands := []string{
@ -881,7 +856,8 @@ func osPipeline(repos []rpmmd.RepoConfig,
return p, nil 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 := new(osbuild.Pipeline)
p.Name = "ostree-tree" p.Name = "ostree-tree"
p.Build = "name:build" 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.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages)))
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{})) p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
language, keyboard := c.GetPrimaryLocale() language, keyboard := c.GetPrimaryLocale()
if language != nil { if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language})) p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
} else { } else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"})) p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: imageConfig.Locale}))
} }
if keyboard != nil { if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard})) 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 { if hostname := c.GetHostname(); hostname != nil {
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname})) p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
} }
@ -911,11 +891,13 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
if timezone != nil { if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone})) p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
} else { } else {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"})) p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone}))
} }
if len(ntpServers) > 0 { if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers})) 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 { 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))) p.AddStage(osbuild.NewFirstBootStage(usersFirstBootOptions(userOptions)))
} }
if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" { if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil ||
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget))) imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" {
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(
imageConfig.EnabledServices,
imageConfig.DisabledServices,
services,
imageConfig.DefaultTarget,
)))
} }
if firewall := c.GetFirewall(); firewall != nil { if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall))) 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. for _, sysconfigConfig := range imageConfig.Sysconfig {
p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{ p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig))
Kernel: &osbuild.SysconfigKernelOptions{ }
UpdateDefault: true,
DefaultKernel: "kernel",
},
Network: &osbuild.SysconfigNetworkOptions{
Networking: true,
NoZeroConf: true,
},
}))
if options.Subscription != nil { if options.Subscription != nil {
commands := []string{ commands := []string{
@ -975,6 +955,7 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec,
})) }))
return p, nil return p, nil
} }
func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuild.Pipeline { func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuild.Pipeline {
p := new(osbuild.Pipeline) p := new(osbuild.Pipeline)
p.Name = "ostree-commit" p.Name = "ostree-commit"

View file

@ -876,17 +876,6 @@
"default_target": "multi-user.target" "default_target": "multi-user.target"
} }
}, },
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{ {
"type": "org.osbuild.sysconfig", "type": "org.osbuild.sysconfig",
"options": { "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", "type": "org.osbuild.cloud-init",
"options": { "options": {

View file

@ -887,17 +887,6 @@
"default_target": "multi-user.target" "default_target": "multi-user.target"
} }
}, },
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{ {
"type": "org.osbuild.sysconfig", "type": "org.osbuild.sysconfig",
"options": { "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", "type": "org.osbuild.cloud-init",
"options": { "options": {

View file

@ -859,17 +859,6 @@
"default_target": "multi-user.target" "default_target": "multi-user.target"
} }
}, },
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{ {
"type": "org.osbuild.sysconfig", "type": "org.osbuild.sysconfig",
"options": { "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", "type": "org.osbuild.cloud-init",
"options": { "options": {

View file

@ -872,17 +872,6 @@
"default_target": "multi-user.target" "default_target": "multi-user.target"
} }
}, },
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{ {
"type": "org.osbuild.sysconfig", "type": "org.osbuild.sysconfig",
"options": { "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", "type": "org.osbuild.cloud-init",
"options": { "options": {

View file

@ -1066,17 +1066,6 @@
"default_target": "multi-user.target" "default_target": "multi-user.target"
} }
}, },
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{ {
"type": "org.osbuild.sysconfig", "type": "org.osbuild.sysconfig",
"options": { "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", "type": "org.osbuild.cloud-init",
"options": { "options": {

View file

@ -1120,17 +1120,6 @@
"default_target": "multi-user.target" "default_target": "multi-user.target"
} }
}, },
{
"type": "org.osbuild.systemd-logind",
"options": {
"filename": "00-getty-fixes.conf",
"config": {
"Login": {
"NAutoVTs": 0
}
}
}
},
{ {
"type": "org.osbuild.sysconfig", "type": "org.osbuild.sysconfig",
"options": { "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", "type": "org.osbuild.cloud-init",
"options": { "options": {