go.mod: update osbuild/images to v0.124.0

This commit is contained in:
Achilleas Koutsou 2025-03-17 18:08:15 +01:00 committed by Sanne Raymaekers
parent a27880c0c6
commit 6a112877f1
62 changed files with 2390 additions and 2108 deletions

2
go.mod
View file

@ -45,7 +45,7 @@ require (
github.com/oapi-codegen/runtime v1.1.1
github.com/openshift-online/ocm-sdk-go v0.1.438
github.com/oracle/oci-go-sdk/v54 v54.0.0
github.com/osbuild/images v0.123.0
github.com/osbuild/images v0.124.0
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d
github.com/osbuild/pulp-client v0.1.0
github.com/prometheus/client_golang v1.20.5

4
go.sum
View file

@ -575,8 +575,8 @@ github.com/openshift-online/ocm-sdk-go v0.1.438 h1:tsLCCUzbLCTL4RZG02y9RuopmGCXp
github.com/openshift-online/ocm-sdk-go v0.1.438/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y=
github.com/oracle/oci-go-sdk/v54 v54.0.0 h1:CDLjeSejv2aDpElAJrhKpi6zvT/zhZCZuXchUUZ+LS4=
github.com/oracle/oci-go-sdk/v54 v54.0.0/go.mod h1:+t+yvcFGVp+3ZnztnyxqXfQDsMlq8U25faBLa+mqCMc=
github.com/osbuild/images v0.123.0 h1:9b2sfl6751dpAEU3wR0bMN1d/bEhbJ39N5a/9ZVCxcg=
github.com/osbuild/images v0.123.0/go.mod h1:Ag87vmyxooiPQBJEDILbypG8/SRIear75YA78NwLix0=
github.com/osbuild/images v0.124.0 h1:WnR2nf43HkNERzz6sa/+Ohzx3QW83bvIlaqi9NGvg4A=
github.com/osbuild/images v0.124.0/go.mod h1:Ag87vmyxooiPQBJEDILbypG8/SRIear75YA78NwLix0=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d h1:r9BFPDv0uuA9k1947Jybcxs36c/pTywWS1gjeizvtcQ=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d/go.mod h1:zR1iu/hOuf+OQNJlk70tju9IqzzM4ycq0ectkFBm94U=
github.com/osbuild/pulp-client v0.1.0 h1:L0C4ezBJGTamN3BKdv+rKLuq/WxXJbsFwz/Hj7aEmJ8=

View file

@ -59,3 +59,12 @@ func ExecError(err error) error {
}
return err
}
// Must() can be used to shortcut all `NewT() (T, err)` constructors.
// It will panic if an error is passed.
func Must[T any](val T, err error) T {
if err != nil {
panic(err)
}
return val
}

View file

@ -262,20 +262,19 @@ func (c *Customizations) GetGroups() []GroupCustomization {
}
func (c *Customizations) GetKernel() *KernelCustomization {
var name string
var append string
var kernelName, kernelAppend string
if c != nil && c.Kernel != nil {
name = c.Kernel.Name
append = c.Kernel.Append
kernelName = c.Kernel.Name
kernelAppend = c.Kernel.Append
}
if name == "" {
name = "kernel"
if kernelName == "" {
kernelName = "kernel"
}
return &KernelCustomization{
Name: name,
Append: append,
Name: kernelName,
Append: kernelAppend,
}
}

View file

@ -6,9 +6,11 @@ import (
"errors"
"fmt"
"path/filepath"
"regexp"
"slices"
"strings"
"github.com/google/uuid"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/pathpolicy"
)
@ -64,6 +66,12 @@ type PartitionCustomization struct {
// (optional, defaults depend on payload and mountpoints).
MinSize uint64 `json:"minsize" toml:"minsize"`
// The partition type GUID for GPT partitions. For DOS partitions, this
// field can be used to set the (2 hex digit) partition type.
// If not set, the type will be automatically set based on the mountpoint
// or the payload type.
PartType string `json:"part_type,omitempty" toml:"part_type,omitempty"`
BtrfsVolumeCustomization
VGCustomization
@ -154,8 +162,9 @@ type BtrfsSubvolumeCustomization struct {
func (v *PartitionCustomization) UnmarshalJSON(data []byte) error {
errPrefix := "JSON unmarshal:"
var typeSniffer struct {
Type string `json:"type"`
MinSize any `json:"minsize"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
}
if err := json.Unmarshal(data, &typeSniffer); err != nil {
return fmt.Errorf("%s %w", errPrefix, err)
@ -184,6 +193,7 @@ func (v *PartitionCustomization) UnmarshalJSON(data []byte) error {
}
v.Type = partType
v.PartType = typeSniffer.PartType
if typeSniffer.MinSize == nil {
return fmt.Errorf("minsize is required")
@ -203,10 +213,11 @@ func (v *PartitionCustomization) UnmarshalJSON(data []byte) error {
// the type is "plain", none of the fields for btrfs or lvm are used.
func decodePlain(v *PartitionCustomization, data []byte) error {
var plain struct {
// Type and minsize are handled by the caller. These are added here to
// Type, minsize, and part_type are handled by the caller. These are added here to
// satisfy "DisallowUnknownFields" when decoding.
Type string `json:"type"`
MinSize any `json:"minsize"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
FilesystemTypedCustomization
}
@ -226,10 +237,11 @@ func decodePlain(v *PartitionCustomization, data []byte) error {
// the type is btrfs, none of the fields for plain or lvm are used.
func decodeBtrfs(v *PartitionCustomization, data []byte) error {
var btrfs struct {
// Type and minsize are handled by the caller. These are added here to
// Type, minsize, and part_type are handled by the caller. These are added here to
// satisfy "DisallowUnknownFields" when decoding.
Type string `json:"type"`
MinSize any `json:"minsize"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
BtrfsVolumeCustomization
}
@ -249,10 +261,11 @@ func decodeBtrfs(v *PartitionCustomization, data []byte) error {
// is lvm, none of the fields for plain or btrfs are used.
func decodeLVM(v *PartitionCustomization, data []byte) error {
var vg struct {
// Type and minsize are handled by the caller. These are added here to
// Type, minsize, and part_type are handled by the caller. These are added here to
// satisfy "DisallowUnknownFields" when decoding.
Type string `json:"type"`
MinSize any `json:"minsize"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
VGCustomization
}
@ -367,6 +380,9 @@ func (p *DiskCustomization) Validate() error {
vgnames := make(map[string]bool)
var errs []error
for _, part := range p.Partitions {
if err := part.ValidatePartitionTypeID(p.Type); err != nil {
errs = append(errs, err)
}
switch part.Type {
case "plain", "":
errs = append(errs, part.validatePlain(mountpoints))
@ -471,6 +487,44 @@ var validPlainFSTypes = []string{
"xfs",
}
// exactly 2 hex digits
var validDosPartitionType = regexp.MustCompile(`^[0-9a-fA-F]{2}$`)
// ValidatePartitionTypeID returns an error if the partition type ID is not
// valid given the partition table type. If the partition table type is an
// empty string, the function returns an error only if the partition type ID is
// invalid for both gpt and dos partition tables.
func (p *PartitionCustomization) ValidatePartitionTypeID(ptType string) error {
// Empty PartType is fine, it will be selected automatically
if p.PartType == "" {
return nil
}
_, uuidErr := uuid.Parse(p.PartType)
validDosType := validDosPartitionType.MatchString(p.PartType)
switch ptType {
case "gpt":
if uuidErr != nil {
return fmt.Errorf("invalid partition part_type %q for partition table type %q (must be a valid UUID): %w", p.PartType, ptType, uuidErr)
}
case "dos":
if !validDosType {
return fmt.Errorf("invalid partition part_type %q for partition table type %q (must be a 2-digit hex number)", p.PartType, ptType)
}
case "":
// We don't know the partition table type yet, the fallback is controlled
// by the CustomPartitionTableOptions, so return an error if it fails both.
if uuidErr != nil && !validDosType {
return fmt.Errorf("invalid part_type %q: must be a valid UUID for GPT partition tables or a 2-digit hex number for DOS partition tables", p.PartType)
}
default:
// ignore: handled elsewhere
}
return nil
}
func (p *PartitionCustomization) validatePlain(mountpoints map[string]bool) error {
if p.FSType == "swap" {
// make sure the mountpoint is empty and return

View file

@ -1272,6 +1272,13 @@ func NewCustomPartitionTable(customizations *blueprint.DiskCustomization, option
}
// add user customized partitions
for _, part := range customizations.Partitions {
if part.PartType != "" {
// check the partition type now that we also know the partition table type
if err := part.ValidatePartitionTypeID(pt.Type.String()); err != nil {
return nil, fmt.Errorf("%s error validating partition type ID for %q: %w", errPrefix, part.Mountpoint, err)
}
}
switch part.Type {
case "plain", "":
if err := addPlainPartition(pt, part, options); err != nil {
@ -1320,28 +1327,34 @@ func addPlainPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
return fmt.Errorf("error creating partition with mountpoint %q: %w", partition.Mountpoint, err)
}
// all user-defined partitions are data partitions except boot and swap
var typeName string
switch {
case partition.Mountpoint == "/":
typeName = "root"
case partition.Mountpoint == "/usr":
typeName = "usr"
case partition.Mountpoint == "/boot":
typeName = "boot"
case fstype == "swap":
typeName = "swap"
default:
typeName = "data"
}
partType := partition.PartType
partType, err := getPartitionTypeIDfor(pt.Type, typeName, options.Architecture)
if err != nil {
return fmt.Errorf("error getting partition type ID for %q: %w", partition.Mountpoint, err)
if partType == "" {
// if the partition type is not specified, determine it based on the
// mountpoint and the partition type
var typeName string
switch {
case partition.Mountpoint == "/":
typeName = "root"
case partition.Mountpoint == "/usr":
typeName = "usr"
case partition.Mountpoint == "/boot":
typeName = "boot"
case fstype == "swap":
typeName = "swap"
default:
typeName = "data"
}
partType, err = getPartitionTypeIDfor(pt.Type, typeName, options.Architecture)
if err != nil {
return fmt.Errorf("error getting partition type ID for %q: %w", partition.Mountpoint, err)
}
}
var payload PayloadEntity
switch typeName {
switch fstype {
case "swap":
payload = &Swap{
Label: partition.Label,
@ -1419,10 +1432,15 @@ func addLVMPartition(pt *PartitionTable, partition blueprint.PartitionCustomizat
}
// create partition for volume group
partType, err := getPartitionTypeIDfor(pt.Type, "lvm", arch.ARCH_UNSET)
if err != nil {
return fmt.Errorf("error creating lvm partition %q: %w", vgname, err)
partType := partition.PartType
if partType == "" {
var err error
partType, err = getPartitionTypeIDfor(pt.Type, "lvm", options.Architecture)
if err != nil {
return fmt.Errorf("error creating lvm partition %q: %w", vgname, err)
}
}
newpart := Partition{
Type: partType,
Size: partition.MinSize,
@ -1448,9 +1466,13 @@ func addBtrfsPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
}
// create partition for btrfs volume
partType, err := getPartitionTypeIDfor(pt.Type, "data", arch.ARCH_UNSET)
if err != nil {
return fmt.Errorf("error creating btrfs partition: %w", err)
partType := partition.PartType
if partType == "" {
var err error
partType, err = getPartitionTypeIDfor(pt.Type, "data", arch.ARCH_UNSET)
if err != nil {
return fmt.Errorf("error creating btrfs partition: %w", err)
}
}
newpart := Partition{
Type: partType,

View file

@ -34,15 +34,6 @@ const (
// blueprint package set name
blueprintPkgsKey = "blueprint"
//Default kernel command line
defaultKernelOptions = "ro"
// Added kernel command line options for ami, qcow2, openstack, vhd and vmdk types
cloudKernelOptions = "ro no_timer_check console=ttyS0,115200n8 biosdevname=0 net.ifnames=0"
// Added kernel command line options for iot-raw-image and iot-qcow2-image types
ostreeDeploymentKernelOptions = "modprobe.blacklist=vc4 rw coreos.no_persist_ip"
)
var (
@ -59,6 +50,23 @@ var (
}
)
// kernel command line arguments
// NOTE: we define them as functions to make sure they globals are never
// modified
// Default kernel command line
func defaultKernelOptions() []string { return []string{"ro"} }
// Added kernel command line options for ami, qcow2, openstack, vhd and vmdk types
func cloudKernelOptions() []string {
return []string{"ro", "no_timer_check", "console=ttyS0,115200n8", "biosdevname=0", "net.ifnames=0"}
}
// Added kernel command line options for iot-raw-image and iot-qcow2-image types
func ostreeDeploymentKernelOptions() []string {
return []string{"modprobe.blacklist=vc4", "rw", "coreos.no_persist_ip"}
}
// Image Definitions
func mkImageInstallerImgType(d distribution) imageType {
return imageType{
@ -67,7 +75,7 @@ func mkImageInstallerImgType(d distribution) imageType {
filename: "installer.iso",
mimeType: "application/x-iso9660-image",
packageSets: map[string]packageSetFunc{
osPkgsKey: func(t *imageType) rpmmd.PackageSet {
osPkgsKey: func(t *imageType) (rpmmd.PackageSet, error) {
// use the minimal raw image type for the OS package set
return packagesets.Load(t, "minimal-raw", VersionReplacements())
},
@ -164,8 +172,8 @@ func mkIotOCIImgType(d distribution) imageType {
mimeType: "application/x-tar",
packageSets: map[string]packageSetFunc{
osPkgsKey: packageSetLoader,
containerPkgsKey: func(t *imageType) rpmmd.PackageSet {
return rpmmd.PackageSet{}
containerPkgsKey: func(t *imageType) (rpmmd.PackageSet, error) {
return rpmmd.PackageSet{}, nil
},
},
defaultImageConfig: &distro.ImageConfig{
@ -235,7 +243,7 @@ func mkIotSimplifiedInstallerImgType(d distribution) imageType {
payloadPipelines: []string{"ostree-deployment", "image", "xz", "coi-tree", "efiboot-tree", "bootiso-tree", "bootiso"},
exports: []string{"bootiso"},
basePartitionTables: iotSimplifiedInstallerPartitionTables,
kernelOptions: ostreeDeploymentKernelOptions,
kernelOptions: ostreeDeploymentKernelOptions(),
requiredPartitionSizes: requiredDirectorySizes,
}
}
@ -265,7 +273,7 @@ func mkIotRawImgType(d distribution) imageType {
payloadPipelines: []string{"ostree-deployment", "image", "xz"},
exports: []string{"xz"},
basePartitionTables: iotBasePartitionTables,
kernelOptions: ostreeDeploymentKernelOptions,
kernelOptions: ostreeDeploymentKernelOptions(),
// Passing an empty map into the required partition sizes disables the
// default partition sizes normally set so our `basePartitionTables` can
@ -297,7 +305,7 @@ func mkIotQcow2ImgType(d distribution) imageType {
payloadPipelines: []string{"ostree-deployment", "image", "qcow2"},
exports: []string{"qcow2"},
basePartitionTables: iotBasePartitionTables,
kernelOptions: ostreeDeploymentKernelOptions,
kernelOptions: ostreeDeploymentKernelOptions(),
requiredPartitionSizes: requiredDirectorySizes,
}
}
@ -314,7 +322,7 @@ func mkQcow2ImgType(d distribution) imageType {
defaultImageConfig: &distro.ImageConfig{
DefaultTarget: common.ToPtr("multi-user.target"),
},
kernelOptions: cloudKernelOptions,
kernelOptions: cloudKernelOptions(),
bootable: true,
defaultSize: 5 * datasizes.GibiByte,
image: diskImage,
@ -347,7 +355,7 @@ func mkVmdkImgType(d distribution) imageType {
osPkgsKey: packageSetLoader,
},
defaultImageConfig: vmdkDefaultImageConfig,
kernelOptions: cloudKernelOptions,
kernelOptions: cloudKernelOptions(),
bootable: true,
defaultSize: 2 * datasizes.GibiByte,
image: diskImage,
@ -368,7 +376,7 @@ func mkOvaImgType(d distribution) imageType {
osPkgsKey: packageSetLoader,
},
defaultImageConfig: vmdkDefaultImageConfig,
kernelOptions: cloudKernelOptions,
kernelOptions: cloudKernelOptions(),
bootable: true,
defaultSize: 2 * datasizes.GibiByte,
image: diskImage,
@ -412,6 +420,20 @@ func mkWslImgType(d distribution) imageType {
osPkgsKey: packageSetLoader,
},
defaultImageConfig: &distro.ImageConfig{
CloudInit: []*osbuild.CloudInitStageOptions{
{
Filename: "99_wsl.cfg",
Config: osbuild.CloudInitConfigFile{
DatasourceList: []string{
"WSL",
"None",
},
Network: &osbuild.CloudInitConfigNetwork{
Config: "disabled",
},
},
},
},
NoSElinux: common.ToPtr(true),
ExcludeDocs: common.ToPtr(true),
Locale: common.ToPtr("C.UTF-8"),
@ -432,7 +454,7 @@ func mkWslImgType(d distribution) imageType {
}
func mkMinimalRawImgType(d distribution) imageType {
return imageType{
it := imageType{
name: "minimal-raw",
filename: "disk.raw.xz",
compression: "xz",
@ -452,7 +474,7 @@ func mkMinimalRawImgType(d distribution) imageType {
InstallWeakDeps: common.ToPtr(common.VersionLessThan(d.osVersion, VERSION_MINIMAL_WEAKDEPS)),
},
rpmOstree: false,
kernelOptions: defaultKernelOptions,
kernelOptions: defaultKernelOptions(),
bootable: true,
defaultSize: 2 * datasizes.GibiByte,
image: diskImage,
@ -462,6 +484,12 @@ func mkMinimalRawImgType(d distribution) imageType {
basePartitionTables: minimalrawPartitionTables,
requiredPartitionSizes: requiredDirectorySizes,
}
if common.VersionGreaterThanOrEqual(d.osVersion, "43") {
// from Fedora 43 onward, we stop writing /etc/fstab and start using
// mount units only
it.defaultImageConfig.MountUnits = common.ToPtr(true)
}
return it
}
type distribution struct {
@ -478,6 +506,7 @@ type distribution struct {
// Fedora based OS image configuration defaults
var defaultDistroImageConfig = &distro.ImageConfig{
Hostname: common.ToPtr("localhost.localdomain"),
Timezone: common.ToPtr("UTC"),
Locale: common.ToPtr("C.UTF-8"),
DefaultOSCAPDatastream: common.ToPtr(oscap.DefaultFedoraDatastream()),

View file

@ -6,6 +6,7 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/anaconda"
@ -40,8 +41,8 @@ func osCustomizations(
osc.KernelName = c.GetKernel().Name
var kernelOptions []string
if t.kernelOptions != "" {
kernelOptions = append(kernelOptions, t.kernelOptions)
if len(t.kernelOptions) > 0 {
kernelOptions = append(kernelOptions, t.kernelOptions...)
}
if bpKernel := c.GetKernel(); bpKernel.Append != "" {
kernelOptions = append(kernelOptions, bpKernel.Append)
@ -106,8 +107,8 @@ func osCustomizations(
if hostname := c.GetHostname(); hostname != nil {
osc.Hostname = *hostname
} else {
osc.Hostname = "localhost.localdomain"
} else if imageConfig.Hostname != nil {
osc.Hostname = *imageConfig.Hostname
}
if imageConfig.InstallWeakDeps != nil {
@ -242,6 +243,10 @@ func osCustomizations(
osc.MachineIdUninitialized = *imageConfig.MachineIdUninitialized
}
if imageConfig.MountUnits != nil {
osc.MountUnits = *imageConfig.MountUnits
}
return osc, nil
}
@ -257,8 +262,8 @@ func ostreeDeploymentCustomizations(
deploymentConf := manifest.OSTreeDeploymentCustomizations{}
var kernelOptions []string
if t.kernelOptions != "" {
kernelOptions = append(kernelOptions, t.kernelOptions)
if len(t.kernelOptions) > 0 {
kernelOptions = append(kernelOptions, t.kernelOptions...)
}
if bpKernel := c.GetKernel(); bpKernel != nil && bpKernel.Append != "" {
kernelOptions = append(kernelOptions, bpKernel.Append)
@ -415,6 +420,11 @@ func liveInstallerImage(workload workload.Workload,
img.RootfsType = manifest.SquashfsRootfs
}
// Enable grub2 BIOS iso on x86_64 only
if img.Platform.GetArch() == arch.ARCH_X86_64 {
img.ISOBoot = manifest.Grub2ISOBoot
}
if locale := t.getDefaultImageConfig().Locale; locale != nil {
img.Locale = *locale
}
@ -516,6 +526,11 @@ func imageInstallerImage(workload workload.Workload,
img.RootfsType = manifest.SquashfsRootfs
}
// Enable grub2 BIOS iso on x86_64 only
if img.Platform.GetArch() == arch.ARCH_X86_64 {
img.ISOBoot = manifest.Grub2ISOBoot
}
return img, nil
}
@ -727,6 +742,11 @@ func iotInstallerImage(workload workload.Workload,
img.RootfsType = manifest.SquashfsRootfs
}
// Enable grub2 BIOS iso on x86_64 only
if img.Platform.GetArch() == arch.ARCH_X86_64 {
img.ISOBoot = manifest.Grub2ISOBoot
}
if locale := t.getDefaultImageConfig().Locale; locale != nil {
img.Locale = *locale
}

View file

@ -16,6 +16,7 @@ import (
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/experimentalflags"
"github.com/osbuild/images/pkg/image"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/platform"
@ -25,7 +26,7 @@ import (
type imageFunc func(workload workload.Workload, t *imageType, bp *blueprint.Blueprint, options distro.ImageOptions, packageSets map[string]rpmmd.PackageSet, containers []container.SourceSpec, rng *rand.Rand) (image.ImageKind, error)
type packageSetFunc func(t *imageType) rpmmd.PackageSet
type packageSetFunc func(t *imageType) (rpmmd.PackageSet, error)
type isoLabelFunc func(t *imageType) string
@ -42,7 +43,7 @@ type imageType struct {
packageSets map[string]packageSetFunc
defaultImageConfig *distro.ImageConfig
defaultInstallerConfig *distro.InstallerConfig
kernelOptions string
kernelOptions []string
defaultSize uint64
buildPipelines []string
payloadPipelines []string
@ -232,7 +233,11 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
// don't add any static packages if Minimal was selected
if !bp.Minimal {
for name, getter := range t.packageSets {
staticPackageSets[name] = getter(t)
pkgSet, err := getter(t)
if err != nil {
return nil, nil, err
}
staticPackageSets[name] = pkgSet
}
}
@ -278,6 +283,16 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
w = cw
}
if experimentalflags.Bool("no-fstab") {
if t.defaultImageConfig == nil {
t.defaultImageConfig = &distro.ImageConfig{
MountUnits: common.ToPtr(true),
}
} else {
t.defaultImageConfig.MountUnits = common.ToPtr(true)
}
}
containerSources := make([]container.SourceSpec, len(bp.Containers))
for idx, cont := range bp.Containers {
containerSources[idx] = container.SourceSpec{

View file

@ -5,6 +5,6 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
func packageSetLoader(t *imageType) rpmmd.PackageSet {
func packageSetLoader(t *imageType) (rpmmd.PackageSet, error) {
return packagesets.Load(t, "", VersionReplacements())
}

View file

@ -12,6 +12,7 @@ import (
// ImageConfig represents a (default) configuration applied to the image payload.
type ImageConfig struct {
Hostname *string
Timezone *string
TimeSynchronization *osbuild.ChronyStageOptions
Locale *string
@ -103,6 +104,10 @@ type ImageConfig struct {
// machine id to be set to 'uninitialized' which causes ConditionFirstboot
// to be triggered in systemd
MachineIdUninitialized *bool
// MountUnits creates systemd .mount units to describe the filesystem
// instead of writing to /etc/fstab
MountUnits *bool
}
// InheritFrom inherits unset values from the provided parent configuration and

File diff suppressed because it is too large Load diff

View file

@ -4,13 +4,18 @@ import (
"embed"
"fmt"
"io/fs"
"os"
"path/filepath"
"sort"
"strings"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/experimentalflags"
"github.com/osbuild/images/pkg/rpmmd"
)
@ -19,6 +24,15 @@ var data embed.FS
var DataFS fs.FS = data
type toplevelYAML struct {
ImageTypes map[string]imageType `yaml:"image_types"`
Common map[string]any `yaml:".common,omitempty"`
}
type imageType struct {
PackageSets []packageSet `yaml:"package_sets"`
}
type packageSet struct {
Include []string `yaml:"include"`
Exclude []string `yaml:"exclude"`
@ -36,7 +50,7 @@ type conditions struct {
// imagetype. By default the imagetype name is used to load the packageset
// but with "overrideTypeName" this can be overriden (useful for e.g.
// installer image types).
func Load(it distro.ImageType, overrideTypeName string, replacements map[string]string) rpmmd.PackageSet {
func Load(it distro.ImageType, overrideTypeName string, replacements map[string]string) (rpmmd.PackageSet, error) {
typeName := it.Name()
if overrideTypeName != "" {
typeName = overrideTypeName
@ -51,69 +65,109 @@ func Load(it distro.ImageType, overrideTypeName string, replacements map[string]
// distro names, sadly go has no rsplit() so we do it manually
// XXX: we cannot use distroidparser here because of import cycles
distroName := distroNameVer[:strings.LastIndex(distroNameVer, "-")]
distroVersion := distribution.OsVersion()
distroVersion := strings.SplitN(distroNameVer, "-", 2)[1]
distroNameMajorVer := strings.SplitN(distroNameVer, ".", 2)[0]
distroSets, err := DataFS.Open(filepath.Join(distroName, "package_sets.yaml"))
if err != nil {
panic(err)
// XXX: this is a short term measure, pass a set of
// searchPaths down the stack instead
var dataFS fs.FS = DataFS
if overrideDir := experimentalflags.String("yamldir"); overrideDir != "" {
logrus.Warnf("using experimental override dir %q", overrideDir)
dataFS = os.DirFS(overrideDir)
}
decoder := yaml.NewDecoder(distroSets)
// XXX: this is only needed temporary until we have a "distros.yaml"
// that describes some high-level properties of each distro
// (like their yaml dirs)
var baseDir string
switch distroName {
case "rhel":
// rhel yaml files are under ./rhel-$majorVer
baseDir = distroNameMajorVer
case "centos":
// centos yaml is just rhel but we have (sadly) no symlinks
// in "go:embed" so we have to have this slightly ugly
// workaround
baseDir = fmt.Sprintf("rhel-%s", distroVersion)
case "fedora", "test-distro":
// our other distros just have a single yaml dir per distro
// and use condition.version_gt etc
baseDir = distroName
default:
return rpmmd.PackageSet{}, fmt.Errorf("unsupported distro in loader %q (add to loader.go)", distroName)
}
f, err := dataFS.Open(filepath.Join(baseDir, "package_sets.yaml"))
if err != nil {
return rpmmd.PackageSet{}, err
}
defer f.Close()
decoder := yaml.NewDecoder(f)
decoder.KnownFields(true)
var pkgSets map[string]packageSet
if err := decoder.Decode(&pkgSets); err != nil {
panic(err)
// each imagetype can have multiple package sets, so that we can
// use yaml aliases/anchors to de-duplicate them
var toplevel toplevelYAML
if err := decoder.Decode(&toplevel); err != nil {
return rpmmd.PackageSet{}, err
}
pkgSet, ok := pkgSets[typeName]
imgType, ok := toplevel.ImageTypes[typeName]
if !ok {
panic(fmt.Sprintf("unknown package set name %q", typeName))
}
rpmmdPkgSet := rpmmd.PackageSet{
Include: pkgSet.Include,
Exclude: pkgSet.Exclude,
return rpmmd.PackageSet{}, fmt.Errorf("unknown image type name %q", typeName)
}
if pkgSet.Condition != nil {
// process conditions
if archSet, ok := pkgSet.Condition.Architecture[archName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: archSet.Include,
Exclude: archSet.Exclude,
})
}
if distroNameSet, ok := pkgSet.Condition.DistroName[distroName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: distroNameSet.Include,
Exclude: distroNameSet.Exclude,
})
}
var rpmmdPkgSet rpmmd.PackageSet
for _, pkgSet := range imgType.PackageSets {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: pkgSet.Include,
Exclude: pkgSet.Exclude,
})
for ltVer, ltSet := range pkgSet.Condition.VersionLessThan {
if r, ok := replacements[ltVer]; ok {
ltVer = r
}
if common.VersionLessThan(distroVersion, ltVer) {
if pkgSet.Condition != nil {
// process conditions
if archSet, ok := pkgSet.Condition.Architecture[archName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: ltSet.Include,
Exclude: ltSet.Exclude,
Include: archSet.Include,
Exclude: archSet.Exclude,
})
}
}
for gteqVer, gteqSet := range pkgSet.Condition.VersionGreaterOrEqual {
if r, ok := replacements[gteqVer]; ok {
gteqVer = r
}
if common.VersionGreaterThanOrEqual(distroVersion, gteqVer) {
if distroNameSet, ok := pkgSet.Condition.DistroName[distroName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: gteqSet.Include,
Exclude: gteqSet.Exclude,
Include: distroNameSet.Include,
Exclude: distroNameSet.Exclude,
})
}
for ltVer, ltSet := range pkgSet.Condition.VersionLessThan {
if r, ok := replacements[ltVer]; ok {
ltVer = r
}
if common.VersionLessThan(distroVersion, ltVer) {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: ltSet.Include,
Exclude: ltSet.Exclude,
})
}
}
for gteqVer, gteqSet := range pkgSet.Condition.VersionGreaterOrEqual {
if r, ok := replacements[gteqVer]; ok {
gteqVer = r
}
if common.VersionGreaterThanOrEqual(distroVersion, gteqVer) {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: gteqSet.Include,
Exclude: gteqSet.Exclude,
})
}
}
}
}
// mostly for tests
sort.Strings(rpmmdPkgSet.Include)
sort.Strings(rpmmdPkgSet.Exclude)
return rpmmdPkgSet
return rpmmdPkgSet, nil
}

View file

@ -0,0 +1,712 @@
---
.common:
distro_build_pkgset: &distro_build_pkgset
include:
- "dnf"
- "dosfstools"
- "e2fsprogs"
- "glibc"
- "lorax-templates-generic"
- "lorax-templates-rhel"
- "lvm2"
- "policycoreutils"
- "python3-iniparse"
- "qemu-img"
- "selinux-policy-targeted"
- "systemd"
- "tar"
- "xfsprogs"
- "xz"
condition:
architecture:
x86_64:
include:
- "grub2-pc"
ppc64el:
include:
- "grub2-ppc64le"
- "grub2-ppc64le-modules"
sap_pkgset: &sap_pkgset
include:
# RHBZ#2076763
- "@Server"
# SAP System Roles
# https:#access.redhat.com/sites/default/files/attachments/rhel_system_roles_for_sap_1.pdf
- "ansible-core"
- "rhel-system-roles-sap"
# RHBZ#1959813
- "bind-utils"
- "nfs-utils"
- "tcsh"
# RHBZ#1959955
- "uuidd"
# RHBZ#1959923
- "cairo"
- "expect"
- "graphviz"
# "gtk2" # gtk2 is not available in RHEL-10
- "iptraf-ng"
- "krb5-workstation"
- "libaio"
- "libatomic"
- "libicu"
- "libtool-ltdl"
- "lm_sensors"
- "net-tools"
- "numactl"
- "PackageKit-gtk3-module"
- "xorg-x11-xauth"
# RHBZ#1960617
- "tuned-profiles-sap-hana"
# RHBZ#1961168
- "libnsl"
exclude:
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
installer_pkgset: &installer_pkgset
include:
- "anaconda-dracut"
- "curl"
- "dracut-config-generic"
- "dracut-network"
- "hostname"
- "iwl100-firmware"
- "iwl1000-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "kernel"
- "less"
- "nfs-utils"
- "openssh-clients"
- "ostree"
- "plymouth"
- "prefixdevname"
- "rng-tools"
- "rpcbind"
- "selinux-policy-targeted"
- "systemd"
- "tar"
- "xfsprogs"
- "xz"
# Extra packages that are required by the dracut stage of all installers.
# These are weak deps of other packages in the list above, but lets be
# explicit about what we need and not rely on the weak deps. Relying
# on hard-dependencies for other modules is OK for now.
#
# TODO: add these dynamically based on the modules enabled by each
# pipeline.
- "mdadm"
- "nss-softokn"
anaconda_boot_pkgset: &anaconda_boot_pkgset
condition:
architecture:
x86_64:
include:
# eficommon
- "efibootmgr"
# XXX: de-dup?
# grub-common
- "grub2-tools"
- "grub2-tools-extra"
- "grub2-tools-minimal"
# arch specific
- "grub2-efi-x64"
- "grub2-efi-x64-cdboot"
- "grub2-pc"
- "grub2-pc-modules"
- "shim-x64"
- "syslinux"
- "syslinux-nonlinux"
aarch64:
include:
# eficommon
- "efibootmgr"
# XXX: de-dup?
# grub-common
- "grub2-tools"
- "grub2-tools-extra"
- "grub2-tools-minimal"
# arch specific
- "grub2-efi-aa64-cdboot"
- "grub2-efi-aa64"
- "shim-aa64"
image_types:
# XXX: not a real pkgset but the "os" pipeline pkgset for image-installer
# find a nicer way to represent this
bare_metal:
package_sets:
- *distro_build_pkgset
- include:
- "@core"
- "chrony"
- "cockpit-system"
- "cockpit-ws"
- "dnf-utils"
- "dosfstools"
- "firewalld"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "lvm2"
- "net-tools"
- "nfs-utils"
- "oddjob"
- "oddjob-mkhomedir"
- "policycoreutils"
- "psmisc"
- "python3-jsonschema"
- "qemu-guest-agent"
- "redhat-release"
- "redhat-release-eula"
- "rsync"
- "tar"
- "tcpdump"
- "tuned"
exclude:
- "dracut-config-rescue"
condition:
distro_name:
rhel:
include:
- "subscription-manager-cockpit"
qcow2: &qcow2
package_sets:
- include:
- "@core"
- "chrony"
- "cloud-init"
- "cloud-utils-growpart"
- "cockpit-system"
- "cockpit-ws"
- "dnf-utils"
- "dosfstools"
- "nfs-utils"
- "oddjob"
- "oddjob-mkhomedir"
- "psmisc"
- "python3-jsonschema"
- "qemu-guest-agent"
- "redhat-release"
- "redhat-release-eula"
- "rsync"
- "tar"
- "tuned"
- "tcpdump"
exclude:
- "aic94xx-firmware"
- "alsa-firmware"
- "alsa-lib"
- "alsa-tools-firmware"
- "biosdevname"
- "dnf-plugin-spacewalk"
- "dracut-config-rescue"
- "fedora-release"
- "fedora-repos"
- "firewalld"
- "iprutils"
- "ivtv-firmware"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "langpacks-*"
- "langpacks-en"
- "libertas-sd8787-firmware"
- "plymouth"
- "rng-tools"
- "udisks2"
condition:
distro_name:
rhel:
include:
- "insights-client"
- "subscription-manager-cockpit"
oci: *qcow2
vhd: &vhd
package_sets:
- &vhd_pkgset
include:
- "@Server"
- "bzip2"
- "cloud-init"
- "cloud-utils-growpart"
- "dracut-config-generic"
- "efibootmgr"
- "hyperv-daemons"
- "kernel-core"
- "kernel-modules"
- "kernel"
- "langpacks-en"
- "lvm2"
- "NetworkManager"
- "NetworkManager-cloud-setup"
- "nvme-cli"
- "patch"
- "rng-tools"
- "selinux-policy-targeted"
- "uuid"
- "WALinuxAgent"
- "yum-utils"
exclude:
- "aic94xx-firmware"
- "alsa-firmware"
- "alsa-lib"
- "alsa-sof-firmware"
- "alsa-tools-firmware"
- "biosdevname"
- "bolt"
- "buildah"
- "cockpit-podman"
- "containernetworking-plugins"
- "dnf-plugin-spacewalk"
- "dracut-config-rescue"
- "glibc-all-langpacks"
- "iprutils"
- "ivtv-firmware"
- "iwl100-firmware"
- "iwl1000-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "libertas-sd8686-firmware"
- "libertas-sd8787-firmware"
- "libertas-usb8388-firmware"
- "NetworkManager-config-server"
- "plymouth"
- "podman"
- "python3-dnf-plugin-spacewalk"
- "python3-hwdata"
- "python3-rhnlib"
- "rhn-check"
- "rhn-client-tools"
- "rhn-setup"
- "rhnlib"
- "rhnsd"
- "usb_modeswitch"
condition:
distro_name:
rhel:
include:
- "insights-client"
azure_rhui: *vhd
azure_sap_rhui:
package_sets:
- *vhd_pkgset
- *sap_pkgset
tar:
package_sets:
- include:
- "policycoreutils"
- "selinux-policy-targeted"
exclude:
- "rng-tools"
vmdk: &vmdk
package_sets:
- include:
- "@core"
- "chrony"
- "cloud-init"
- "firewalld"
- "langpacks-en"
- "open-vm-tools"
- "tuned"
exclude:
- "dracut-config-rescue"
- "rng-tools"
ova: *vmdk
ami: &ami
package_sets:
- &ami_pkgset
include:
- "@core"
- "chrony"
- "cloud-init"
- "cloud-utils-growpart"
- "dhcpcd"
- "yum-utils"
- "dracut-config-generic"
- "grub2"
- "langpacks-en"
- "NetworkManager-cloud-setup"
- "redhat-release"
- "redhat-release-eula"
- "rsync"
- "tuned"
- "tar"
exclude:
- "aic94xx-firmware"
- "alsa-firmware"
- "alsa-tools-firmware"
- "biosdevname"
- "firewalld"
- "iprutils"
- "ivtv-firmware"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "libertas-sd8686-firmware"
- "libertas-sd8787-firmware"
- "libertas-usb8388-firmware"
- "plymouth"
# RHBZ#2064087
- "dracut-config-rescue"
# RHBZ#2075815
- "qemu-guest-agent"
condition:
distro_name:
rhel:
include:
- "insights-client"
ec2: *ami
ec2_ha:
package_sets:
- *ami_pkgset
- include:
- "fence-agents-all"
- "pacemaker"
- "pcs"
ec2_sap:
package_sets:
- *ami_pkgset
- *sap_pkgset
wsl:
package_sets:
- include:
- "alternatives"
- "audit-libs"
- "basesystem"
- "bash"
- "ca-certificates"
- "cloud-init"
- "coreutils-single"
- "crypto-policies-scripts"
- "curl-minimal"
- "dejavu-sans-fonts"
- "dnf"
- "filesystem"
- "findutils"
- "gdb-gdbserver"
# Differs from official UBI, as we don't include CRB repos
# - "gdbm"
- "glibc-minimal-langpack"
- "gmp"
- "gnupg2"
- "gobject-introspection"
- "hostname"
- "langpacks-en"
- "libcurl-minimal"
- "openssl"
- "pam"
- "passwd"
- "procps-ng"
- "python3"
- "python3-inotify"
- "redhat-release"
- "rootfiles"
- "rpm"
- "sed"
- "setup"
- "shadow-utils"
- "subscription-manager"
- "systemd"
- "tar"
- "tpm2-tss"
- "tzdata"
- "util-linux"
- "vim-minimal"
- "yum"
exclude:
- "gawk-all-langpacks"
- "glibc-gconv-extra"
- "glibc-langpack-en"
- "openssl-pkcs11"
- "python-unversioned-command"
- "redhat-release-eula"
- "rpm-plugin-systemd-inhibit"
image_installer:
package_sets:
- *installer_pkgset
- *anaconda_boot_pkgset
- include:
- "@hardware-support"
- "alsa-firmware"
- "alsa-tools-firmware"
- "anaconda"
- "anaconda-dracut"
- "anaconda-install-img-deps"
- "anaconda-widgets"
- "audit"
- "bind-utils"
- "bzip2"
- "cryptsetup"
- "curl"
- "dbus-x11"
- "default-fonts-core-sans"
- "default-fonts-other-sans"
- "dejavu-sans-fonts"
- "dejavu-sans-mono-fonts"
- "device-mapper-persistent-data"
- "dmidecode"
- "dnf"
- "dracut-config-generic"
- "dracut-network"
- "efibootmgr"
- "ethtool"
- "fcoe-utils"
- "ftp"
- "gdb-gdbserver"
- "glibc-all-langpacks"
- "gnome-kiosk"
- "google-noto-sans-cjk-ttc-fonts"
- "grub2-tools"
- "grub2-tools-extra"
- "grub2-tools-minimal"
- "grubby"
- "gsettings-desktop-schemas"
- "hdparm"
- "hexedit"
- "hostname"
- "initscripts"
- "ipmitool"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "jomolhari-fonts"
- "kbd"
- "kbd-misc"
- "kdump-anaconda-addon"
- "kernel"
- "less"
- "libblockdev-lvm-dbus"
- "libibverbs"
- "librsvg2"
- "linux-firmware"
- "lldpad"
- "lsof"
- "madan-fonts"
- "mtr"
- "mt-st"
- "net-tools"
- "nfs-utils"
- "nmap-ncat"
- "nm-connection-editor"
- "nss-tools"
- "openssh-clients"
- "openssh-server"
# the package is not yet available on c10s / el10
# "oscap-anaconda-addon"
- "ostree"
- "pciutils"
- "perl-interpreter"
- "pigz"
- "plymouth"
- "prefixdevname"
- "python3-pyatspi"
- "rdma-core"
- "redhat-release-eula"
- "rng-tools"
- "rpcbind"
- "rpm-ostree"
- "rsync"
- "rsyslog"
- "selinux-policy-targeted"
- "sg3_utils"
- "sil-padauk-fonts"
- "smartmontools"
- "spice-vdagent"
- "strace"
- "systemd"
- "tar"
- "udisks2"
- "udisks2-iscsi"
- "usbutils"
- "vim-minimal"
- "volume_key"
- "wget"
- "xfsdump"
- "xfsprogs"
- "xz"
condition:
architecture:
x86_64:
include:
- "biosdevname"
- "dmidecode"
- "grub2-tools-efi"
- "memtest86+"
aarch64:
include:
- "dmidecode"
gce:
package_sets:
- include:
- "@core"
- "langpacks-en" # not in Google's KS
- "acpid"
- "dnf-automatic"
- "net-tools"
- "python3"
- "rng-tools"
- "tar"
- "vim"
# GCE guest tools
# TODO: uncomment once the package is available
# the el9 version depends on libboost_regex.so.1.75.0()(64bit), which is not available on el10
# - "google-compute-engine"
- "google-osconfig-agent"
# Requires gdisk which was removed late in the RHEL 10 development cycle
# - "gce-disk-expand"
# cloud-init is a replacement for- "google-compute-engine" remove once the package is available
- "cloud-init"
# Not explicitly included in GCP kickstart, but present on the image
# for time synchronization
- "chrony"
- "timedatex"
# EFI
- "grub2-tools"
- "grub2-tools-minimal"
# Performance tuning
- "tuned"
exclude:
- "alsa-utils"
- "b43-fwcutter"
- "dmraid"
- "dracut-config-rescue"
- "eject"
- "gpm"
- "irqbalance"
- "microcode_ctl"
- "smartmontools"
- "aic94xx-firmware"
- "atmel-firmware"
- "b43-openfwwf"
- "bfa-firmware"
- "ipw2100-firmware"
- "ipw2200-firmware"
- "ivtv-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl1000-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "kernel-firmware"
- "libertas-usb8388-firmware"
- "ql2100-firmware"
- "ql2200-firmware"
- "ql23xx-firmware"
- "ql2400-firmware"
- "ql2500-firmware"
- "rt61pci-firmware"
- "rt73usb-firmware"
- "xorg-x11-drv-ati-firmware"
- "zd1211-firmware"
# RHBZ#2075815
- "qemu-guest-agent"
condition:
distro_name:
rhel:
include:
- "insights-client"

View file

@ -5,6 +5,7 @@ import (
"math/rand"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/anaconda"
@ -39,8 +40,8 @@ func osCustomizations(
osc.KernelName = c.GetKernel().Name
var kernelOptions []string
if t.KernelOptions != "" {
kernelOptions = append(kernelOptions, t.KernelOptions)
if len(t.KernelOptions) > 0 {
kernelOptions = append(kernelOptions, t.KernelOptions...)
}
if bpKernel := c.GetKernel(); bpKernel.Append != "" {
kernelOptions = append(kernelOptions, bpKernel.Append)
@ -283,6 +284,10 @@ func osCustomizations(
osc.InstallWeakDeps = *imageConfig.InstallWeakDeps
}
if imageConfig.MountUnits != nil {
osc.MountUnits = *imageConfig.MountUnits
}
return osc, nil
}
@ -298,8 +303,8 @@ func ostreeDeploymentCustomizations(
deploymentConf := manifest.OSTreeDeploymentCustomizations{}
var kernelOptions []string
if t.KernelOptions != "" {
kernelOptions = append(kernelOptions, t.KernelOptions)
if len(t.KernelOptions) > 0 {
kernelOptions = append(kernelOptions, t.KernelOptions...)
}
if bpKernel := c.GetKernel(); bpKernel != nil && bpKernel.Append != "" {
kernelOptions = append(kernelOptions, bpKernel.Append)
@ -357,6 +362,10 @@ func ostreeDeploymentCustomizations(
deploymentConf.CustomFileSystems = append(deploymentConf.CustomFileSystems, fs.Mountpoint)
}
if imageConfig.MountUnits != nil {
deploymentConf.MountUnits = *imageConfig.MountUnits
}
return deploymentConf, nil
}
@ -504,6 +513,17 @@ func EdgeInstallerImage(workload workload.Workload,
img.RootfsType = manifest.SquashfsRootfs
}
// Enable BIOS iso on x86_64 only
// Use grub2 on RHEL10, otherwise use syslinux
// NOTE: Will need to be updated for RHEL11 and later
if img.Platform.GetArch() == arch.ARCH_X86_64 {
if t.Arch().Distro().Releasever() == "10" {
img.ISOBoot = manifest.Grub2ISOBoot
} else {
img.ISOBoot = manifest.SyslinuxISOBoot
}
}
installerConfig, err := t.getDefaultInstallerConfig()
if err != nil {
return nil, err
@ -730,6 +750,17 @@ func ImageInstallerImage(workload workload.Workload,
img.RootfsType = manifest.SquashfsRootfs
}
// Enable BIOS iso on x86_64 only
// Use grub2 on RHEL10, otherwise use syslinux
// NOTE: Will need to be updated for RHEL11 and later
if img.Platform.GetArch() == arch.ARCH_X86_64 {
if t.Arch().Distro().Releasever() == "10" {
img.ISOBoot = manifest.Grub2ISOBoot
} else {
img.ISOBoot = manifest.SyslinuxISOBoot
}
}
// put the kickstart file in the root of the iso
img.ISORootKickstart = true

View file

@ -6,6 +6,7 @@ import (
"slices"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/blueprint"
@ -13,6 +14,7 @@ import (
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/experimentalflags"
"github.com/osbuild/images/pkg/image"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/osbuild"
@ -76,7 +78,7 @@ type ImageType struct {
Compression string // TODO: remove from image definition and make it a transport option
DefaultImageConfig *distro.ImageConfig
DefaultInstallerConfig *distro.InstallerConfig
KernelOptions string
KernelOptions []string
DefaultSize uint64
// bootISO: installable ISO
@ -338,6 +340,16 @@ func (t *ImageType) Manifest(bp *blueprint.Blueprint,
}
}
if experimentalflags.Bool("no-fstab") {
if t.DefaultImageConfig == nil {
t.DefaultImageConfig = &distro.ImageConfig{
MountUnits: common.ToPtr(true),
}
} else {
t.DefaultImageConfig.MountUnits = common.ToPtr(true)
}
}
source := rand.NewSource(seed)
// math/rand is good enough in this case
/* #nosec G404 */

View file

@ -6,16 +6,29 @@ import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
)
// TODO: move these to the EC2 environment
func amiKernelOptions() []string {
return []string{"console=tty0", "console=ttyS0,115200n8", "nvme_core.io_timeout=4294967295"}
}
func amiAarch64KernelOptions() []string {
return append(amiKernelOptions(), "iommu.strict=0")
}
func amiSapKernelOptions() []string {
return append(amiKernelOptions(), []string{"processor.max_cstate=1", "intel_idle.max_cstate=1"}...)
}
func mkAMIImgTypeX86_64() *rhel.ImageType {
it := rhel.NewImageType(
"ami",
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: ec2PackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -23,7 +36,7 @@ func mkAMIImgTypeX86_64() *rhel.ImageType {
[]string{"image"},
)
it.KernelOptions = amiKernelOptions
it.KernelOptions = amiKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
@ -38,7 +51,7 @@ func mkAMIImgTypeAarch64() *rhel.ImageType {
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: ec2PackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -46,7 +59,7 @@ func mkAMIImgTypeAarch64() *rhel.ImageType {
[]string{"image"},
)
it.KernelOptions = amiAarch64KernelOptions
it.KernelOptions = amiAarch64KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfig()
@ -62,7 +75,7 @@ func mkEc2ImgTypeX86_64() *rhel.ImageType {
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: ec2PackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -71,7 +84,7 @@ func mkEc2ImgTypeX86_64() *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = amiKernelOptions
it.KernelOptions = amiKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
@ -87,7 +100,7 @@ func mkEC2ImgTypeAarch64() *rhel.ImageType {
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: ec2PackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -96,7 +109,7 @@ func mkEC2ImgTypeAarch64() *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = amiAarch64KernelOptions
it.KernelOptions = amiAarch64KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfig()
@ -112,7 +125,7 @@ func mkEc2HaImgTypeX86_64() *rhel.ImageType {
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: rhelEc2HaPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -121,7 +134,7 @@ func mkEc2HaImgTypeX86_64() *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = amiKernelOptions
it.KernelOptions = amiKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
@ -136,7 +149,7 @@ func mkEC2SapImgTypeX86_64(osVersion string) *rhel.ImageType {
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: rhelEc2SapPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -145,7 +158,7 @@ func mkEC2SapImgTypeX86_64(osVersion string) *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = amiSapKernelOptions
it.KernelOptions = amiSapKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = sapImageConfig(osVersion).InheritFrom(defaultEc2ImageConfigX86_64())
@ -156,13 +169,6 @@ func mkEC2SapImgTypeX86_64(osVersion string) *rhel.ImageType {
// IMAGE CONFIG
// TODO: move these to the EC2 environment
const (
amiKernelOptions = "console=tty0 console=ttyS0,115200n8 nvme_core.io_timeout=4294967295"
amiAarch64KernelOptions = amiKernelOptions + " iommu.strict=0"
amiSapKernelOptions = amiKernelOptions + " processor.max_cstate=1 intel_idle.max_cstate=1"
)
// default EC2 images config (common for all architectures)
func defaultEc2ImageConfig() *distro.ImageConfig {
return &distro.ImageConfig{
@ -287,84 +293,3 @@ func defaultEc2ImageConfigX86_64() *distro.ImageConfig {
ic := defaultEc2ImageConfig()
return appendEC2DracutX86_64(ic)
}
// PACKAGE SETS
func ec2PackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"@core",
"chrony",
"cloud-init",
"cloud-utils-growpart",
"dhcpcd",
"yum-utils",
"dracut-config-generic",
"grub2",
"langpacks-en",
"NetworkManager-cloud-setup",
"redhat-release",
"redhat-release-eula",
"rsync",
"tuned",
"tar",
},
Exclude: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-tools-firmware",
"biosdevname",
"firewalld",
"iprutils",
"ivtv-firmware",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"libertas-sd8686-firmware",
"libertas-sd8787-firmware",
"libertas-usb8388-firmware",
"plymouth",
// RHBZ#2064087
"dracut-config-rescue",
// RHBZ#2075815
"qemu-guest-agent",
},
}.Append(distroSpecificPackageSet(t))
return ps
}
// rhel-ha-ec2 image package set
func rhelEc2HaPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ec2HaPackageSet := ec2PackageSet(t)
ec2HaPackageSet = ec2HaPackageSet.Append(rpmmd.PackageSet{
Include: []string{
"fence-agents-all",
"pacemaker",
"pcs",
},
})
return ec2HaPackageSet
}
// rhel-sap-ec2 image package set
func rhelEc2SapPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
return rpmmd.PackageSet{
Include: []string{
//"libcanberra-gtk2", // libcanberra-gtk2 is not available in RHEL-10
},
}.Append(ec2PackageSet(t)).Append(SapPackageSet(t))
}

View file

@ -8,7 +8,6 @@ import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
)
// Azure image type
@ -18,7 +17,7 @@ func mkAzureImgType(rd *rhel.Distribution) *rhel.ImageType {
"disk.vhd",
"application/x-vhd",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: azurePackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -26,7 +25,7 @@ func mkAzureImgType(rd *rhel.Distribution) *rhel.ImageType {
[]string{"vpc"},
)
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.DefaultImageConfig = defaultAzureImageConfig(rd)
@ -42,7 +41,7 @@ func mkAzureInternalImgType(rd *rhel.Distribution) *rhel.ImageType {
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: azurePackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -51,7 +50,7 @@ func mkAzureInternalImgType(rd *rhel.Distribution) *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.DefaultImageConfig = defaultAzureImageConfig(rd)
@ -66,7 +65,7 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution) *rhel.ImageType {
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: azureSapPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -75,7 +74,7 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution) *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.DefaultImageConfig = sapAzureImageConfig(rd)
@ -84,98 +83,6 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution) *rhel.ImageType {
return it
}
// PACKAGE SETS
// Common Azure image package set
func azureCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"@Server",
"bzip2",
"cloud-init",
"cloud-utils-growpart",
"dracut-config-generic",
"efibootmgr",
"hyperv-daemons",
"kernel-core",
"kernel-modules",
"kernel",
"langpacks-en",
"lvm2",
"NetworkManager",
"NetworkManager-cloud-setup",
"nvme-cli",
"patch",
"rng-tools",
"selinux-policy-targeted",
"uuid",
"WALinuxAgent",
"yum-utils",
},
Exclude: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
"alsa-sof-firmware",
"alsa-tools-firmware",
"biosdevname",
"bolt",
"buildah",
"cockpit-podman",
"containernetworking-plugins",
"dnf-plugin-spacewalk",
"dracut-config-rescue",
"glibc-all-langpacks",
"iprutils",
"ivtv-firmware",
"iwl100-firmware",
"iwl1000-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"libertas-sd8686-firmware",
"libertas-sd8787-firmware",
"libertas-usb8388-firmware",
"NetworkManager-config-server",
"plymouth",
"podman",
"python3-dnf-plugin-spacewalk",
"python3-hwdata",
"python3-rhnlib",
"rhn-check",
"rhn-client-tools",
"rhn-setup",
"rhnlib",
"rhnsd",
"usb_modeswitch",
},
}.Append(distroSpecificPackageSet(t))
return ps
}
// Azure BYOS image package set
func azurePackageSet(t *rhel.ImageType) rpmmd.PackageSet {
return azureCommonPackageSet(t)
}
// Azure SAP image package set
// Includes the common azure package set, the common SAP packages
func azureSapPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
return azureCommonPackageSet(t).Append(SapPackageSet(t))
}
// PARTITION TABLES
func azureInternalBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
switch t.Arch().Name() {
@ -401,7 +308,9 @@ func azureInternalBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, b
// IMAGE CONFIG
// use loglevel=3 as described in the RHEL documentation and used in existing RHEL images built by MSFT
const defaultAzureKernelOptions = "ro loglevel=3 console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300"
func defaultAzureKernelOptions() []string {
return []string{"ro", "loglevel=3", "console=tty1", "console=ttyS0", "earlyprintk=ttyS0", "rootdelay=300"}
}
// based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure
func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig {

View file

@ -1,10 +1,9 @@
package rhel10
import (
"fmt"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/packagesets"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
@ -15,12 +14,7 @@ func mkTarImgType() *rhel.ImageType {
"root.tar.xz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: func(t *rhel.ImageType) rpmmd.PackageSet {
return rpmmd.PackageSet{
Include: []string{"policycoreutils", "selinux-policy-targeted"},
Exclude: []string{"rng-tools"},
}
},
rhel.OSPkgsKey: packageSetLoader,
},
rhel.TarImage,
[]string{"build"},
@ -35,8 +29,10 @@ func mkImageInstallerImgType() *rhel.ImageType {
"installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: bareMetalPackageSet,
rhel.InstallerPkgsKey: anacondaPackageSet,
rhel.OSPkgsKey: func(t *rhel.ImageType) rpmmd.PackageSet {
return common.Must(packagesets.Load(t, "bare-metal", nil))
},
rhel.InstallerPkgsKey: packageSetLoader,
},
rhel.ImageInstallerImage,
[]string{"build"},
@ -63,268 +59,3 @@ func mkImageInstallerImgType() *rhel.ImageType {
return it
}
// PACKAGE SETS
func bareMetalPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"@core",
"chrony",
"cockpit-system",
"cockpit-ws",
"dnf-utils",
"dosfstools",
"firewalld",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"lvm2",
"net-tools",
"nfs-utils",
"oddjob",
"oddjob-mkhomedir",
"policycoreutils",
"psmisc",
"python3-jsonschema",
"qemu-guest-agent",
"redhat-release",
"redhat-release-eula",
"rsync",
"tar",
"tcpdump",
"tuned",
},
Exclude: []string{
"dracut-config-rescue",
},
}.Append(distroBuildPackageSet(t))
// Ensure to not pull in subscription-manager on non-RHEL distro
if t.IsRHEL() {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"subscription-manager-cockpit",
},
})
}
return ps
}
func installerPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"anaconda-dracut",
"curl",
"dracut-config-generic",
"dracut-network",
"hostname",
"iwl100-firmware",
"iwl1000-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"kernel",
"less",
"nfs-utils",
"openssh-clients",
"ostree",
"plymouth",
"prefixdevname",
"rng-tools",
"rpcbind",
"selinux-policy-targeted",
"systemd",
"tar",
"xfsprogs",
"xz",
},
}
ps = ps.Append(rpmmd.PackageSet{
// Extra packages that are required by the dracut stage of all installers.
// These are weak deps of other packages in the list above, but lets be
// explicit about what we need and not rely on the weak deps. Relying
// on hard-dependencies for other modules is OK for now.
//
// TODO: add these dynamically based on the modules enabled by each
// pipeline.
Include: []string{
"mdadm",
"nss-softokn",
},
})
switch t.Arch().Name() {
case arch.ARCH_X86_64.String():
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"biosdevname",
},
})
}
return ps
}
func anacondaPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
// common installer packages
ps := installerPackageSet(t)
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"@hardware-support",
"alsa-firmware",
"alsa-tools-firmware",
"anaconda",
"anaconda-dracut",
"anaconda-install-img-deps",
"anaconda-widgets",
"audit",
"bind-utils",
"bzip2",
"cryptsetup",
"curl",
"dbus-x11",
"default-fonts-core-sans",
"default-fonts-other-sans",
"dejavu-sans-fonts",
"dejavu-sans-mono-fonts",
"device-mapper-persistent-data",
"dmidecode",
"dnf",
"dracut-config-generic",
"dracut-network",
"efibootmgr",
"ethtool",
"fcoe-utils",
"ftp",
"gdb-gdbserver",
"glibc-all-langpacks",
"gnome-kiosk",
"google-noto-sans-cjk-ttc-fonts",
"grub2-tools",
"grub2-tools-extra",
"grub2-tools-minimal",
"grubby",
"gsettings-desktop-schemas",
"hdparm",
"hexedit",
"hostname",
"initscripts",
"ipmitool",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"jomolhari-fonts",
"kbd",
"kbd-misc",
"kdump-anaconda-addon",
"kernel",
"less",
"libblockdev-lvm-dbus",
"libibverbs",
"librsvg2",
"linux-firmware",
"lldpad",
"lsof",
"madan-fonts",
"mtr",
"mt-st",
"net-tools",
"nfs-utils",
"nmap-ncat",
"nm-connection-editor",
"nss-tools",
"openssh-clients",
"openssh-server",
// the package is not yet available on c10s / el10
//"oscap-anaconda-addon",
"ostree",
"pciutils",
"perl-interpreter",
"pigz",
"plymouth",
"prefixdevname",
"python3-pyatspi",
"rdma-core",
"redhat-release-eula",
"rng-tools",
"rpcbind",
"rpm-ostree",
"rsync",
"rsyslog",
"selinux-policy-targeted",
"sg3_utils",
"sil-padauk-fonts",
"smartmontools",
"spice-vdagent",
"strace",
"systemd",
"tar",
"udisks2",
"udisks2-iscsi",
"usbutils",
"vim-minimal",
"volume_key",
"wget",
"xfsdump",
"xfsprogs",
"xz",
},
})
ps = ps.Append(anacondaBootPackageSet(t))
switch t.Arch().Name() {
case arch.ARCH_X86_64.String():
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"biosdevname",
"dmidecode",
"grub2-tools-efi",
"memtest86+",
},
})
case arch.ARCH_AARCH64.String():
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"dmidecode",
},
})
default:
panic(fmt.Sprintf("unsupported arch: %s", t.Arch().Name()))
}
return ps
}

View file

@ -6,10 +6,11 @@ import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
)
const gceKernelOptions = "biosdevname=0 scsi_mod.use_blk_mq=Y console=ttyS0,38400n8d"
func gceKernelOptions() []string {
return []string{"biosdevname=0", "scsi_mod.use_blk_mq=Y", "console=ttyS0,38400n8d"}
}
func mkGCEImageType() *rhel.ImageType {
it := rhel.NewImageType(
@ -17,7 +18,7 @@ func mkGCEImageType() *rhel.ImageType {
"image.tar.gz",
"application/gzip",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: gcePackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -26,7 +27,7 @@ func mkGCEImageType() *rhel.ImageType {
)
it.DefaultImageConfig = baseGCEImageConfig()
it.KernelOptions = gceKernelOptions
it.KernelOptions = gceKernelOptions()
it.DefaultSize = 20 * datasizes.GibiByte
it.Bootable = true
// TODO: the base partition table still contains the BIOS boot partition, but the image is UEFI-only
@ -135,92 +136,3 @@ func baseGCEImageConfig() *distro.ImageConfig {
return ic
}
func gceCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"@core",
"langpacks-en", // not in Google's KS
"acpid",
"dnf-automatic",
"net-tools",
"python3",
"rng-tools",
"tar",
"vim",
// GCE guest tools
// TODO: uncomment once the package is available
// the el9 version depends on libboost_regex.so.1.75.0()(64bit), which is not available on el10
//"google-compute-engine",
"google-osconfig-agent",
// Requires gdisk which was removed late in the RHEL 10 development cycle
// "gce-disk-expand",
// cloud-init is a replacement for "google-compute-engine", remove once the package is available
"cloud-init",
// Not explicitly included in GCP kickstart, but present on the image
// for time synchronization
"chrony",
"timedatex",
// EFI
"grub2-tools",
"grub2-tools-minimal",
// Performance tuning
"tuned",
},
Exclude: []string{
"alsa-utils",
"b43-fwcutter",
"dmraid",
"dracut-config-rescue",
"eject",
"gpm",
"irqbalance",
"microcode_ctl",
"smartmontools",
"aic94xx-firmware",
"atmel-firmware",
"b43-openfwwf",
"bfa-firmware",
"ipw2100-firmware",
"ipw2200-firmware",
"ivtv-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl1000-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"kernel-firmware",
"libertas-usb8388-firmware",
"ql2100-firmware",
"ql2200-firmware",
"ql23xx-firmware",
"ql2400-firmware",
"ql2500-firmware",
"rt61pci-firmware",
"rt73usb-firmware",
"xorg-x11-drv-ati-firmware",
"zd1211-firmware",
// RHBZ#2075815
"qemu-guest-agent",
},
}.Append(distroSpecificPackageSet(t))
return ps
}
// GCE image
func gcePackageSet(t *rhel.ImageType) rpmmd.PackageSet {
return gceCommonPackageSet(t)
}

View file

@ -3,130 +3,12 @@ package rhel10
// This file defines package sets that are used by more than one image type.
import (
"fmt"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro/packagesets"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
// BUILD PACKAGE SETS
// distro-wide build package set
func distroBuildPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"dnf",
"dosfstools",
"e2fsprogs",
"glibc",
"lorax-templates-generic",
"lorax-templates-rhel",
"lvm2",
"policycoreutils",
"python3-iniparse",
"qemu-img",
"selinux-policy-targeted",
"systemd",
"tar",
"xfsprogs",
"xz",
},
}
switch t.Arch().Name() {
case arch.ARCH_X86_64.String():
ps = ps.Append(x8664BuildPackageSet(t))
case arch.ARCH_PPC64LE.String():
ps = ps.Append(ppc64leBuildPackageSet(t))
}
return ps
}
// x86_64 build package set
func x8664BuildPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
return rpmmd.PackageSet{
Include: []string{
"grub2-pc",
},
}
}
// ppc64le build package set
func ppc64leBuildPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
return rpmmd.PackageSet{
Include: []string{
"grub2-ppc64le",
"grub2-ppc64le-modules",
},
}
}
// installer boot package sets, needed for booting and
// also in the build host
func anacondaBootPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{}
grubCommon := rpmmd.PackageSet{
Include: []string{
"grub2-tools",
"grub2-tools-extra",
"grub2-tools-minimal",
},
}
efiCommon := rpmmd.PackageSet{
Include: []string{
"efibootmgr",
},
}
switch t.Arch().Name() {
case arch.ARCH_X86_64.String():
ps = ps.Append(grubCommon)
ps = ps.Append(efiCommon)
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"grub2-efi-x64",
"grub2-efi-x64-cdboot",
"grub2-pc",
"grub2-pc-modules",
"shim-x64",
"syslinux",
"syslinux-nonlinux",
},
})
case arch.ARCH_AARCH64.String():
ps = ps.Append(grubCommon)
ps = ps.Append(efiCommon)
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"grub2-efi-aa64-cdboot",
"grub2-efi-aa64",
"shim-aa64",
},
})
default:
panic(fmt.Sprintf("unsupported arch: %s", t.Arch().Name()))
}
return ps
}
// OS package sets
// packages that are only in some (sub)-distributions
func distroSpecificPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
if t.IsRHEL() {
return rpmmd.PackageSet{
Include: []string{
"insights-client",
},
}
}
return rpmmd.PackageSet{}
func packageSetLoader(t *rhel.ImageType) rpmmd.PackageSet {
return common.Must(packagesets.Load(t, "", nil))
}

View file

@ -6,7 +6,6 @@ import (
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
func mkQcow2ImgType(d *rhel.Distribution) *rhel.ImageType {
@ -15,7 +14,7 @@ func mkQcow2ImgType(d *rhel.Distribution) *rhel.ImageType {
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: qcow2CommonPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -24,7 +23,7 @@ func mkQcow2ImgType(d *rhel.Distribution) *rhel.ImageType {
)
it.DefaultImageConfig = qcowImageConfig(d)
it.KernelOptions = "console=tty0 console=ttyS0,115200n8 no_timer_check"
it.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check"}
it.DefaultSize = 10 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables
@ -38,7 +37,7 @@ func mkOCIImgType(d *rhel.Distribution) *rhel.ImageType {
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: qcow2CommonPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -47,7 +46,7 @@ func mkOCIImgType(d *rhel.Distribution) *rhel.ImageType {
)
it.DefaultImageConfig = qcowImageConfig(d)
it.KernelOptions = "console=tty0 console=ttyS0,115200n8 no_timer_check"
it.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check"}
it.DefaultSize = 10 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables
@ -55,80 +54,6 @@ func mkOCIImgType(d *rhel.Distribution) *rhel.ImageType {
return it
}
func qcow2CommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"@core",
"chrony",
"cloud-init",
"cloud-utils-growpart",
"cockpit-system",
"cockpit-ws",
"dnf-utils",
"dosfstools",
"nfs-utils",
"oddjob",
"oddjob-mkhomedir",
"psmisc",
"python3-jsonschema",
"qemu-guest-agent",
"redhat-release",
"redhat-release-eula",
"rsync",
"tar",
"tuned",
"tcpdump",
},
Exclude: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
"alsa-tools-firmware",
"biosdevname",
"dnf-plugin-spacewalk",
"dracut-config-rescue",
"fedora-release",
"fedora-repos",
"firewalld",
"iprutils",
"ivtv-firmware",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"langpacks-*",
"langpacks-en",
"libertas-sd8787-firmware",
"plymouth",
"rng-tools",
"udisks2",
},
}.Append(distroSpecificPackageSet(t))
// Ensure to not pull in subscription-manager on non-RHEL distro
if t.IsRHEL() {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"subscription-manager-cockpit",
},
})
}
return ps
}
func qcowImageConfig(d *rhel.Distribution) *distro.ImageConfig {
ic := &distro.ImageConfig{
DefaultTarget: common.ToPtr("multi-user.target"),

View file

@ -2,9 +2,7 @@ package rhel10
import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
)
// sapImageConfig returns the SAP specific ImageConfig data
@ -118,57 +116,3 @@ func sapImageConfig(osVersion string) *distro.ImageConfig {
},
}
}
func SapPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
return rpmmd.PackageSet{
Include: []string{
// RHBZ#2076763
"@Server",
// SAP System Roles
// https://access.redhat.com/sites/default/files/attachments/rhel_system_roles_for_sap_1.pdf
"ansible-core",
"rhel-system-roles-sap",
// RHBZ#1959813
"bind-utils",
"nfs-utils",
"tcsh",
// RHBZ#1959955
"uuidd",
// RHBZ#1959923
"cairo",
"expect",
"graphviz",
//"gtk2", // gtk2 is not available in RHEL-10
"iptraf-ng",
"krb5-workstation",
"libaio",
"libatomic",
"libicu",
"libtool-ltdl",
"lm_sensors",
"net-tools",
"numactl",
"PackageKit-gtk3-module",
"xorg-x11-xauth",
// RHBZ#1960617
"tuned-profiles-sap-hana",
// RHBZ#1961168
"libnsl",
},
Exclude: []string{
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
},
}
}

View file

@ -5,7 +5,6 @@ import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
)
func mkWSLImgType() *rhel.ImageType {
@ -14,7 +13,7 @@ func mkWSLImgType() *rhel.ImageType {
"disk.tar.gz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: ubiCommonPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.TarImage,
[]string{"build"},
@ -23,6 +22,20 @@ func mkWSLImgType() *rhel.ImageType {
)
it.DefaultImageConfig = &distro.ImageConfig{
CloudInit: []*osbuild.CloudInitStageOptions{
{
Filename: "99_wsl.cfg",
Config: osbuild.CloudInitConfigFile{
DatasourceList: []string{
"WSL",
"None",
},
Network: &osbuild.CloudInitConfigNetwork{
Config: "disabled",
},
},
},
},
NoSElinux: common.ToPtr(true),
WSLConfig: &osbuild.WSLConfStageOptions{
Boot: osbuild.WSLConfBootOptions{
@ -33,63 +46,3 @@ func mkWSLImgType() *rhel.ImageType {
return it
}
func ubiCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"alternatives",
"audit-libs",
"basesystem",
"bash",
"ca-certificates",
"coreutils-single",
"crypto-policies-scripts",
"curl-minimal",
"dejavu-sans-fonts",
"dnf",
"filesystem",
"findutils",
"gdb-gdbserver",
// Differs from official UBI, as we don't include CRB repos
// "gdbm",
"glibc-minimal-langpack",
"gmp",
"gnupg2",
"gobject-introspection",
"hostname",
"langpacks-en",
"libcurl-minimal",
"openssl",
"pam",
"passwd",
"procps-ng",
"python3",
"python3-inotify",
"redhat-release",
"rootfiles",
"rpm",
"sed",
"setup",
"shadow-utils",
"subscription-manager",
"systemd",
"tar",
"tpm2-tss",
"tzdata",
"util-linux",
"vim-minimal",
"yum",
},
Exclude: []string{
"gawk-all-langpacks",
"glibc-gconv-extra",
"glibc-langpack-en",
"openssl-pkcs11",
"python-unversioned-command",
"redhat-release-eula",
"rpm-plugin-systemd-inhibit",
},
}
return ps
}

View file

@ -3,10 +3,11 @@ package rhel10
import (
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
const vmdkKernelOptions = "ro"
func vmdkKernelOptions() []string {
return []string{"ro"}
}
func mkVMDKImgType() *rhel.ImageType {
it := rhel.NewImageType(
@ -14,7 +15,7 @@ func mkVMDKImgType() *rhel.ImageType {
"disk.vmdk",
"application/x-vmdk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: vmdkCommonPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -22,7 +23,7 @@ func mkVMDKImgType() *rhel.ImageType {
[]string{"vmdk"},
)
it.KernelOptions = vmdkKernelOptions
it.KernelOptions = vmdkKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -36,7 +37,7 @@ func mkOVAImgType() *rhel.ImageType {
"image.ova",
"application/ovf",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: vmdkCommonPackageSet,
rhel.OSPkgsKey: packageSetLoader,
},
rhel.DiskImage,
[]string{"build"},
@ -44,30 +45,10 @@ func mkOVAImgType() *rhel.ImageType {
[]string{"archive"},
)
it.KernelOptions = vmdkKernelOptions
it.KernelOptions = vmdkKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
return it
}
func vmdkCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"@core",
"chrony",
"cloud-init",
"firewalld",
"langpacks-en",
"open-vm-tools",
"tuned",
},
Exclude: []string{
"dracut-config-rescue",
"rng-tools",
},
}
return ps
}

View file

@ -14,9 +14,9 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
const (
ec2KernelOptions = "ro console=tty0 console=ttyS0,115200n8 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto LANG=en_US.UTF-8"
)
func ec2KernelOptions() []string {
return []string{"ro", "console=tty0", "console=ttyS0,115200n8", "net.ifnames=0", "rd.blacklist=nouveau", "nvme_core.io_timeout=4294967295", "crashkernel=auto", "LANG=en_US.UTF-8"}
}
func mkEc2ImgTypeX86_64() *rhel.ImageType {
it := rhel.NewImageType(
@ -37,7 +37,7 @@ func mkEc2ImgTypeX86_64() *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = ec2ImageConfig()
it.KernelOptions = ec2KernelOptions
it.KernelOptions = ec2KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = ec2PartitionTables

View file

@ -32,7 +32,7 @@ func mkAzureRhuiImgType() *rhel.ImageType {
it.DiskImageVPCForceSize = common.ToPtr(false)
it.Compression = "xz"
it.KernelOptions = "ro crashkernel=auto console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300 scsi_mod.use_blk_mq=y"
it.KernelOptions = []string{"ro", "crashkernel=auto", "console=tty1", "console=ttyS0", "earlyprintk=ttyS0", "rootdelay=300", "scsi_mod.use_blk_mq=y"}
it.DefaultImageConfig = azureDefaultImgConfig
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte

View file

@ -27,7 +27,7 @@ func mkQcow2ImgType() *rhel.ImageType {
// all RHEL 7 images should use sgdisk
it.DiskImagePartTool = common.ToPtr(osbuild.PTSgdisk)
it.KernelOptions = "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto"
it.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check", "net.ifnames=0", "crashkernel=auto"}
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = qcow2DefaultImgConfig

View file

@ -10,11 +10,17 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
const (
amiX86KernelOptions = "console=tty0 console=ttyS0,115200n8 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto"
amiAarch64KernelOptions = "console=tty0 console=ttyS0,115200n8 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto"
amiSapKernelOptions = "console=tty0 console=ttyS0,115200n8 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto processor.max_cstate=1 intel_idle.max_cstate=1"
)
func amiX86KernelOptions() []string {
return []string{"console=tty0", "console=ttyS0,115200n8", "net.ifnames=0", "rd.blacklist=nouveau", "nvme_core.io_timeout=4294967295", "crashkernel=auto"}
}
func amiAarch64KernelOptions() []string {
return []string{"console=tty0", "console=ttyS0,115200n8", "net.ifnames=0", "rd.blacklist=nouveau", "nvme_core.io_timeout=4294967295", "iommu.strict=0", "crashkernel=auto"}
}
func amiSapKernelOptions() []string {
return []string{"console=tty0", "console=ttyS0,115200n8", "net.ifnames=0", "rd.blacklist=nouveau", "nvme_core.io_timeout=4294967295", "crashkernel=auto", "processor.max_cstate=1", "intel_idle.max_cstate=1"}
}
func mkAmiImgTypeX86_64() *rhel.ImageType {
it := rhel.NewImageType(
@ -31,7 +37,7 @@ func mkAmiImgTypeX86_64() *rhel.ImageType {
)
it.DefaultImageConfig = defaultAMIImageConfigX86_64()
it.KernelOptions = amiX86KernelOptions
it.KernelOptions = amiX86KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = ec2PartitionTables
@ -55,7 +61,7 @@ func mkEc2ImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = defaultEc2ImageConfigX86_64(rd)
it.KernelOptions = amiX86KernelOptions
it.KernelOptions = amiX86KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = ec2PartitionTables
@ -79,7 +85,7 @@ func mkEc2HaImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = defaultEc2ImageConfigX86_64(rd)
it.KernelOptions = amiX86KernelOptions
it.KernelOptions = amiX86KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = ec2PartitionTables
@ -102,7 +108,7 @@ func mkAmiImgTypeAarch64() *rhel.ImageType {
)
it.DefaultImageConfig = defaultAMIImageConfig()
it.KernelOptions = amiAarch64KernelOptions
it.KernelOptions = amiAarch64KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = ec2PartitionTables
@ -126,7 +132,7 @@ func mkEc2ImgTypeAarch64(rd *rhel.Distribution) *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = defaultEc2ImageConfig(rd)
it.KernelOptions = amiAarch64KernelOptions
it.KernelOptions = amiAarch64KernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = ec2PartitionTables
@ -150,7 +156,7 @@ func mkEc2SapImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = defaultEc2SapImageConfigX86_64(rd)
it.KernelOptions = amiSapKernelOptions
it.KernelOptions = amiSapKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = ec2PartitionTables

View file

@ -14,7 +14,9 @@ import (
)
// use loglevel=3 as described in the RHEL documentation and used in existing RHEL images built by MSFT
const defaultAzureKernelOptions = "ro loglevel=3 crashkernel=auto console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300"
func defaultAzureKernelOptions() []string {
return []string{"ro", "loglevel=3", "crashkernel=auto", "console=tty1", "console=ttyS0", "earlyprintk=ttyS0", "rootdelay=300"}
}
func mkAzureRhuiImgType() *rhel.ImageType {
it := rhel.NewImageType(
@ -32,7 +34,7 @@ func mkAzureRhuiImgType() *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = defaultAzureRhuiImageConfig.InheritFrom(defaultVhdImageConfig())
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.BasePartitionTables = azureRhuiBasePartitionTables
@ -56,7 +58,7 @@ func mkAzureSapRhuiImgType(rd *rhel.Distribution) *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = defaultAzureRhuiImageConfig.InheritFrom(sapAzureImageConfig(rd))
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.BasePartitionTables = azureRhuiBasePartitionTables
@ -79,7 +81,7 @@ func mkAzureByosImgType() *rhel.ImageType {
)
it.DefaultImageConfig = defaultAzureByosImageConfig.InheritFrom(defaultVhdImageConfig())
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -103,7 +105,7 @@ func mkAzureImgType() *rhel.ImageType {
)
it.DefaultImageConfig = defaultVhdImageConfig()
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -127,7 +129,7 @@ func mkAzureEap7RhuiImgType() *rhel.ImageType {
it.Compression = "xz"
it.DefaultImageConfig = defaultAzureEapImageConfig.InheritFrom(defaultAzureRhuiImageConfig.InheritFrom(defaultAzureImageConfig))
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.BasePartitionTables = azureRhuiBasePartitionTables

View file

@ -81,7 +81,7 @@ func mkEdgeRawImgType() *rhel.ImageType {
it.NameAliases = []string{"rhel-edge-raw-image"}
it.Compression = "xz"
it.KernelOptions = "modprobe.blacklist=vc4"
it.KernelOptions = []string{"modprobe.blacklist=vc4"}
it.DefaultImageConfig = &distro.ImageConfig{
Keyboard: &osbuild.KeymapStageOptions{
Keymap: "us",
@ -162,7 +162,7 @@ func mkEdgeSimplifiedInstallerImgType(rd *rhel.Distribution) *rhel.ImageType {
)
it.NameAliases = []string{"rhel-edge-simplified-installer"}
it.KernelOptions = "modprobe.blacklist=vc4"
it.KernelOptions = []string{"modprobe.blacklist=vc4"}
it.DefaultImageConfig = &distro.ImageConfig{
EnabledServices: edgeServices(rd),
Keyboard: &osbuild.KeymapStageOptions{
@ -212,7 +212,7 @@ func mkMinimalRawImgType() *rhel.ImageType {
// requires a kickstart file in the root directory.
Files: []*fsnode.File{initialSetupKickstart()},
}
it.KernelOptions = "ro"
it.KernelOptions = []string{"ro"}
it.Bootable = true
it.DefaultSize = 2 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables

View file

@ -10,7 +10,9 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
const gceKernelOptions = "net.ifnames=0 biosdevname=0 scsi_mod.use_blk_mq=Y crashkernel=auto console=ttyS0,38400n8d"
func gceKernelOptions() []string {
return []string{"net.ifnames=0", "biosdevname=0", "scsi_mod.use_blk_mq=Y", "crashkernel=auto", "console=ttyS0,38400n8d"}
}
func mkGceImgType(rd distro.Distro) *rhel.ImageType {
it := rhel.NewImageType(
@ -27,7 +29,7 @@ func mkGceImgType(rd distro.Distro) *rhel.ImageType {
)
it.DefaultImageConfig = defaultGceByosImageConfig(rd)
it.KernelOptions = gceKernelOptions
it.KernelOptions = gceKernelOptions()
it.Bootable = true
it.DefaultSize = 20 * datasizes.GibiByte
// TODO: the base partition table still contains the BIOS boot partition, but the image is UEFI-only
@ -51,7 +53,7 @@ func mkGceRhuiImgType(rd distro.Distro) *rhel.ImageType {
)
it.DefaultImageConfig = defaultGceRhuiImageConfig(rd)
it.KernelOptions = gceKernelOptions
it.KernelOptions = gceKernelOptions()
it.Bootable = true
it.DefaultSize = 20 * datasizes.GibiByte
// TODO: the base partition table still contains the BIOS boot partition, but the image is UEFI-only

View file

@ -24,7 +24,7 @@ func mkQcow2ImgType(rd *rhel.Distribution) *rhel.ImageType {
)
it.DefaultImageConfig = qcowImageConfig(rd)
it.KernelOptions = "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto"
it.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check", "net.ifnames=0", "crashkernel=auto"}
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -47,7 +47,7 @@ func mkOCIImgType(rd *rhel.Distribution) *rhel.ImageType {
)
it.DefaultImageConfig = qcowImageConfig(rd)
it.KernelOptions = "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto"
it.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check", "net.ifnames=0", "crashkernel=auto"}
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -69,7 +69,7 @@ func mkOpenstackImgType() *rhel.ImageType {
[]string{"qcow2"},
)
it.KernelOptions = "ro net.ifnames=0"
it.KernelOptions = []string{"ro", "net.ifnames=0"}
it.DefaultSize = 4 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables

View file

@ -14,7 +14,7 @@ func mkWslImgType() *rhel.ImageType {
"disk.tar.gz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: ubiCommonPackageSet,
rhel.OSPkgsKey: wslPackageSet,
},
rhel.TarImage,
[]string{"build"},
@ -23,6 +23,20 @@ func mkWslImgType() *rhel.ImageType {
)
it.DefaultImageConfig = &distro.ImageConfig{
CloudInit: []*osbuild.CloudInitStageOptions{
{
Filename: "99_wsl.cfg",
Config: osbuild.CloudInitConfigFile{
DatasourceList: []string{
"WSL",
"None",
},
Network: &osbuild.CloudInitConfigNetwork{
Config: "disabled",
},
},
},
},
Locale: common.ToPtr("en_US.UTF-8"),
NoSElinux: common.ToPtr(true),
WSLConfig: &osbuild.WSLConfStageOptions{
@ -35,7 +49,7 @@ func mkWslImgType() *rhel.ImageType {
return it
}
func ubiCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
func wslPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"alternatives",
@ -44,6 +58,7 @@ func ubiCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
"bash",
"brotli",
"ca-certificates",
"cloud-init",
"coreutils-single",
"crypto-policies-scripts",
"curl",
@ -87,7 +102,6 @@ func ubiCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
"alsa-tools-firmware",
"biosdevname",
"cpio",
"diffutils",
"dnf-plugin-spacewalk",
"dracut",
"elfutils-debuginfod-client",
@ -112,18 +126,15 @@ func ubiCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
"libkcapi",
"libkcapi-hmaccalc",
"libsecret",
"libselinux-utils",
"libxkbcommon",
"libertas-sd8787-firmware",
"memstrack",
"nss",
"openssl",
"openssl-pkcs11",
"os-prober",
"pigz",
"pinentry",
"plymouth",
"policycoreutils",
"python3-unbound",
"redhat-release-eula",
"rng-tools",

View file

@ -6,7 +6,9 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
const vmdkKernelOptions = "ro net.ifnames=0"
func vmdkKernelOptions() []string {
return []string{"ro", "net.ifnames=0"}
}
func mkVmdkImgType() *rhel.ImageType {
it := rhel.NewImageType(
@ -22,7 +24,7 @@ func mkVmdkImgType() *rhel.ImageType {
[]string{"vmdk"},
)
it.KernelOptions = vmdkKernelOptions
it.KernelOptions = vmdkKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -44,7 +46,7 @@ func mkOvaImgType() *rhel.ImageType {
[]string{"archive"},
)
it.KernelOptions = vmdkKernelOptions
it.KernelOptions = vmdkKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables

View file

@ -10,7 +10,10 @@ import (
)
// TODO: move these to the EC2 environment
const amiKernelOptions = "console=tty0 console=ttyS0,115200n8 net.ifnames=0 nvme_core.io_timeout=4294967295"
func amiKernelOptions() []string {
return []string{"console=tty0", "console=ttyS0,115200n8", "net.ifnames=0", "nvme_core.io_timeout=4294967295"}
}
// default EC2 images config (common for all architectures)
func defaultEc2ImageConfig() *distro.ImageConfig {
@ -275,7 +278,7 @@ func mkEc2ImgTypeX86_64() *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = amiKernelOptions
it.KernelOptions = amiKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
@ -298,7 +301,7 @@ func mkAMIImgTypeX86_64() *rhel.ImageType {
[]string{"image"},
)
it.KernelOptions = amiKernelOptions
it.KernelOptions = amiKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
@ -322,7 +325,7 @@ func mkEC2SapImgTypeX86_64(osVersion string) *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = "console=ttyS0,115200n8 console=tty0 net.ifnames=0 nvme_core.io_timeout=4294967295 processor.max_cstate=1 intel_idle.max_cstate=1"
it.KernelOptions = []string{"console=ttyS0,115200n8", "console=tty0", "net.ifnames=0", "nvme_core.io_timeout=4294967295", "processor.max_cstate=1", "intel_idle.max_cstate=1"}
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = sapImageConfig(osVersion).InheritFrom(defaultEc2ImageConfigX86_64())
@ -346,7 +349,7 @@ func mkEc2HaImgTypeX86_64() *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = amiKernelOptions
it.KernelOptions = amiKernelOptions()
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
@ -369,7 +372,7 @@ func mkAMIImgTypeAarch64() *rhel.ImageType {
[]string{"image"},
)
it.KernelOptions = "console=ttyS0,115200n8 console=tty0 net.ifnames=0 nvme_core.io_timeout=4294967295 iommu.strict=0"
it.KernelOptions = []string{"console=ttyS0,115200n8", "console=tty0", "net.ifnames=0", "nvme_core.io_timeout=4294967295", "iommu.strict=0"}
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfig()
@ -393,7 +396,7 @@ func mkEC2ImgTypeAarch64() *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = "console=ttyS0,115200n8 console=tty0 net.ifnames=0 nvme_core.io_timeout=4294967295 iommu.strict=0"
it.KernelOptions = []string{"console=ttyS0,115200n8", "console=tty0", "net.ifnames=0", "nvme_core.io_timeout=4294967295", "iommu.strict=0"}
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfig()

View file

@ -26,7 +26,7 @@ func mkAzureImgType(rd *rhel.Distribution) *rhel.ImageType {
[]string{"vpc"},
)
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.DefaultImageConfig = defaultAzureImageConfig(rd)
@ -51,7 +51,7 @@ func mkAzureInternalImgType(rd *rhel.Distribution) *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.DefaultImageConfig = defaultAzureImageConfig(rd)
@ -75,7 +75,7 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution) *rhel.ImageType {
)
it.Compression = "xz"
it.KernelOptions = defaultAzureKernelOptions
it.KernelOptions = defaultAzureKernelOptions()
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.DefaultImageConfig = sapAzureImageConfig(rd)
@ -413,7 +413,9 @@ func azureInternalBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, b
// IMAGE CONFIG
// use loglevel=3 as described in the RHEL documentation and used in existing RHEL images built by MSFT
const defaultAzureKernelOptions = "ro loglevel=3 console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300"
func defaultAzureKernelOptions() []string {
return []string{"ro", "loglevel=3", "console=tty1", "console=ttyS0", "earlyprintk=ttyS0", "rootdelay=300"}
}
// based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure
func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig {

View file

@ -110,9 +110,9 @@ func mkEdgeRawImgType(d *rhel.Distribution) *rhel.ImageType {
it.DefaultImageConfig.IgnitionPlatform = common.ToPtr("metal")
}
it.KernelOptions = "modprobe.blacklist=vc4"
it.KernelOptions = []string{"modprobe.blacklist=vc4"}
if common.VersionGreaterThanOrEqual(d.OsVersion(), "9.2") || !d.IsRHEL() {
it.KernelOptions += " rw coreos.no_persist_ip"
it.KernelOptions = append(it.KernelOptions, "rw", "coreos.no_persist_ip")
}
it.DefaultSize = 10 * datasizes.GibiByte
@ -213,9 +213,9 @@ func mkEdgeSimplifiedInstallerImgType(d *rhel.Distribution) *rhel.ImageType {
it.BasePartitionTables = edgeBasePartitionTables
it.UnsupportedPartitioningModes = []disk.PartitioningMode{disk.RawPartitioningMode}
it.KernelOptions = "modprobe.blacklist=vc4"
it.KernelOptions = []string{"modprobe.blacklist=vc4"}
if common.VersionGreaterThanOrEqual(d.OsVersion(), "9.2") || !d.IsRHEL() {
it.KernelOptions += " rw coreos.no_persist_ip"
it.KernelOptions = append(it.KernelOptions, "rw", "coreos.no_persist_ip")
}
return it
@ -245,9 +245,9 @@ func mkEdgeAMIImgType(d *rhel.Distribution) *rhel.ImageType {
it.DefaultImageConfig.IgnitionPlatform = common.ToPtr("metal")
}
it.KernelOptions = amiKernelOptions + " modprobe.blacklist=vc4"
it.KernelOptions = append(amiKernelOptions(), "modprobe.blacklist=vc4")
if common.VersionGreaterThanOrEqual(d.OsVersion(), "9.2") || !d.IsRHEL() {
it.KernelOptions += " rw coreos.no_persist_ip"
it.KernelOptions = append(it.KernelOptions, "rw", "coreos.no_persist_ip")
}
it.DefaultSize = 10 * datasizes.GibiByte
@ -284,9 +284,9 @@ func mkEdgeVsphereImgType(d *rhel.Distribution) *rhel.ImageType {
it.DefaultImageConfig.IgnitionPlatform = common.ToPtr("metal")
}
it.KernelOptions = "modprobe.blacklist=vc4"
it.KernelOptions = []string{"modprobe.blacklist=vc4"}
if common.VersionGreaterThanOrEqual(d.OsVersion(), "9.2") || !d.IsRHEL() {
it.KernelOptions += " rw coreos.no_persist_ip"
it.KernelOptions = append(it.KernelOptions, "rw", "coreos.no_persist_ip")
}
it.DefaultSize = 10 * datasizes.GibiByte
@ -320,7 +320,7 @@ func mkMinimalrawImgType() *rhel.ImageType {
// requires a kickstart file in the root directory.
Files: []*fsnode.File{initialSetupKickstart()},
}
it.KernelOptions = "ro"
it.KernelOptions = []string{"ro"}
it.DefaultSize = 2 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = minimalrawPartitionTables

View file

@ -9,7 +9,9 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
const gceKernelOptions = "net.ifnames=0 biosdevname=0 scsi_mod.use_blk_mq=Y console=ttyS0,38400n8d"
func gceKernelOptions() []string {
return []string{"net.ifnames=0", "biosdevname=0", "scsi_mod.use_blk_mq=Y", "console=ttyS0,38400n8d"}
}
func mkGCEImageType() *rhel.ImageType {
it := rhel.NewImageType(
@ -29,7 +31,7 @@ func mkGCEImageType() *rhel.ImageType {
// The configuration for non-RHUI images does not touch the RHSM configuration at all.
// https://issues.redhat.com/browse/COMPOSER-2157
it.DefaultImageConfig = baseGCEImageConfig()
it.KernelOptions = gceKernelOptions
it.KernelOptions = gceKernelOptions()
it.DefaultSize = 20 * datasizes.GibiByte
it.Bootable = true
// TODO: the base partition table still contains the BIOS boot partition, but the image is UEFI-only

View file

@ -24,7 +24,7 @@ func mkQcow2ImgType(d *rhel.Distribution) *rhel.ImageType {
)
it.DefaultImageConfig = qcowImageConfig(d)
it.KernelOptions = "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0"
it.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check", "net.ifnames=0"}
it.DefaultSize = 10 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables
@ -47,7 +47,7 @@ func mkOCIImgType(d *rhel.Distribution) *rhel.ImageType {
)
it.DefaultImageConfig = qcowImageConfig(d)
it.KernelOptions = "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0"
it.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check", "net.ifnames=0"}
it.DefaultSize = 10 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables
@ -72,7 +72,7 @@ func mkOpenstackImgType() *rhel.ImageType {
it.DefaultImageConfig = &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
}
it.KernelOptions = "ro net.ifnames=0"
it.KernelOptions = []string{"ro", "net.ifnames=0"}
it.DefaultSize = 4 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables

View file

@ -14,7 +14,7 @@ func mkWSLImgType() *rhel.ImageType {
"disk.tar.gz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: ubiCommonPackageSet,
rhel.OSPkgsKey: wslPackageSet,
},
rhel.TarImage,
[]string{"build"},
@ -23,6 +23,20 @@ func mkWSLImgType() *rhel.ImageType {
)
it.DefaultImageConfig = &distro.ImageConfig{
CloudInit: []*osbuild.CloudInitStageOptions{
{
Filename: "99_wsl.cfg",
Config: osbuild.CloudInitConfigFile{
DatasourceList: []string{
"WSL",
"None",
},
Network: &osbuild.CloudInitConfigNetwork{
Config: "disabled",
},
},
},
},
Locale: common.ToPtr("en_US.UTF-8"),
NoSElinux: common.ToPtr(true),
WSLConfig: &osbuild.WSLConfStageOptions{
@ -35,7 +49,7 @@ func mkWSLImgType() *rhel.ImageType {
return it
}
func ubiCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
func wslPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"alternatives",
@ -43,6 +57,7 @@ func ubiCommonPackageSet(t *rhel.ImageType) rpmmd.PackageSet {
"basesystem",
"bash",
"ca-certificates",
"cloud-init",
"coreutils-single",
"crypto-policies-scripts",
"curl-minimal",

View file

@ -8,7 +8,9 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
const vmdkKernelOptions = "ro net.ifnames=0"
func vmdkKernelOptions() []string {
return []string{"ro", "net.ifnames=0"}
}
func mkVMDKImgType() *rhel.ImageType {
it := rhel.NewImageType(
@ -27,7 +29,7 @@ func mkVMDKImgType() *rhel.ImageType {
it.DefaultImageConfig = &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
}
it.KernelOptions = vmdkKernelOptions
it.KernelOptions = vmdkKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -52,7 +54,7 @@ func mkOVAImgType() *rhel.ImageType {
it.DefaultImageConfig = &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
}
it.KernelOptions = vmdkKernelOptions
it.KernelOptions = vmdkKernelOptions()
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables

View file

@ -24,6 +24,7 @@ type AnacondaContainerInstaller struct {
RootfsCompression string
RootfsType manifest.RootfsType
ISOBoot manifest.ISOBootType
ISOLabel string
Product string
@ -131,9 +132,6 @@ func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest,
bootTreePipeline.KernelOpts = append(bootTreePipeline.KernelOpts, "fips=1")
}
// enable ISOLinux on x86_64 only
isoLinuxEnabled := img.Platform.GetArch() == arch.ARCH_X86_64
isoTreePipeline := manifest.NewAnacondaInstallerISOTree(buildPipeline, anacondaPipeline, rootfsImagePipeline, bootTreePipeline)
isoTreePipeline.PartitionTable = efiBootPartitionTable(rng)
isoTreePipeline.Release = img.Release
@ -147,14 +145,14 @@ func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.PayloadRemoveSignatures = img.ContainerRemoveSignatures
isoTreePipeline.ContainerSource = &img.ContainerSource
isoTreePipeline.ISOLinux = isoLinuxEnabled
isoTreePipeline.ISOBoot = img.ISOBoot
if img.FIPS {
isoTreePipeline.KernelOpts = append(isoTreePipeline.KernelOpts, "fips=1")
}
isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel)
isoPipeline.SetFilename(img.Filename)
isoPipeline.ISOLinux = isoLinuxEnabled
isoPipeline.ISOBoot = img.ISOBoot
artifact := isoPipeline.Export()
return artifact, nil

View file

@ -25,6 +25,7 @@ type AnacondaLiveInstaller struct {
RootfsCompression string
RootfsType manifest.RootfsType
ISOBoot manifest.ISOBootType
ISOLabel string
Product string
@ -105,22 +106,19 @@ func (img *AnacondaLiveInstaller) InstantiateManifest(m *manifest.Manifest,
bootTreePipeline.KernelOpts = kernelOpts
// enable ISOLinux on x86_64 only
isoLinuxEnabled := img.Platform.GetArch() == arch.ARCH_X86_64
isoTreePipeline := manifest.NewAnacondaInstallerISOTree(buildPipeline, livePipeline, rootfsImagePipeline, bootTreePipeline)
isoTreePipeline.PartitionTable = efiBootPartitionTable(rng)
isoTreePipeline.Release = img.Release
isoTreePipeline.KernelOpts = kernelOpts
isoTreePipeline.ISOLinux = isoLinuxEnabled
isoTreePipeline.ISOBoot = img.ISOBoot
isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType
isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel)
isoPipeline.SetFilename(img.Filename)
isoPipeline.ISOLinux = isoLinuxEnabled
isoPipeline.ISOBoot = img.ISOBoot
artifact := isoPipeline.Export()

View file

@ -30,6 +30,7 @@ type AnacondaOSTreeInstaller struct {
RootfsCompression string
RootfsType manifest.RootfsType
ISOBoot manifest.ISOBootType
ISOLabel string
Product string
@ -133,9 +134,6 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
bootTreePipeline.KernelOpts = append(bootTreePipeline.KernelOpts, "fips=1")
}
// enable ISOLinux on x86_64 only
isoLinuxEnabled := img.Platform.GetArch() == arch.ARCH_X86_64
var subscriptionPipeline *manifest.Subscription
if img.Subscription != nil {
// pipeline that will create subscription service and key file to be copied out
@ -152,7 +150,7 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.PayloadPath = "/ostree/repo"
isoTreePipeline.OSTreeCommitSource = &img.Commit
isoTreePipeline.ISOLinux = isoLinuxEnabled
isoTreePipeline.ISOBoot = img.ISOBoot
if img.FIPS {
isoTreePipeline.KernelOpts = append(isoTreePipeline.KernelOpts, "fips=1")
}
@ -160,7 +158,7 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel)
isoPipeline.SetFilename(img.Filename)
isoPipeline.ISOLinux = isoLinuxEnabled
isoPipeline.ISOBoot = img.ISOBoot
artifact := isoPipeline.Export()
return artifact, nil

View file

@ -58,6 +58,7 @@ type AnacondaTarInstaller struct {
RootfsCompression string
RootfsType manifest.RootfsType
ISOBoot manifest.ISOBootType
ISOLabel string
Product string
@ -184,9 +185,6 @@ func (img *AnacondaTarInstaller) InstantiateManifest(m *manifest.Manifest,
osPipeline.Environment = img.Environment
osPipeline.Workload = img.Workload
// enable ISOLinux on x86_64 only
isoLinuxEnabled := img.Platform.GetArch() == arch.ARCH_X86_64
isoTreePipeline := manifest.NewAnacondaInstallerISOTree(buildPipeline, anacondaPipeline, rootfsImagePipeline, bootTreePipeline)
// TODO: the partition table is required - make it a ctor arg or set a default one in the pipeline
isoTreePipeline.PartitionTable = efiBootPartitionTable(rng)
@ -206,11 +204,11 @@ func (img *AnacondaTarInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.KernelOpts = append(isoTreePipeline.KernelOpts, "fips=1")
}
isoTreePipeline.ISOLinux = isoLinuxEnabled
isoTreePipeline.ISOBoot = img.ISOBoot
isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel)
isoPipeline.SetFilename(img.Filename)
isoPipeline.ISOLinux = isoLinuxEnabled
isoPipeline.ISOBoot = img.ISOBoot
artifact := isoPipeline.Export()

View file

@ -68,6 +68,7 @@ func (img *BootcDiskImage) InstantiateManifestFromContainers(m *manifest.Manifes
rawImage.Directories = img.Directories
rawImage.KernelOptionsAppend = img.KernelOptionsAppend
rawImage.SELinux = img.SELinux
rawImage.MountUnits = true // always use mount units for bootc disk images
// In BIB, we export multiple images from the same pipeline so we use the
// filename as the basename for each export and set the extensions based on

View file

@ -156,7 +156,9 @@ func (img *OSTreeSimplifiedInstaller) InstantiateManifest(m *manifest.Manifest,
isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, isoLabel)
isoPipeline.SetFilename(img.Filename)
isoPipeline.ISOLinux = isoLinuxEnabled
if isoLinuxEnabled {
isoPipeline.ISOBoot = manifest.SyslinuxISOBoot
}
artifact := isoPipeline.Export()
return artifact, nil

View file

@ -25,6 +25,15 @@ const ( // Rootfs type enum
ErofsRootfs // Create a plain erofs rootfs
)
type ISOBootType uint64
// These constants are used by the ISO images to control the type of bootable iso
const ( // ISOBoot type enum
Grub2UEFIOnlyISOBoot ISOBootType = iota // Only boot with grub2 UEFI
SyslinuxISOBoot // Boot with grub2 UEFI and syslinux/isolinux BIOS
Grub2ISOBoot // Boot with grub2 UEFI and grub2 BIOS
)
// An AnacondaInstallerISOTree represents a tree containing the anaconda installer,
// configuration in terms of a kickstart file, as well as an embedded
// payload to be installed, this payload can either be an ostree
@ -62,8 +71,8 @@ type AnacondaInstallerISOTree struct {
// Kernel options for the ISO image
KernelOpts []string
// Enable ISOLinux stage
ISOLinux bool
// ISOBoot selects the type of boot support on the iso
ISOBoot ISOBootType
Kickstart *kickstart.Options
@ -145,6 +154,11 @@ func (p *AnacondaInstallerISOTree) getBuildPackages(_ Distro) []string {
default:
}
if p.ISOBoot == Grub2ISOBoot {
// Needed for the i386-pc directory of modules needed by grub2 BIOS booting
packages = append(packages, "grub2-pc-modules")
}
if p.OSTreeCommitSource != nil {
packages = append(packages, "rpm-ostree")
}
@ -342,8 +356,8 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
default:
}
if p.ISOLinux {
isoLinuxOptions := &osbuild.ISOLinuxStageOptions{
if p.ISOBoot == SyslinuxISOBoot {
options := &osbuild.ISOLinuxStageOptions{
Product: osbuild.ISOLinuxProduct{
Name: p.anacondaPipeline.product,
Version: p.anacondaPipeline.version,
@ -354,8 +368,26 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
},
}
isoLinuxStage := osbuild.NewISOLinuxStage(isoLinuxOptions, p.anacondaPipeline.Name())
pipeline.AddStage(isoLinuxStage)
stage := osbuild.NewISOLinuxStage(options, p.anacondaPipeline.Name())
pipeline.AddStage(stage)
} else if p.ISOBoot == Grub2ISOBoot {
options := &osbuild.Grub2ISOLegacyStageOptions{
Product: osbuild.Product{
Name: p.anacondaPipeline.product,
Version: p.anacondaPipeline.version,
},
Kernel: osbuild.ISOKernel{
Dir: "/images/pxeboot",
Opts: kernelOpts,
},
ISOLabel: p.isoLabel,
}
stage := osbuild.NewGrub2ISOLegacyStage(options)
pipeline.AddStage(stage)
// Add a stage to create the eltorito.img file for grub2 BIOS boot support
pipeline.AddStage(osbuild.NewGrub2InstStage(osbuild.NewGrub2InstISO9660StageOption("images/eltorito.img", "/boot/grub2")))
}
filename := "images/efiboot.img"

View file

@ -0,0 +1,22 @@
package manifest
import (
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/osbuild"
)
// filesystemConfigStages generates either an org.osbuild.fstab stage or a
// collection of org.osbuild.systemd.unit.create stages for .mount and .swap
// units (and an org.osbuild.systemd stage to enable them) depending on the
// pipeline configuration.
func filesystemConfigStages(pt *disk.PartitionTable, mountUnits bool) ([]*osbuild.Stage, error) {
if mountUnits {
return osbuild.GenSystemdMountStages(pt)
} else {
opts, err := osbuild.NewFSTabStageOptions(pt)
if err != nil {
return nil, err
}
return []*osbuild.Stage{osbuild.NewFSTabStage(opts)}, nil
}
}

View file

@ -9,7 +9,7 @@ import (
// an existing ISOTreePipeline.
type ISO struct {
Base
ISOLinux bool
ISOBoot ISOBootType
filename string
treePipeline Pipeline
@ -45,13 +45,13 @@ func (p *ISO) getBuildPackages(Distro) []string {
func (p *ISO) serialize() osbuild.Pipeline {
pipeline := p.Base.serialize()
pipeline.AddStage(osbuild.NewXorrisofsStage(xorrisofsStageOptions(p.Filename(), p.isoLabel, p.ISOLinux), p.treePipeline.Name()))
pipeline.AddStage(osbuild.NewXorrisofsStage(xorrisofsStageOptions(p.Filename(), p.isoLabel, p.ISOBoot), p.treePipeline.Name()))
pipeline.AddStage(osbuild.NewImplantisomd5Stage(&osbuild.Implantisomd5StageOptions{Filename: p.Filename()}))
return pipeline
}
func xorrisofsStageOptions(filename, isolabel string, isolinux bool) *osbuild.XorrisofsStageOptions {
func xorrisofsStageOptions(filename, isolabel string, isoboot ISOBootType) *osbuild.XorrisofsStageOptions {
options := &osbuild.XorrisofsStageOptions{
Filename: filename,
VolID: isolabel,
@ -60,13 +60,20 @@ func xorrisofsStageOptions(filename, isolabel string, isolinux bool) *osbuild.Xo
ISOLevel: 3,
}
if isolinux {
if isoboot == SyslinuxISOBoot {
// Syslinux BIOS ISO creation
options.Boot = &osbuild.XorrisofsBoot{
Image: "isolinux/isolinux.bin",
Catalog: "isolinux/boot.cat",
}
options.IsohybridMBR = "/usr/share/syslinux/isohdpfx.bin"
} else if isoboot == Grub2ISOBoot {
// grub2 BIOS ISO creation
options.Boot = &osbuild.XorrisofsBoot{
Image: "images/eltorito.img",
Catalog: "boot.cat",
}
options.Grub2MBR = "/usr/lib/grub/i386-pc/boot_hybrid.img"
}
return options

View file

@ -157,6 +157,10 @@ type OSCustomizations struct {
// Determines if the machine id should be set to "uninitialized" which allows
// "ConditionFirstBoot" to work in systemd
MachineIdUninitialized bool
// MountUnits creates systemd .mount units to describe the filesystem
// instead of writing to /etc/fstab
MountUnits bool
}
// OS represents the filesystem tree of the target image. This roughly
@ -476,7 +480,9 @@ func (p *OS) serialize() osbuild.Pipeline {
}
}
pipeline.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: p.Language}))
if p.Language != "" {
pipeline.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: p.Language}))
}
if p.Keyboard != nil {
keymapOptions := &osbuild.KeymapStageOptions{Keymap: *p.Keyboard}
@ -489,7 +495,10 @@ func (p *OS) serialize() osbuild.Pipeline {
if p.Hostname != "" {
pipeline.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: p.Hostname}))
}
pipeline.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: p.Timezone}))
if p.Timezone != "" {
pipeline.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: p.Timezone}))
}
if len(p.NTPServers) > 0 {
chronyOptions := &osbuild.ChronyStageOptions{Servers: p.NTPServers}
@ -633,7 +642,10 @@ func (p *OS) serialize() osbuild.Pipeline {
}
if pt := p.PartitionTable; pt != nil {
kernelOptions := osbuild.GenImageKernelOptions(p.PartitionTable)
rootUUID, kernelOptions, err := osbuild.GenImageKernelOptions(p.PartitionTable, p.MountUnits)
if err != nil {
panic(err)
}
kernelOptions = append(kernelOptions, p.KernelOptionsAppend...)
if p.FIPS {
@ -644,15 +656,11 @@ func (p *OS) serialize() osbuild.Pipeline {
}))
}
if !p.KernelOptionsBootloader || p.platform.GetArch() == arch.ARCH_S390X {
pipeline = prependKernelCmdlineStage(pipeline, strings.Join(kernelOptions, " "), pt)
}
opts, err := osbuild.NewFSTabStageOptions(pt)
fsCfgStages, err := filesystemConfigStages(pt, p.MountUnits)
if err != nil {
panic(err)
}
pipeline.AddStage(osbuild.NewFSTabStage(opts))
pipeline.AddStages(fsCfgStages...)
var bootloader *osbuild.Stage
switch p.platform.GetArch() {
@ -708,6 +716,10 @@ func (p *OS) serialize() osbuild.Pipeline {
}
pipeline.AddStage(bootloader)
if !p.KernelOptionsBootloader || p.platform.GetArch() == arch.ARCH_S390X {
pipeline = prependKernelCmdlineStage(pipeline, rootUUID, kernelOptions)
}
}
if p.RHSMFacts != nil {
@ -890,13 +902,8 @@ func (p *OS) serialize() osbuild.Pipeline {
return pipeline
}
func prependKernelCmdlineStage(pipeline osbuild.Pipeline, kernelOptions string, pt *disk.PartitionTable) osbuild.Pipeline {
rootFs := pt.FindMountable("/")
if rootFs == nil {
panic("root filesystem must be defined for kernel-cmdline stage, this is a programming error")
}
rootFsUUID := rootFs.GetFSSpec().UUID
kernelStage := osbuild.NewKernelCmdlineStage(osbuild.NewKernelCmdlineStageOptions(rootFsUUID, kernelOptions))
func prependKernelCmdlineStage(pipeline osbuild.Pipeline, rootUUID string, kernelOptions []string) osbuild.Pipeline {
kernelStage := osbuild.NewKernelCmdlineStage(osbuild.NewKernelCmdlineStageOptions(rootUUID, strings.Join(kernelOptions, " ")))
pipeline.Stages = append([]*osbuild.Stage{kernelStage}, pipeline.Stages...)
return pipeline
}

View file

@ -42,6 +42,10 @@ type OSTreeDeploymentCustomizations struct {
// Lock the root account in the deployment unless the user defined root
// user options in the build configuration.
LockRoot bool
// MountUnits creates systemd .mount units to describe the filesystem
// instead of writing to /etc/fstab
MountUnits bool
}
// OSTreeDeployment represents the filesystem tree of a target image based
@ -289,7 +293,10 @@ func (p *OSTreeDeployment) serialize() osbuild.Pipeline {
},
},
}))
kernelOpts := osbuild.GenImageKernelOptions(p.PartitionTable)
_, kernelOpts, err := osbuild.GenImageKernelOptions(p.PartitionTable, p.MountUnits)
if err != nil {
panic(err)
}
kernelOpts = append(kernelOpts, p.KernelOptionsAppend...)
if p.IgnitionPlatform != "" {
@ -329,13 +336,14 @@ func (p *OSTreeDeployment) serialize() osbuild.Pipeline {
configStage.MountOSTree(p.osName, ref, 0)
pipeline.AddStage(configStage)
fstabOptions, err := osbuild.NewFSTabStageOptions(p.PartitionTable)
fsCfgStages, err := filesystemConfigStages(p.PartitionTable, p.MountUnits)
if err != nil {
panic(err)
}
fstabStage := osbuild.NewFSTabStage(fstabOptions)
fstabStage.MountOSTree(p.osName, ref, 0)
pipeline.AddStage(fstabStage)
for _, stage := range fsCfgStages {
stage.MountOSTree(p.osName, ref, 0)
pipeline.AddStage(stage)
}
if len(p.Groups) > 0 {
grpStage := osbuild.GenGroupsStage(p.Groups)

View file

@ -44,6 +44,10 @@ type RawBootcImage struct {
// SELinux policy, when set it enables the labeling of the tree with the
// selected profile
SELinux string
// MountUnits creates systemd .mount units to describe the filesystem
// instead of writing to /etc/fstab
MountUnits bool
}
func (p RawBootcImage) Filename() string {
@ -168,17 +172,15 @@ func (p *RawBootcImage) serialize() osbuild.Pipeline {
mounts = append(mounts, *osbuild.NewOSTreeDeploymentMountDefault("ostree.deployment", osbuild.OSTreeMountSourceMount))
mounts = append(mounts, *osbuild.NewBindMount("bind-ostree-deployment-to-tree", "mount://", "tree://"))
// we always include the fstab stage
// XXX: see issue#756 - if we stop doing this, conditionally
// apply selinux again
fstabOpts, err := osbuild.NewFSTabStageOptions(pt)
fsCfgStages, err := filesystemConfigStages(pt, p.MountUnits)
if err != nil {
panic(err)
}
fstabStage := osbuild.NewFSTabStage(fstabOpts)
fstabStage.Mounts = mounts
fstabStage.Devices = devices
pipeline.AddStage(fstabStage)
for _, stage := range fsCfgStages {
stage.Mounts = mounts
stage.Devices = devices
pipeline.AddStage(stage)
}
// customize the image
if len(p.Groups) > 0 {

View file

@ -30,6 +30,7 @@ type CloudInitConfigFile struct {
Datasource *CloudInitConfigDatasource `json:"datasource,omitempty"`
DatasourceList []string `json:"datasource_list,omitempty"`
Output *CloudInitConfigOutput `json:"output,omitempty"`
Network *CloudInitConfigNetwork `json:"network,omitempty"`
}
// Represents the 'system_info' configuration section
@ -69,6 +70,10 @@ type CloudInitConfigDefaultUser struct {
Name string `json:"name,omitempty"`
}
type CloudInitConfigNetwork struct {
Config string `json:"config"`
}
func (c CloudInitConfigFile) validate() error {
if c.SystemInfo == nil && c.Reporting == nil && c.Datasource == nil && len(c.DatasourceList) == 0 && c.Output == nil {
return fmt.Errorf("at least one cloud-init configuration option must be specified")
@ -89,7 +94,7 @@ func (c CloudInitConfigFile) validate() error {
}
}
allowedDatasources := []string{"Azure", "Ec2", "None"}
allowedDatasources := []string{"Azure", "Ec2", "WSL", "NoCloud", "None"}
if len(c.DatasourceList) > 0 {
for _, d := range c.DatasourceList {
if !slices.Contains(allowedDatasources, d) {
@ -102,6 +107,11 @@ func (c CloudInitConfigFile) validate() error {
return err
}
}
if c.Network != nil {
if err := c.Network.validate(); err != nil {
return err
}
}
return nil
}
@ -160,3 +170,10 @@ func (du CloudInitConfigDefaultUser) validate() error {
}
return nil
}
func (n CloudInitConfigNetwork) validate() error {
if n.Config != "disabled" {
return fmt.Errorf("Network config must be set to disabled if the network section is specified")
}
return nil
}

View file

@ -111,16 +111,42 @@ func GenImageFinishStages(pt *disk.PartitionTable, filename string) []*Stage {
return GenDeviceFinishStages(pt, filename)
}
func GenImageKernelOptions(pt *disk.PartitionTable) []string {
func GenImageKernelOptions(pt *disk.PartitionTable, mountUnits bool) (string, []string, error) {
cmdline := make([]string, 0)
rootFs := pt.FindMountable("/")
if rootFs == nil {
return "", nil, fmt.Errorf("root filesystem must be defined for kernel-cmdline stage, this is a programming error")
}
rootFsUUID := rootFs.GetFSSpec().UUID
// if /usr is on a separate filesystem, it needs to be defined in the
// kernel cmdline options for autodiscovery (when there's no /etc/fstab)
// see:
// - https://github.com/systemd/systemd/issues/24027
// - https://github.com/systemd/systemd/pull/33397
if usrFs := pt.FindMountable("/usr"); usrFs != nil && mountUnits {
fsOptions, err := usrFs.GetFSTabOptions()
if err != nil {
panic(fmt.Sprintf("error getting filesystem options for /usr mountpoint: %s", err))
}
cmdline = append(
cmdline,
fmt.Sprintf("mount.usr=UUID=%s", usrFs.GetFSSpec().UUID),
fmt.Sprintf("mount.usrfstype=%s", usrFs.GetFSType()),
fmt.Sprintf("mount.usrflags=%s", fsOptions.MntOps),
)
}
genOptions := func(e disk.Entity, path []disk.Entity) error {
switch ent := e.(type) {
case *disk.LUKSContainer:
karg := "luks.uuid=" + ent.UUID
cmdline = append(cmdline, karg)
case *disk.BtrfsSubvolume:
if ent.Mountpoint == "/" {
if ent.Mountpoint == "/" && !mountUnits {
// if we're using mount units, the rootflags will be added
// separately (below)
karg := "rootflags=subvol=" + ent.Name
cmdline = append(cmdline, karg)
}
@ -128,6 +154,36 @@ func GenImageKernelOptions(pt *disk.PartitionTable) []string {
return nil
}
if mountUnits {
// The systemd-remount-fs service reads /etc/fstab to discover mount
// options for / and /usr. Without an /etc/fstab, / and /usr do not get
// remounted, which means if they are mounted read-only in the initrd,
// they will remain read-only. Flip the option if we're using only
// mount units, otherwise the filesystems will stay mounted 'ro'.
//
// See https://www.freedesktop.org/software/systemd/man/latest/systemd-remount-fs.service.html
for idx := range cmdline {
// TODO: consider removing 'ro' from static image configurations
// and adding either 'ro' or 'rw' here based on the value of
// mountUnits.
if cmdline[idx] == "ro" {
cmdline[idx] = "rw"
break
}
}
// set the rootflags for the same reason as above
fsOptions, err := rootFs.GetFSTabOptions()
if err != nil {
panic(fmt.Sprintf("error getting filesystem options for / mountpoint: %s", err))
}
// if the options are just 'defaults', there's no need to add rootflags
if fsOptions.MntOps != "defaults" {
cmdline = append(cmdline, fmt.Sprintf("rootflags=%s", fsOptions.MntOps))
}
}
_ = pt.ForEachEntity(genOptions)
return cmdline
return rootFsUUID, cmdline, nil
}

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/disk"
)
@ -16,7 +17,7 @@ type Grub2InstStageOptions struct {
// Platform of the target system
Platform string `json:"platform"`
Location uint64 `json:"location"`
Location *uint64 `json:"location,omitempty"`
// How to obtain the GRUB core image
Core CoreMkImage `json:"core"`
@ -41,12 +42,12 @@ type CoreMkImage struct {
// Grub2 config on a specific partition, e.g. (,gpt3)/boot
type PrefixPartition struct {
Type string `json:"type"`
Type string `json:"type,omitempty"`
PartLabel string `json:"partlabel"`
PartLabel string `json:"partlabel,omitempty"`
// The partition number, starting at zero
Number uint `json:"number"`
Number *uint `json:"number,omitempty"`
// Location of the grub config inside the partition
Path string `json:"path"`
@ -81,15 +82,18 @@ func (options Grub2InstStageOptions) MarshalJSON() ([]byte, error) {
if !valueIn(g2options.Core.PartLabel, []string{"gpt", "dos"}) {
return nil, fmt.Errorf("org.osbuild.grub2.inst: invalid value %q for core.partlabel", g2options.Core.PartLabel)
}
if !valueIn(g2options.Core.Filesystem, []string{"ext4", "xfs", "btrfs"}) {
if !valueIn(g2options.Core.Filesystem, []string{"ext4", "xfs", "btrfs", "iso9660"}) {
return nil, fmt.Errorf("org.osbuild.grub2.inst: invalid value %q for core.filesystem", g2options.Core.Filesystem)
}
if g2options.Prefix.Type != "partition" {
return nil, fmt.Errorf("org.osbuild.grub2.inst: invalid value %q for prefix.type", g2options.Prefix.Type)
}
if !valueIn(g2options.Prefix.PartLabel, []string{"gpt", "dos"}) {
return nil, fmt.Errorf("org.osbuild.grub2.inst: invalid value %q for core.partlabel", g2options.Core.PartLabel)
// iso9660 doesn't use Prefix.Type, Prefix.PartLabel, or Prefix.Number
if g2options.Core.Filesystem != "iso9660" {
if g2options.Prefix.Type != "partition" {
return nil, fmt.Errorf("org.osbuild.grub2.inst: invalid value %q for prefix.type", g2options.Prefix.Type)
}
if !valueIn(g2options.Prefix.PartLabel, []string{"gpt", "dos"}) {
return nil, fmt.Errorf("org.osbuild.grub2.inst: invalid value %q for core.partlabel", g2options.Core.PartLabel)
}
}
return json.Marshal(g2options)
@ -152,15 +156,32 @@ func NewGrub2InstStageOption(filename string, pt *disk.PartitionTable, platform
PartLabel: pt.Type.String(),
// bootidx can't be negative after check with rootIdx above:
// nolint:gosec
Number: uint(bootIdx),
Number: common.ToPtr(uint(bootIdx)),
Path: prefixPath,
}
return &Grub2InstStageOptions{
Filename: filename,
Platform: platform,
Location: coreLocation,
Location: common.ToPtr(coreLocation),
Core: core,
Prefix: prefix,
}
}
// NewGrub2InstISO9660StageOption returns the options needed to create the eltoritio.img
// for use on an iso
func NewGrub2InstISO9660StageOption(filename, prefix string) *Grub2InstStageOptions {
return &Grub2InstStageOptions{
Filename: filename,
Platform: "i386-pc",
Core: CoreMkImage{
Type: "mkimage",
PartLabel: "gpt",
Filesystem: "iso9660",
},
Prefix: PrefixPartition{
Path: prefix,
},
}
}

View file

@ -0,0 +1,50 @@
package osbuild
import "fmt"
const grub2isoLegacyStageType = "org.osbuild.grub2.iso.legacy"
type Grub2ISOLegacyStageOptions struct {
Product Product `json:"product"`
Kernel ISOKernel `json:"kernel"`
ISOLabel string `json:"isolabel"`
}
func (Grub2ISOLegacyStageOptions) isStageOptions() {}
func (o Grub2ISOLegacyStageOptions) validate() error {
// The stage schema marks product.name, product.version, kernel.dir, and
// isolabel as required. Empty values are technically valid according to
// the schema, but here we will consider them invalid.
if o.Product.Name == "" {
return fmt.Errorf("%s: product.name option is required", grub2isoLegacyStageType)
}
if o.Product.Version == "" {
return fmt.Errorf("%s: product.version option is required", grub2isoLegacyStageType)
}
if o.Kernel.Dir == "" {
return fmt.Errorf("%s: kernel.dir option is required", grub2isoLegacyStageType)
}
if o.ISOLabel == "" {
return fmt.Errorf("%s: isolabel option is required", grub2isoLegacyStageType)
}
return nil
}
// Assemble a file system tree for a bootable ISO
func NewGrub2ISOLegacyStage(options *Grub2ISOLegacyStageOptions) *Stage {
if err := options.validate(); err != nil {
panic(err)
}
return &Stage{
Type: grub2isoLegacyStageType,
Options: options,
}
}

View file

@ -1,5 +1,13 @@
package osbuild
import (
"regexp"
"strings"
)
// vfat volume-id is a 32-bit hex number (mkfs.vfat(8))
const fatVolIDRegex = `^[a-fA-F0-9]{8}$`
type MkfsFATStageOptions struct {
VolID string `json:"volid"`
Label string `json:"label,omitempty"`
@ -15,3 +23,13 @@ func NewMkfsFATStage(options *MkfsFATStageOptions, devices map[string]Device) *S
Devices: devices,
}
}
func isFATVolID(id string) bool {
// Internally, we generate FAT volume IDs with a dash (-) in the middle.
// This is also how they're represented by udev (in /dev/disk/by-uuid). The
// mkfs.vfat command doesn't accept dashes, which is why we remove them
// when generating the mkfs stage in mkfs_stage.go. This check removes all
// dashes to determine if the given id is a valid vfat volid.
volidre := regexp.MustCompile(fatVolIDRegex)
return volidre.MatchString(strings.Replace(id, "-", "", -1))
}

View file

@ -4,8 +4,15 @@ import (
"fmt"
"path/filepath"
"regexp"
"slices"
"strings"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/disk"
)
const unitFilenameRegex = "^[\\w:.\\\\-]+[@]{0,1}[\\w:.\\\\-]*\\.(service|mount|socket|swap)$"
type SystemdServiceType string
type SystemdUnitPath string
@ -51,6 +58,13 @@ type MountSection struct {
Options string `json:"Options,omitempty"`
}
type SwapSection struct {
What string `json:"What"`
Priority *int `json:"Priority,omitempty"`
Options string `json:"Options,omitempty"`
TimeoutSec string `json:"TimeoutSec,omitempty"`
}
type SocketSection struct {
Service string `json:"Service,omitempty"`
ListenStream string `json:"ListenStream,omitempty"`
@ -73,10 +87,11 @@ type InstallSection struct {
type SystemdUnit struct {
Unit *UnitSection `json:"Unit"`
Service *ServiceSection `json:"Service"`
Service *ServiceSection `json:"Service,omitempty"`
Mount *MountSection `json:"Mount,omitempty"`
Socket *SocketSection `json:"Socket,omitempty"`
Install *InstallSection `json:"Install"`
Swap *SwapSection `json:"Swap,omitempty"`
Install *InstallSection `json:"Install,omitempty"`
}
type SystemdUnitCreateStageOptions struct {
@ -102,6 +117,9 @@ func (o *SystemdUnitCreateStageOptions) validateService() error {
if o.Config.Socket != nil {
return fmt.Errorf("systemd service unit %q contains invalid section Socket", o.Filename)
}
if o.Config.Swap != nil {
return fmt.Errorf("systemd service unit %q contains invalid section Swap", o.Filename)
}
vre := regexp.MustCompile(envVarRegex)
if service := o.Config.Service; service != nil {
@ -119,12 +137,19 @@ func (o *SystemdUnitCreateStageOptions) validateMount() error {
if o.Config.Mount == nil {
return fmt.Errorf("systemd mount unit %q requires a Mount section", o.Filename)
}
if o.Config.Swap != nil {
return fmt.Errorf("systemd mount unit %q contains invalid section Swap", o.Filename)
}
if o.Config.Service != nil {
return fmt.Errorf("systemd mount unit %q contains invalid section Service", o.Filename)
}
if o.Config.Socket != nil {
return fmt.Errorf("systemd mount unit %q contains invalid section Socket", o.Filename)
}
if o.Config.Swap != nil {
return fmt.Errorf("systemd mount unit %q contains invalid section Swap", o.Filename)
}
if o.Config.Mount.What == "" {
return fmt.Errorf("What option for Mount section of systemd unit %q is required", o.Filename)
@ -136,24 +161,47 @@ func (o *SystemdUnitCreateStageOptions) validateMount() error {
return nil
}
func (o *SystemdUnitCreateStageOptions) validateSwap() error {
if o.Config.Swap == nil {
return fmt.Errorf("systemd swap unit %q requires a Swap section", o.Filename)
}
if o.Config.Mount != nil {
return fmt.Errorf("systemd swap unit %q contains invalid section Mount", o.Filename)
}
if o.Config.Service != nil {
return fmt.Errorf("systemd swap unit %q contains invalid section Service", o.Filename)
}
if o.Config.Socket != nil {
return fmt.Errorf("systemd swap unit %q contains invalid section Socket", o.Filename)
}
return nil
}
func (o *SystemdUnitCreateStageOptions) validateSocket() error {
if o.Config.Socket == nil {
return fmt.Errorf("systemd socket unit %q requires a Socket section", o.Filename)
}
if o.Config.Mount != nil {
return fmt.Errorf("systemd socket unit %q contains invalid section Mount", o.Filename)
}
if o.Config.Service != nil {
return fmt.Errorf("systemd socket unit %q contains invalid section Service", o.Filename)
}
if o.Config.Swap != nil {
return fmt.Errorf("systemd socket unit %q contains invalid section Swap", o.Filename)
}
return nil
}
func (o *SystemdUnitCreateStageOptions) validate() error {
fre := regexp.MustCompile(filenameRegex)
fre := regexp.MustCompile(unitFilenameRegex)
if !fre.MatchString(o.Filename) {
return fmt.Errorf("invalid filename %q for systemd unit: does not conform to schema (%s)", o.Filename, filenameRegex)
return fmt.Errorf("invalid filename %q for systemd unit: does not conform to schema (%s)", o.Filename, unitFilenameRegex)
}
switch filepath.Ext(o.Filename) {
@ -161,10 +209,13 @@ func (o *SystemdUnitCreateStageOptions) validate() error {
return o.validateService()
case ".mount":
return o.validateMount()
case ".swap":
return o.validateSwap()
case ".socket":
return o.validateSocket()
default:
return fmt.Errorf("invalid filename %q for systemd unit: extension must be one of .service, .mount, or .socket", o.Filename)
// this should be caught by the regex
return fmt.Errorf("invalid filename %q for systemd unit: extension must be one of .service, .mount, .swap, or .socket", o.Filename)
}
}
@ -177,3 +228,98 @@ func NewSystemdUnitCreateStage(options *SystemdUnitCreateStageOptions) *Stage {
Options: options,
}
}
// GenSystemdMountStages generates a collection of
// org.osbuild.systemd.unit.create stages with options to create systemd mount
// units, one for each mountpoint in the partition table.
func GenSystemdMountStages(pt *disk.PartitionTable) ([]*Stage, error) {
mountStages := make([]*Stage, 0)
unitNames := make([]string, 0)
genOption := func(ent disk.FSTabEntity, path []disk.Entity) error {
fsSpec := ent.GetFSSpec()
fsOptions, err := ent.GetFSTabOptions()
if err != nil {
return err
}
options := &SystemdUnitCreateStageOptions{
Config: SystemdUnit{
Unit: &UnitSection{
// Adds the following dependencies for mount units (systemd.mount(5)):
// - Before=umount.target
// - Conflicts=umount.target
// - After=local-fs-pre.target
// - Before=local-fs.target
// and the following for swap units (systemd.swap(5)):
// - Before=umount.target
// - Conflicts=umount.target
DefaultDependencies: common.ToPtr(true),
},
Install: &InstallSection{
WantedBy: []string{"multi-user.target"},
},
},
}
device := filepath.Join("/dev/disk/by-uuid", strings.ToLower(fsSpec.UUID))
if isFATVolID(fsSpec.UUID) {
// vfat IDs aren't lowercased
device = filepath.Join("/dev/disk/by-uuid", fsSpec.UUID)
}
switch ent.GetFSType() {
case "swap":
options.Filename = fmt.Sprintf("%s.swap", pathEscape(device))
options.Config.Swap = &SwapSection{
What: device,
Options: fsOptions.MntOps,
}
default:
options.Filename = fmt.Sprintf("%s.mount", pathEscape(ent.GetFSFile()))
options.Config.Mount = &MountSection{
What: device,
Where: ent.GetFSFile(),
Type: ent.GetFSType(),
Options: fsOptions.MntOps,
}
}
mountStages = append(mountStages, NewSystemdUnitCreateStage(options))
unitNames = append(unitNames, options.Filename)
return nil
}
err := pt.ForEachFSTabEntity(genOption)
if err != nil {
return nil, err
}
// sort the entries by filename for stable ordering
slices.SortFunc(mountStages, func(a, b *Stage) int {
optsa := a.Options.(*SystemdUnitCreateStageOptions)
optsb := b.Options.(*SystemdUnitCreateStageOptions)
// this sorter is not guaranteed to be stable, but the unit Filenames
// are unique
switch {
case optsa.Filename < optsb.Filename:
return -1
case optsa.Filename > optsb.Filename:
return 1
}
panic(fmt.Sprintf("error sorting systemd unit mount stages: possible duplicate mount unit filenames: %q %q", optsa.Filename, optsb.Filename))
})
// sort the unit names for the systemd (enable) stage for stable ordering
slices.Sort(unitNames)
if len(unitNames) > 0 {
enableStage := NewSystemdStage(&SystemdStageOptions{
EnabledServices: unitNames,
})
mountStages = append(mountStages, enableStage)
}
return mountStages, nil
}

View file

@ -19,6 +19,11 @@ type XorrisofsStageOptions struct {
// The ISO 9660 version (limits data size and filenames; min: 1, max: 4)
ISOLevel int `json:"isolevel,omitempty"`
// Path to grub2 hybrid mbr boot image
// This will cause the created iso to use grub2 instead of syslinux/isolinux
// when booting on BIOS systems.
Grub2MBR string `json:"grub2mbr,omitempty"`
}
type XorrisofsBoot struct {

2
vendor/modules.txt vendored
View file

@ -1045,7 +1045,7 @@ github.com/oracle/oci-go-sdk/v54/identity
github.com/oracle/oci-go-sdk/v54/objectstorage
github.com/oracle/oci-go-sdk/v54/objectstorage/transfer
github.com/oracle/oci-go-sdk/v54/workrequests
# github.com/osbuild/images v0.123.0
# github.com/osbuild/images v0.124.0
## explicit; go 1.22.8
github.com/osbuild/images/data/dependencies
github.com/osbuild/images/data/repositories