These return the parent object of the Arch and ImageType, respectively. Not a functional change. Signed-off-by: Tom Gundersen <teg@jklm.no>
847 lines
20 KiB
Go
847 lines
20 KiB
Go
package rhel81
|
|
|
|
import (
|
|
"errors"
|
|
"sort"
|
|
"strconv"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/distro"
|
|
"github.com/osbuild/osbuild-composer/internal/osbuild"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
|
"github.com/osbuild/osbuild-composer/internal/crypt"
|
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
|
)
|
|
|
|
const name = "rhel-8.1"
|
|
const modulePlatformID = "platform:el8"
|
|
|
|
type RHEL81 struct {
|
|
arches map[string]arch
|
|
imageTypes map[string]imageType
|
|
buildPackages []string
|
|
}
|
|
|
|
type arch struct {
|
|
name string
|
|
bootloaderPackages []string
|
|
buildPackages []string
|
|
uefi bool
|
|
}
|
|
|
|
type imageType struct {
|
|
name string
|
|
mimeType string
|
|
packages []string
|
|
excludedPackages []string
|
|
enabledServices []string
|
|
disabledServices []string
|
|
bootable bool
|
|
defaultTarget string
|
|
kernelOptions string
|
|
defaultSize uint64
|
|
assembler func(uefi bool, size uint64) *osbuild.Assembler
|
|
}
|
|
|
|
type rhel81Arch struct {
|
|
name string
|
|
distro *RHEL81
|
|
arch *arch
|
|
}
|
|
|
|
type rhel81ImageType struct {
|
|
name string
|
|
arch *rhel81Arch
|
|
imageType *imageType
|
|
}
|
|
|
|
func (a *rhel81Arch) Distro() distro.Distro {
|
|
return a.distro
|
|
}
|
|
|
|
func (t *rhel81ImageType) Arch() distro.Arch {
|
|
return t.arch
|
|
}
|
|
|
|
func (d *RHEL81) ListArches() []string {
|
|
archs := make([]string, 0, len(d.arches))
|
|
for name := range d.arches {
|
|
archs = append(archs, name)
|
|
}
|
|
sort.Strings(archs)
|
|
return archs
|
|
}
|
|
|
|
func (d *RHEL81) GetArch(name string) (distro.Arch, error) {
|
|
a, exists := d.arches[name]
|
|
if !exists {
|
|
return nil, errors.New("invalid architecture: " + name)
|
|
}
|
|
|
|
return &rhel81Arch{
|
|
name: name,
|
|
distro: d,
|
|
arch: &a,
|
|
}, nil
|
|
}
|
|
|
|
func (a *rhel81Arch) Name() string {
|
|
return a.name
|
|
}
|
|
|
|
func (a *rhel81Arch) ListImageTypes() []string {
|
|
formats := make([]string, 0, len(a.distro.imageTypes))
|
|
for name := range a.distro.imageTypes {
|
|
formats = append(formats, name)
|
|
}
|
|
sort.Strings(formats)
|
|
return formats
|
|
}
|
|
|
|
func (a *rhel81Arch) GetImageType(name string) (distro.ImageType, error) {
|
|
t, exists := a.distro.imageTypes[name]
|
|
if !exists {
|
|
return nil, errors.New("invalid image type: " + name)
|
|
}
|
|
|
|
return &rhel81ImageType{
|
|
name: name,
|
|
arch: a,
|
|
imageType: &t,
|
|
}, nil
|
|
}
|
|
|
|
func (t *rhel81ImageType) Name() string {
|
|
return t.name
|
|
}
|
|
|
|
func (t *rhel81ImageType) Filename() string {
|
|
return t.imageType.name
|
|
}
|
|
|
|
func (t *rhel81ImageType) MIMEType() string {
|
|
return t.imageType.mimeType
|
|
}
|
|
|
|
func (t *rhel81ImageType) Size(size uint64) uint64 {
|
|
const MegaByte = 1024 * 1024
|
|
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
|
|
if t.name == "vhd" && size%MegaByte != 0 {
|
|
size = (size/MegaByte + 1) * MegaByte
|
|
}
|
|
if size == 0 {
|
|
size = t.imageType.defaultSize
|
|
}
|
|
return size
|
|
}
|
|
|
|
func (t *rhel81ImageType) BasePackages() ([]string, []string) {
|
|
packages := t.imageType.packages
|
|
if t.imageType.bootable {
|
|
packages = append(packages, t.arch.arch.bootloaderPackages...)
|
|
}
|
|
|
|
return packages, t.imageType.excludedPackages
|
|
}
|
|
|
|
func (t *rhel81ImageType) BuildPackages() []string {
|
|
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
|
|
}
|
|
|
|
func (t *rhel81ImageType) Manifest(c *blueprint.Customizations,
|
|
repos []rpmmd.RepoConfig,
|
|
packageSpecs,
|
|
buildPackageSpecs []rpmmd.PackageSpec,
|
|
size uint64) (*osbuild.Manifest, error) {
|
|
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &osbuild.Manifest{
|
|
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
|
|
Pipeline: *pipeline,
|
|
}, nil
|
|
}
|
|
|
|
func New() *RHEL81 {
|
|
const GigaByte = 1024 * 1024 * 1024
|
|
|
|
r := RHEL81{
|
|
imageTypes: map[string]imageType{},
|
|
buildPackages: []string{
|
|
"dnf",
|
|
"dosfstools",
|
|
"e2fsprogs",
|
|
"glibc",
|
|
"policycoreutils",
|
|
"python36",
|
|
"qemu-img",
|
|
"systemd",
|
|
"tar",
|
|
"xfsprogs",
|
|
"xz",
|
|
},
|
|
arches: map[string]arch{
|
|
"x86_64": arch{
|
|
name: "x86_64",
|
|
bootloaderPackages: []string{
|
|
"dracut-config-generic",
|
|
"grub2-pc",
|
|
},
|
|
buildPackages: []string{
|
|
"grub2-pc",
|
|
},
|
|
},
|
|
"aarch64": arch{
|
|
name: "aarch64",
|
|
bootloaderPackages: []string{
|
|
"dracut-config-generic",
|
|
"efibootmgr",
|
|
"grub2-efi-aa64",
|
|
"grub2-tools",
|
|
"shim-aa64",
|
|
},
|
|
uefi: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
r.imageTypes["ami"] = imageType{
|
|
name: "image.vhdx",
|
|
mimeType: "application/octet-stream",
|
|
packages: []string{
|
|
"checkpolicy",
|
|
"chrony",
|
|
"cloud-init",
|
|
"cloud-init",
|
|
"cloud-utils-growpart",
|
|
"@core",
|
|
"dhcp-client",
|
|
"gdisk",
|
|
"insights-client",
|
|
"kernel",
|
|
"langpacks-en",
|
|
"net-tools",
|
|
"NetworkManager",
|
|
"redhat-release",
|
|
"redhat-release-eula",
|
|
"rng-tools",
|
|
"rsync",
|
|
"selinux-policy-targeted",
|
|
"tar",
|
|
"yum-utils",
|
|
|
|
// TODO this doesn't exist in BaseOS or AppStream
|
|
// "rh-amazon-rhui-client",
|
|
},
|
|
excludedPackages: []string{
|
|
"aic94xx-firmware",
|
|
"alsa-firmware",
|
|
"alsa-lib",
|
|
"alsa-tools-firmware",
|
|
"biosdevname",
|
|
"dracut-config-rescue",
|
|
"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",
|
|
|
|
// TODO this cannot be removed, because the kernel (?)
|
|
// depends on it. The ec2 kickstart force-removes it.
|
|
// "linux-firmware",
|
|
|
|
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
|
|
// https://errata.devel.redhat.com/advisory/47339 lands
|
|
"timedatex",
|
|
},
|
|
defaultTarget: "multi-user.target",
|
|
bootable: true,
|
|
kernelOptions: "ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
|
|
defaultSize: 6 * GigaByte,
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
|
|
return r.qemuAssembler("vhdx", "image.vhdx", uefi, size)
|
|
},
|
|
}
|
|
|
|
r.imageTypes["ext4-filesystem"] = imageType{
|
|
name: "filesystem.img",
|
|
mimeType: "application/octet-stream",
|
|
packages: []string{
|
|
"policycoreutils",
|
|
"selinux-policy-targeted",
|
|
"kernel",
|
|
"firewalld",
|
|
"chrony",
|
|
"langpacks-en",
|
|
},
|
|
excludedPackages: []string{
|
|
"dracut-config-rescue",
|
|
|
|
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
|
|
// https://errata.devel.redhat.com/advisory/47339 lands
|
|
"timedatex",
|
|
},
|
|
bootable: false,
|
|
kernelOptions: "ro net.ifnames=0",
|
|
defaultSize: 2 * GigaByte,
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
|
|
}
|
|
|
|
r.imageTypes["partitioned-disk"] = imageType{
|
|
name: "disk.img",
|
|
mimeType: "application/octet-stream",
|
|
packages: []string{
|
|
"@core",
|
|
"chrony",
|
|
"firewalld",
|
|
"kernel",
|
|
"langpacks-en",
|
|
"selinux-policy-targeted",
|
|
},
|
|
excludedPackages: []string{
|
|
"dracut-config-rescue",
|
|
|
|
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
|
|
// https://errata.devel.redhat.com/advisory/47339 lands
|
|
"timedatex",
|
|
},
|
|
bootable: true,
|
|
kernelOptions: "ro net.ifnames=0",
|
|
defaultSize: 2 * GigaByte,
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
|
|
return r.qemuAssembler("raw", "disk.img", uefi, size)
|
|
},
|
|
}
|
|
|
|
r.imageTypes["qcow2"] = imageType{
|
|
name: "disk.qcow2",
|
|
mimeType: "application/x-qemu-disk",
|
|
packages: []string{
|
|
"@core",
|
|
"chrony",
|
|
"dnf",
|
|
"kernel",
|
|
"yum",
|
|
"nfs-utils",
|
|
"dnf-utils",
|
|
"cloud-init",
|
|
"python3-jsonschema",
|
|
"qemu-guest-agent",
|
|
"cloud-utils-growpart",
|
|
"dracut-norescue",
|
|
"tar",
|
|
"tcpdump",
|
|
"rsync",
|
|
"dnf-plugin-spacewalk",
|
|
"rhn-client-tools",
|
|
"rhnlib",
|
|
"rhnsd",
|
|
"rhn-setup",
|
|
"NetworkManager",
|
|
"dhcp-client",
|
|
"cockpit-ws",
|
|
"cockpit-system",
|
|
"subscription-manager-cockpit",
|
|
"redhat-release",
|
|
"redhat-release-eula",
|
|
"rng-tools",
|
|
"insights-client",
|
|
// TODO: rh-amazon-rhui-client
|
|
},
|
|
excludedPackages: []string{
|
|
"dracut-config-rescue",
|
|
"aic94xx-firmware",
|
|
"alsa-firmware",
|
|
"alsa-lib",
|
|
"alsa-tools-firmware",
|
|
"firewalld",
|
|
"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",
|
|
"langpacks-*",
|
|
"langpacks-en",
|
|
"biosdevname",
|
|
"plymouth",
|
|
"iprutils",
|
|
"langpacks-en",
|
|
"fedora-release",
|
|
"fedora-repos",
|
|
|
|
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
|
|
// https://errata.devel.redhat.com/advisory/47339 lands
|
|
"timedatex",
|
|
},
|
|
bootable: true,
|
|
kernelOptions: "console=ttyS0 console=ttyS0,115200n8 no_timer_check crashkernel=auto net.ifnames=0",
|
|
defaultSize: 2 * GigaByte,
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
|
|
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
|
|
},
|
|
}
|
|
|
|
r.imageTypes["openstack"] = imageType{
|
|
name: "disk.qcow2",
|
|
mimeType: "application/x-qemu-disk",
|
|
packages: []string{
|
|
// Defaults
|
|
"@Core",
|
|
"langpacks-en",
|
|
|
|
// From the lorax kickstart
|
|
"kernel",
|
|
"selinux-policy-targeted",
|
|
"cloud-init",
|
|
"qemu-guest-agent",
|
|
"spice-vdagent",
|
|
},
|
|
excludedPackages: []string{
|
|
"dracut-config-rescue",
|
|
},
|
|
bootable: true,
|
|
kernelOptions: "ro net.ifnames=0",
|
|
defaultSize: 2 * GigaByte,
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
|
|
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
|
|
},
|
|
}
|
|
|
|
r.imageTypes["tar"] = imageType{
|
|
name: "root.tar.xz",
|
|
mimeType: "application/x-tar",
|
|
packages: []string{
|
|
"policycoreutils",
|
|
"selinux-policy-targeted",
|
|
"kernel",
|
|
"firewalld",
|
|
"chrony",
|
|
"langpacks-en",
|
|
},
|
|
excludedPackages: []string{
|
|
"dracut-config-rescue",
|
|
|
|
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
|
|
// https://errata.devel.redhat.com/advisory/47339 lands
|
|
"timedatex",
|
|
},
|
|
bootable: false,
|
|
kernelOptions: "ro net.ifnames=0",
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
|
|
}
|
|
|
|
r.imageTypes["vhd"] = imageType{
|
|
name: "disk.vhd",
|
|
mimeType: "application/x-vhd",
|
|
packages: []string{
|
|
// Defaults
|
|
"@Core",
|
|
"langpacks-en",
|
|
|
|
// From the lorax kickstart
|
|
"kernel",
|
|
"selinux-policy-targeted",
|
|
"chrony",
|
|
"WALinuxAgent",
|
|
"python3",
|
|
"net-tools",
|
|
"cloud-init",
|
|
"cloud-utils-growpart",
|
|
"gdisk",
|
|
},
|
|
excludedPackages: []string{
|
|
"dracut-config-rescue",
|
|
|
|
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
|
|
// https://errata.devel.redhat.com/advisory/47339 lands
|
|
"timedatex",
|
|
},
|
|
enabledServices: []string{
|
|
"sshd",
|
|
"waagent",
|
|
},
|
|
defaultTarget: "multi-user.target",
|
|
bootable: true,
|
|
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
|
|
defaultSize: 2 * GigaByte,
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
|
|
return r.qemuAssembler("vpc", "disk.vhd", uefi, size)
|
|
},
|
|
}
|
|
|
|
r.imageTypes["vmdk"] = imageType{
|
|
name: "disk.vmdk",
|
|
mimeType: "application/x-vmdk",
|
|
packages: []string{
|
|
"@core",
|
|
"chrony",
|
|
"firewalld",
|
|
"kernel",
|
|
"langpacks-en",
|
|
"open-vm-tools",
|
|
"selinux-policy-targeted",
|
|
},
|
|
excludedPackages: []string{
|
|
"dracut-config-rescue",
|
|
|
|
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
|
|
// https://errata.devel.redhat.com/advisory/47339 lands
|
|
"timedatex",
|
|
},
|
|
bootable: true,
|
|
kernelOptions: "ro net.ifnames=0",
|
|
defaultSize: 2 * GigaByte,
|
|
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
|
|
return r.qemuAssembler("vmdk", "disk.vmdk", uefi, size)
|
|
},
|
|
}
|
|
|
|
return &r
|
|
}
|
|
|
|
func (r *RHEL81) Name() string {
|
|
return name
|
|
}
|
|
|
|
func (r *RHEL81) ModulePlatformID() string {
|
|
return modulePlatformID
|
|
}
|
|
|
|
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
|
|
files := &osbuild.FilesSource{
|
|
URLs: make(map[string]string),
|
|
}
|
|
for _, pkg := range packages {
|
|
files.URLs[pkg.Checksum] = pkg.RemoteLocation
|
|
}
|
|
return &osbuild.Sources{
|
|
"org.osbuild.files": files,
|
|
}
|
|
}
|
|
|
|
func (t *rhel81ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
|
|
p := &osbuild.Pipeline{}
|
|
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.rhel81")
|
|
|
|
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
|
|
p.AddStage(osbuild.NewFixBLSStage())
|
|
|
|
if t.imageType.bootable {
|
|
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
|
|
}
|
|
|
|
kernelOptions := t.imageType.kernelOptions
|
|
if kernel := c.GetKernel(); kernel != nil {
|
|
kernelOptions += " " + kernel.Append
|
|
}
|
|
p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(kernelOptions, t.arch.arch.uefi)))
|
|
|
|
// TODO support setting all languages and install corresponding langpack-* package
|
|
language, keyboard := c.GetPrimaryLocale()
|
|
|
|
if language != nil {
|
|
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{*language}))
|
|
} else {
|
|
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{"en_US"}))
|
|
}
|
|
|
|
if keyboard != nil {
|
|
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{*keyboard}))
|
|
}
|
|
|
|
if hostname := c.GetHostname(); hostname != nil {
|
|
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{*hostname}))
|
|
}
|
|
|
|
timezone, ntpServers := c.GetTimezoneSettings()
|
|
|
|
// TODO install chrony when this is set?
|
|
if timezone != nil {
|
|
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{*timezone}))
|
|
}
|
|
|
|
if len(ntpServers) > 0 {
|
|
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{ntpServers}))
|
|
}
|
|
|
|
if users := c.GetUsers(); len(users) > 0 {
|
|
options, err := t.userStageOptions(users)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
p.AddStage(osbuild.NewUsersStage(options))
|
|
}
|
|
|
|
if groups := c.GetGroups(); len(groups) > 0 {
|
|
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
|
|
}
|
|
|
|
if services := c.GetServices(); services != nil || t.imageType.enabledServices != nil {
|
|
p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.imageType.enabledServices, t.imageType.disabledServices, services, t.imageType.defaultTarget)))
|
|
}
|
|
|
|
if firewall := c.GetFirewall(); firewall != nil {
|
|
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
|
|
}
|
|
|
|
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
|
|
|
|
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
|
|
|
|
return p, nil
|
|
}
|
|
|
|
func (r *rhel81ImageType) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
|
|
p := &osbuild.Pipeline{}
|
|
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, buildPackageSpecs)))
|
|
return p
|
|
}
|
|
|
|
func (r *rhel81ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
|
|
var gpgKeys []string
|
|
for _, repo := range repos {
|
|
if repo.GPGKey == "" {
|
|
continue
|
|
}
|
|
gpgKeys = append(gpgKeys, repo.GPGKey)
|
|
}
|
|
|
|
var packages []string
|
|
for _, spec := range specs {
|
|
packages = append(packages, spec.Checksum)
|
|
}
|
|
|
|
return &osbuild.RPMStageOptions{
|
|
GPGKeys: gpgKeys,
|
|
Packages: packages,
|
|
}
|
|
}
|
|
|
|
func (r *rhel81ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
|
|
options := osbuild.UsersStageOptions{
|
|
Users: make(map[string]osbuild.UsersStageOptionsUser),
|
|
}
|
|
|
|
for _, c := range users {
|
|
if c.Password != nil && !crypt.PasswordIsCrypted(*c.Password) {
|
|
cryptedPassword, err := crypt.CryptSHA512(*c.Password)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c.Password = &cryptedPassword
|
|
}
|
|
|
|
user := osbuild.UsersStageOptionsUser{
|
|
Groups: c.Groups,
|
|
Description: c.Description,
|
|
Home: c.Home,
|
|
Shell: c.Shell,
|
|
Password: c.Password,
|
|
Key: c.Key,
|
|
}
|
|
|
|
if c.UID != nil {
|
|
uid := strconv.Itoa(*c.UID)
|
|
user.UID = &uid
|
|
}
|
|
|
|
if c.GID != nil {
|
|
gid := strconv.Itoa(*c.GID)
|
|
user.GID = &gid
|
|
}
|
|
|
|
options.Users[c.Name] = user
|
|
}
|
|
|
|
return &options, nil
|
|
}
|
|
|
|
func (r *rhel81ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
|
|
options := osbuild.GroupsStageOptions{
|
|
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
|
|
}
|
|
|
|
for _, group := range groups {
|
|
groupData := osbuild.GroupsStageOptionsGroup{
|
|
Name: group.Name,
|
|
}
|
|
if group.GID != nil {
|
|
gid := strconv.Itoa(*group.GID)
|
|
groupData.GID = &gid
|
|
}
|
|
|
|
options.Groups[group.Name] = groupData
|
|
}
|
|
|
|
return &options
|
|
}
|
|
|
|
func (r *rhel81ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
|
|
options := osbuild.FirewallStageOptions{
|
|
Ports: firewall.Ports,
|
|
}
|
|
|
|
if firewall.Services != nil {
|
|
options.EnabledServices = firewall.Services.Enabled
|
|
options.DisabledServices = firewall.Services.Disabled
|
|
}
|
|
|
|
return &options
|
|
}
|
|
|
|
func (r *rhel81ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
|
|
if s != nil {
|
|
enabledServices = append(enabledServices, s.Enabled...)
|
|
disabledServices = append(disabledServices, s.Disabled...)
|
|
}
|
|
return &osbuild.SystemdStageOptions{
|
|
EnabledServices: enabledServices,
|
|
DisabledServices: disabledServices,
|
|
DefaultTarget: target,
|
|
}
|
|
}
|
|
|
|
func (r *rhel81ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
|
|
options := osbuild.FSTabStageOptions{}
|
|
options.AddFilesystem("0bd700f8-090f-4556-b797-b340297ea1bd", "xfs", "/", "defaults", 0, 0)
|
|
if uefi {
|
|
options.AddFilesystem("46BB-8120", "vfat", "/boot/efi", "umask=0077,shortname=winnt", 0, 2)
|
|
}
|
|
return &options
|
|
}
|
|
|
|
func (r *rhel81ImageType) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
|
|
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
|
|
|
|
var uefiOptions *osbuild.GRUB2UEFI
|
|
if uefi {
|
|
uefiOptions = &osbuild.GRUB2UEFI{
|
|
Vendor: "redhat",
|
|
}
|
|
}
|
|
|
|
return &osbuild.GRUB2StageOptions{
|
|
RootFilesystemUUID: id,
|
|
KernelOptions: kernelOptions,
|
|
Legacy: !uefi,
|
|
UEFI: uefiOptions,
|
|
}
|
|
}
|
|
|
|
func (r *rhel81ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
|
|
return &osbuild.SELinuxStageOptions{
|
|
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
|
|
}
|
|
}
|
|
|
|
func (r *RHEL81) qemuAssembler(format string, filename string, uefi bool, size uint64) *osbuild.Assembler {
|
|
var options osbuild.QEMUAssemblerOptions
|
|
if uefi {
|
|
fstype := uuid.MustParse("C12A7328-F81F-11D2-BA4B-00A0C93EC93B")
|
|
options = osbuild.QEMUAssemblerOptions{
|
|
Format: format,
|
|
Filename: filename,
|
|
Size: size,
|
|
PTUUID: "8DFDFF87-C96E-EA48-A3A6-9408F1F6B1EF",
|
|
PTType: "gpt",
|
|
Partitions: []osbuild.QEMUPartition{
|
|
{
|
|
Start: 2048,
|
|
Size: 972800,
|
|
Type: &fstype,
|
|
Filesystem: osbuild.QEMUFilesystem{
|
|
Type: "vfat",
|
|
UUID: "46BB-8120",
|
|
Label: "EFI System Partition",
|
|
Mountpoint: "/boot/efi",
|
|
},
|
|
},
|
|
{
|
|
Start: 976896,
|
|
Filesystem: osbuild.QEMUFilesystem{
|
|
Type: "xfs",
|
|
UUID: "0bd700f8-090f-4556-b797-b340297ea1bd",
|
|
Mountpoint: "/",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
} else {
|
|
options = osbuild.QEMUAssemblerOptions{
|
|
Format: format,
|
|
Filename: filename,
|
|
Size: size,
|
|
PTUUID: "0x14fc63d2",
|
|
PTType: "mbr",
|
|
Partitions: []osbuild.QEMUPartition{
|
|
{
|
|
Start: 2048,
|
|
Bootable: true,
|
|
Filesystem: osbuild.QEMUFilesystem{
|
|
Type: "xfs",
|
|
UUID: "0bd700f8-090f-4556-b797-b340297ea1bd",
|
|
Mountpoint: "/",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
return osbuild.NewQEMUAssembler(&options)
|
|
}
|
|
|
|
func (r *RHEL81) tarAssembler(filename, compression string) *osbuild.Assembler {
|
|
return osbuild.NewTarAssembler(
|
|
&osbuild.TarAssemblerOptions{
|
|
Filename: filename,
|
|
Compression: compression,
|
|
})
|
|
}
|
|
|
|
func (r *RHEL81) rawFSAssembler(filename string, size uint64) *osbuild.Assembler {
|
|
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
|
|
return osbuild.NewRawFSAssembler(
|
|
&osbuild.RawFSAssemblerOptions{
|
|
Filename: filename,
|
|
RootFilesystemUUID: id,
|
|
Size: size,
|
|
FilesystemType: "xfs",
|
|
})
|
|
}
|