Move the FactsImageOptions from distro to the new rhsm/facts package. At the same time define the values we use as an enum, including the "test-manifest" value. Though the values don't really matter, the test value is defined first so it takes the 0 value, which feels nicer conceptually. The field in the distro.ImageOptions is changed to be a pointer to allow for nil values.
250 lines
7.9 KiB
Go
250 lines
7.9 KiB
Go
package rhel7
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
|
"github.com/osbuild/osbuild-composer/internal/common"
|
|
"github.com/osbuild/osbuild-composer/internal/container"
|
|
"github.com/osbuild/osbuild-composer/internal/distro"
|
|
"github.com/osbuild/osbuild-composer/internal/image"
|
|
"github.com/osbuild/osbuild-composer/internal/manifest"
|
|
"github.com/osbuild/osbuild-composer/internal/osbuild"
|
|
"github.com/osbuild/osbuild-composer/internal/platform"
|
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
|
"github.com/osbuild/osbuild-composer/internal/users"
|
|
"github.com/osbuild/osbuild-composer/internal/workload"
|
|
)
|
|
|
|
func osCustomizations(
|
|
t *imageType,
|
|
osPackageSet rpmmd.PackageSet,
|
|
options distro.ImageOptions,
|
|
containers []container.Spec,
|
|
c *blueprint.Customizations,
|
|
) manifest.OSCustomizations {
|
|
|
|
imageConfig := t.getDefaultImageConfig()
|
|
|
|
osc := manifest.OSCustomizations{}
|
|
|
|
if t.bootable {
|
|
osc.KernelName = c.GetKernel().Name
|
|
|
|
var kernelOptions []string
|
|
if t.kernelOptions != "" {
|
|
kernelOptions = append(kernelOptions, t.kernelOptions)
|
|
}
|
|
if bpKernel := c.GetKernel(); bpKernel.Append != "" {
|
|
kernelOptions = append(kernelOptions, bpKernel.Append)
|
|
}
|
|
osc.KernelOptionsAppend = kernelOptions
|
|
if t.platform.GetArch() != platform.ARCH_S390X {
|
|
osc.KernelOptionsBootloader = true
|
|
}
|
|
}
|
|
|
|
osc.ExtraBasePackages = osPackageSet.Include
|
|
osc.ExcludeBasePackages = osPackageSet.Exclude
|
|
osc.ExtraBaseRepos = osPackageSet.Repositories
|
|
|
|
osc.Containers = containers
|
|
|
|
osc.GPGKeyFiles = imageConfig.GPGKeyFiles
|
|
if imageConfig.ExcludeDocs != nil {
|
|
osc.ExcludeDocs = *imageConfig.ExcludeDocs
|
|
}
|
|
|
|
// don't put users and groups in the payload of an installer
|
|
// add them via kickstart instead
|
|
osc.Groups = users.GroupsFromBP(c.GetGroups())
|
|
osc.Users = users.UsersFromBP(c.GetUsers())
|
|
|
|
osc.EnabledServices = imageConfig.EnabledServices
|
|
osc.DisabledServices = imageConfig.DisabledServices
|
|
if imageConfig.DefaultTarget != nil {
|
|
osc.DefaultTarget = *imageConfig.DefaultTarget
|
|
}
|
|
|
|
osc.Firewall = imageConfig.Firewall
|
|
if fw := c.GetFirewall(); fw != nil {
|
|
options := osbuild.FirewallStageOptions{
|
|
Ports: fw.Ports,
|
|
}
|
|
|
|
if fw.Services != nil {
|
|
options.EnabledServices = fw.Services.Enabled
|
|
options.DisabledServices = fw.Services.Disabled
|
|
}
|
|
if fw.Zones != nil {
|
|
for _, z := range fw.Zones {
|
|
options.Zones = append(options.Zones, osbuild.FirewallZone{
|
|
Name: *z.Name,
|
|
Sources: z.Sources,
|
|
})
|
|
}
|
|
}
|
|
osc.Firewall = &options
|
|
}
|
|
|
|
language, keyboard := c.GetPrimaryLocale()
|
|
if language != nil {
|
|
osc.Language = *language
|
|
} else if imageConfig.Locale != nil {
|
|
osc.Language = *imageConfig.Locale
|
|
}
|
|
if keyboard != nil {
|
|
osc.Keyboard = keyboard
|
|
} else if imageConfig.Keyboard != nil {
|
|
osc.Keyboard = &imageConfig.Keyboard.Keymap
|
|
if imageConfig.Keyboard.X11Keymap != nil {
|
|
osc.X11KeymapLayouts = imageConfig.Keyboard.X11Keymap.Layouts
|
|
}
|
|
}
|
|
|
|
if hostname := c.GetHostname(); hostname != nil {
|
|
osc.Hostname = *hostname
|
|
}
|
|
|
|
timezone, ntpServers := c.GetTimezoneSettings()
|
|
if timezone != nil {
|
|
osc.Timezone = *timezone
|
|
} else if imageConfig.Timezone != nil {
|
|
osc.Timezone = *imageConfig.Timezone
|
|
}
|
|
|
|
if len(ntpServers) > 0 {
|
|
for _, server := range ntpServers {
|
|
osc.NTPServers = append(osc.NTPServers, osbuild.ChronyConfigServer{Hostname: server})
|
|
}
|
|
} else if imageConfig.TimeSynchronization != nil {
|
|
osc.NTPServers = imageConfig.TimeSynchronization.Servers
|
|
osc.LeapSecTZ = imageConfig.TimeSynchronization.LeapsecTz
|
|
}
|
|
|
|
// Relabel the tree, unless the `NoSElinux` flag is explicitly set to `true`
|
|
if imageConfig.NoSElinux == nil || imageConfig.NoSElinux != nil && !*imageConfig.NoSElinux {
|
|
osc.SElinux = "targeted"
|
|
osc.SELinuxForceRelabel = imageConfig.SELinuxForceRelabel
|
|
}
|
|
|
|
if oscapConfig := c.GetOpenSCAP(); oscapConfig != nil {
|
|
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(
|
|
osbuild.OscapConfig{
|
|
Datastream: oscapConfig.DataStream,
|
|
ProfileID: oscapConfig.ProfileID,
|
|
},
|
|
)
|
|
}
|
|
|
|
if t.arch.distro.isRHEL() && options.Facts != nil {
|
|
osc.FactAPIType = &options.Facts.APIType
|
|
}
|
|
|
|
var err error
|
|
osc.Directories, err = blueprint.DirectoryCustomizationsToFsNodeDirectories(c.GetDirectories())
|
|
if err != nil {
|
|
// In theory this should never happen, because the blueprint directory customizations
|
|
// should have been validated before this point.
|
|
panic(fmt.Sprintf("failed to convert directory customizations to fs node directories: %v", err))
|
|
}
|
|
|
|
osc.Files, err = blueprint.FileCustomizationsToFsNodeFiles(c.GetFiles())
|
|
if err != nil {
|
|
// In theory this should never happen, because the blueprint file customizations
|
|
// should have been validated before this point.
|
|
panic(fmt.Sprintf("failed to convert file customizations to fs node files: %v", err))
|
|
}
|
|
|
|
// set yum repos first, so it doesn't get overridden by
|
|
// imageConfig.YUMRepos
|
|
osc.YUMRepos = imageConfig.YUMRepos
|
|
|
|
customRepos, err := c.GetRepositories()
|
|
if err != nil {
|
|
// This shouldn't happen and since the repos
|
|
// should have already been validated
|
|
panic(fmt.Sprintf("failed to get custom repos: %v", err))
|
|
}
|
|
|
|
// This function returns a map of filename and corresponding yum repos
|
|
// and a list of fs node files for the inline gpg keys so we can save
|
|
// them to disk. This step also swaps the inline gpg key with the path
|
|
// to the file in the os file tree
|
|
yumRepos, gpgKeyFiles, err := blueprint.RepoCustomizationsToRepoConfigAndGPGKeyFiles(customRepos)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("failed to convert inline gpgkeys to fs node files: %v", err))
|
|
}
|
|
|
|
// add the gpg key files to the list of files to be added to the tree
|
|
if len(gpgKeyFiles) > 0 {
|
|
osc.Files = append(osc.Files, gpgKeyFiles...)
|
|
}
|
|
|
|
for filename, repos := range yumRepos {
|
|
osc.YUMRepos = append(osc.YUMRepos, osbuild.NewYumReposStageOptions(filename, repos))
|
|
}
|
|
|
|
osc.ShellInit = imageConfig.ShellInit
|
|
|
|
osc.Grub2Config = imageConfig.Grub2Config
|
|
osc.Sysconfig = imageConfig.Sysconfig
|
|
osc.SystemdLogind = imageConfig.SystemdLogind
|
|
osc.CloudInit = imageConfig.CloudInit
|
|
osc.Modprobe = imageConfig.Modprobe
|
|
osc.DracutConf = imageConfig.DracutConf
|
|
osc.SystemdUnit = imageConfig.SystemdUnit
|
|
osc.Authselect = imageConfig.Authselect
|
|
osc.SELinuxConfig = imageConfig.SELinuxConfig
|
|
osc.Tuned = imageConfig.Tuned
|
|
osc.Tmpfilesd = imageConfig.Tmpfilesd
|
|
osc.PamLimitsConf = imageConfig.PamLimitsConf
|
|
osc.Sysctld = imageConfig.Sysctld
|
|
osc.DNFConfig = imageConfig.DNFConfig
|
|
osc.DNFAutomaticConfig = imageConfig.DNFAutomaticConfig
|
|
osc.YUMConfig = imageConfig.YumConfig
|
|
osc.SshdConfig = imageConfig.SshdConfig
|
|
osc.AuthConfig = imageConfig.Authconfig
|
|
osc.PwQuality = imageConfig.PwQuality
|
|
osc.RHSMConfig = imageConfig.RHSMConfig
|
|
osc.Subscription = options.Subscription
|
|
osc.WAAgentConfig = imageConfig.WAAgentConfig
|
|
osc.UdevRules = imageConfig.UdevRules
|
|
osc.GCPGuestAgentConfig = imageConfig.GCPGuestAgentConfig
|
|
|
|
return osc
|
|
}
|
|
|
|
func liveImage(workload workload.Workload,
|
|
t *imageType,
|
|
customizations *blueprint.Customizations,
|
|
options distro.ImageOptions,
|
|
packageSets map[string]rpmmd.PackageSet,
|
|
containers []container.Spec,
|
|
rng *rand.Rand) (image.ImageKind, error) {
|
|
|
|
img := image.NewLiveImage()
|
|
img.Platform = t.platform
|
|
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], options, containers, customizations)
|
|
img.Environment = t.environment
|
|
img.Workload = workload
|
|
img.Compression = t.compression
|
|
img.PartTool = osbuild.PTSgdisk // all RHEL 7 images should use sgdisk
|
|
img.ForceSize = common.ToPtr(false) // RHEL 7 qemu vpc subformat does not support force_size
|
|
img.NoBLS = true // RHEL 7 grub does not support BLS
|
|
img.OSProduct = t.arch.distro.product
|
|
img.OSVersion = t.arch.distro.osVersion
|
|
img.OSNick = t.arch.distro.nick
|
|
|
|
// TODO: move generation into LiveImage
|
|
pt, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
img.PartitionTable = pt
|
|
|
|
img.Filename = t.Filename()
|
|
|
|
return img, nil
|
|
}
|