RHEL-90: add gce image type
Add the `gce` image type intended for Google Compute Engine. The image is BYOS - bring your own subscription and requires registering in order to access Red Hat content. Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
parent
ea3e6f072e
commit
5d27b7c784
16 changed files with 24367 additions and 1 deletions
|
|
@ -1315,6 +1315,146 @@ func newDistro(distroName string) distro.Distro {
|
|||
basePartitionTables: defaultBasePartitionTables,
|
||||
}
|
||||
|
||||
defaultGceImageConfig := &distro.ImageConfig{
|
||||
Timezone: "UTC",
|
||||
TimeSynchronization: &osbuild.ChronyStageOptions{
|
||||
Timeservers: []string{"metadata.google.internal"},
|
||||
},
|
||||
Firewall: &osbuild.FirewallStageOptions{
|
||||
DefaultZone: "trusted",
|
||||
},
|
||||
EnabledServices: []string{
|
||||
"sshd",
|
||||
"rngd",
|
||||
"dnf-automatic.timer",
|
||||
},
|
||||
DisabledServices: []string{
|
||||
"sshd-keygen@",
|
||||
"reboot.target",
|
||||
},
|
||||
DefaultTarget: "multi-user.target",
|
||||
Locale: "en_US.UTF-8",
|
||||
Keyboard: &osbuild.KeymapStageOptions{
|
||||
Keymap: "us",
|
||||
},
|
||||
DNFConfig: []*osbuild.DNFConfigStageOptions{
|
||||
{
|
||||
Config: &osbuild.DNFConfig{
|
||||
Main: &osbuild.DNFConfigMain{
|
||||
IPResolve: "4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DNFAutomaticConfig: &osbuild.DNFAutomaticConfigStageOptions{
|
||||
Config: &osbuild.DNFAutomaticConfig{
|
||||
Commands: &osbuild.DNFAutomaticConfigCommands{
|
||||
ApplyUpdates: common.BoolToPtr(true),
|
||||
UpgradeType: osbuild.DNFAutomaticUpgradeTypeSecurity,
|
||||
},
|
||||
},
|
||||
},
|
||||
YUMRepos: []*osbuild.YumReposStageOptions{
|
||||
{
|
||||
Filename: "google-cloud.repo",
|
||||
Repos: []osbuild.YumRepository{
|
||||
{
|
||||
Id: "google-compute-engine",
|
||||
Name: "Google Compute Engine",
|
||||
BaseURL: []string{"https://packages.cloud.google.com/yum/repos/google-compute-engine-el9-x86_64-stable"},
|
||||
Enabled: common.BoolToPtr(true),
|
||||
GPGCheck: common.BoolToPtr(true),
|
||||
RepoGPGCheck: common.BoolToPtr(false),
|
||||
GPGKey: []string{
|
||||
"https://packages.cloud.google.com/yum/doc/yum-key.gpg",
|
||||
"https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg",
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: "google-cloud-sdk",
|
||||
Name: "Google Cloud SDK",
|
||||
BaseURL: []string{"https://packages.cloud.google.com/yum/repos/cloud-sdk-el9-x86_64"},
|
||||
Enabled: common.BoolToPtr(true),
|
||||
GPGCheck: common.BoolToPtr(true),
|
||||
RepoGPGCheck: common.BoolToPtr(false),
|
||||
GPGKey: []string{
|
||||
"https://packages.cloud.google.com/yum/doc/yum-key.gpg",
|
||||
"https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RHSMConfig: map[distro.RHSMSubscriptionStatus]*osbuild.RHSMStageOptions{
|
||||
distro.RHSMConfigNoSubscription: {
|
||||
SubMan: &osbuild.RHSMStageOptionsSubMan{
|
||||
Rhsmcertd: &osbuild.SubManConfigRHSMCERTDSection{
|
||||
AutoRegistration: common.BoolToPtr(true),
|
||||
},
|
||||
// Don't disable RHSM redhat.repo management on the GCE
|
||||
// image, which is BYOS and does not use RHUI for content.
|
||||
// Otherwise subscribing the system manually after booting
|
||||
// it would result in empty redhat.repo. Without RHUI, such
|
||||
// system would have no way to get Red Hat content, but
|
||||
// enable the repo management manually, which would be very
|
||||
// confusing.
|
||||
},
|
||||
},
|
||||
distro.RHSMConfigWithSubscription: {
|
||||
SubMan: &osbuild.RHSMStageOptionsSubMan{
|
||||
Rhsmcertd: &osbuild.SubManConfigRHSMCERTDSection{
|
||||
AutoRegistration: common.BoolToPtr(true),
|
||||
},
|
||||
// do not disable the redhat.repo management if the user
|
||||
// explicitly request the system to be subscribed
|
||||
},
|
||||
},
|
||||
},
|
||||
SshdConfig: &osbuild.SshdConfigStageOptions{
|
||||
Config: osbuild.SshdConfigConfig{
|
||||
PasswordAuthentication: common.BoolToPtr(false),
|
||||
ClientAliveInterval: common.IntToPtr(420),
|
||||
PermitRootLogin: osbuild.PermitRootLoginValueNo,
|
||||
},
|
||||
},
|
||||
Sysconfig: []*osbuild.SysconfigStageOptions{
|
||||
{
|
||||
Kernel: &osbuild.SysconfigKernelOptions{
|
||||
DefaultKernel: "kernel-core",
|
||||
UpdateDefault: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Modprobe: []*osbuild.ModprobeStageOptions{
|
||||
{
|
||||
Filename: "blacklist-floppy.conf",
|
||||
Commands: osbuild.ModprobeConfigCmdList{
|
||||
osbuild.NewModprobeConfigCmdBlacklist("floppy"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
gceImgType := imageType{
|
||||
name: "gce",
|
||||
filename: "image.tar.gz",
|
||||
mimeType: "application/gzip",
|
||||
packageSets: map[string]packageSetFunc{
|
||||
buildPkgsKey: distroBuildPackageSet,
|
||||
osPkgsKey: gcePackageSet,
|
||||
},
|
||||
defaultImageConfig: defaultGceImageConfig,
|
||||
kernelOptions: "net.ifnames=0 biosdevname=0 scsi_mod.use_blk_mq=Y console=ttyS0,38400n8d",
|
||||
bootable: true,
|
||||
bootType: distro.UEFIBootType,
|
||||
defaultSize: 20 * GigaByte,
|
||||
pipelines: gcePipelines,
|
||||
buildPipelines: []string{"build"},
|
||||
payloadPipelines: []string{"os", "image", "archive"},
|
||||
exports: []string{"archive"},
|
||||
basePartitionTables: defaultBasePartitionTables,
|
||||
}
|
||||
|
||||
tarImgType := imageType{
|
||||
name: "tar",
|
||||
filename: "root.tar.xz",
|
||||
|
|
@ -1354,7 +1494,7 @@ func newDistro(distroName string) distro.Distro {
|
|||
ociImgType := qcow2ImgType
|
||||
ociImgType.name = "oci"
|
||||
|
||||
x86_64.addImageTypes(qcow2ImgType, vhdImgType, vmdkImgType, openstackImgType, amiImgTypeX86_64, tarImgType, imageInstaller, edgeCommitImgType, edgeInstallerImgType, edgeOCIImgType, edgeRawImgType, edgeSimplifiedInstallerImgType, ociImgType)
|
||||
x86_64.addImageTypes(qcow2ImgType, vhdImgType, vmdkImgType, openstackImgType, amiImgTypeX86_64, tarImgType, imageInstaller, edgeCommitImgType, edgeInstallerImgType, edgeOCIImgType, edgeRawImgType, edgeSimplifiedInstallerImgType, ociImgType, gceImgType)
|
||||
aarch64.addImageTypes(qcow2ImgType, openstackImgType, amiImgTypeAarch64, tarImgType, imageInstaller, edgeCommitImgType, edgeInstallerImgType, edgeOCIImgType, edgeRawImgType, edgeSimplifiedInstallerImgType)
|
||||
ppc64le.addImageTypes(qcow2ImgType, tarImgType)
|
||||
s390x.addImageTypes(qcow2ImgType, tarImgType)
|
||||
|
|
|
|||
|
|
@ -171,6 +171,14 @@ func TestFilenameFromType(t *testing.T) {
|
|||
mimeType: "application/x-iso9660-image",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gce",
|
||||
args: args{"gce"},
|
||||
want: wantResult{
|
||||
filename: "image.tar.gz",
|
||||
mimeType: "application/gzip",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid-output-type",
|
||||
args: args{"foobar"},
|
||||
|
|
@ -273,6 +281,7 @@ func TestImageType_Name(t *testing.T) {
|
|||
"edge-commit",
|
||||
"edge-container",
|
||||
"edge-installer",
|
||||
"gce",
|
||||
"tar",
|
||||
"image-installer",
|
||||
},
|
||||
|
|
@ -462,6 +471,7 @@ func TestArchitecture_ListImageTypes(t *testing.T) {
|
|||
"edge-installer",
|
||||
"edge-raw-image",
|
||||
"edge-simplified-installer",
|
||||
"gce",
|
||||
"tar",
|
||||
"image-installer",
|
||||
"oci",
|
||||
|
|
|
|||
|
|
@ -705,6 +705,88 @@ func rhelEc2SapPackageSet(t *imageType) rpmmd.PackageSet {
|
|||
return ec2SapPackageSet
|
||||
}
|
||||
|
||||
// common GCE image
|
||||
func gceCommonPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
ps := rpmmd.PackageSet{
|
||||
Include: []string{
|
||||
"langpacks-en", // not in Google's KS
|
||||
"acpid",
|
||||
"dhcp-client",
|
||||
"dnf-automatic",
|
||||
"net-tools",
|
||||
//"openssh-server", included in core
|
||||
"python3",
|
||||
"rng-tools",
|
||||
"tar",
|
||||
"vim",
|
||||
|
||||
// GCE guest tools
|
||||
"google-compute-engine",
|
||||
"google-osconfig-agent",
|
||||
"gce-disk-expand",
|
||||
// GCP SDK
|
||||
"google-cloud-sdk",
|
||||
|
||||
// Not explicitly included in GCP kickstart, but present on the image
|
||||
// for time synchronization
|
||||
"chrony",
|
||||
"timedatex",
|
||||
// Detected Platform requirements by Anaconda
|
||||
"qemu-guest-agent",
|
||||
// EFI
|
||||
"grub2-tools-efi",
|
||||
"firewalld", // not pulled in any more as on RHEL-8
|
||||
},
|
||||
Exclude: []string{
|
||||
"alsa-utils",
|
||||
"b43-fwcutter",
|
||||
"dmraid",
|
||||
"eject",
|
||||
"gpm",
|
||||
"irqbalance",
|
||||
"microcode_ctl",
|
||||
"smartmontools",
|
||||
"aic94xx-firmware",
|
||||
"atmel-firmware",
|
||||
"b43-openfwwf",
|
||||
"bfa-firmware",
|
||||
"ipw2100-firmware",
|
||||
"ipw2200-firmware",
|
||||
"ivtv-firmware",
|
||||
"iwl100-firmware",
|
||||
"iwl1000-firmware",
|
||||
"iwl3945-firmware",
|
||||
"iwl4965-firmware",
|
||||
"iwl5000-firmware",
|
||||
"iwl5150-firmware",
|
||||
"iwl6000-firmware",
|
||||
"iwl6000g2a-firmware",
|
||||
"iwl6050-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",
|
||||
},
|
||||
}.Append(bootPackageSet(t)).Append(coreOsCommonPackageSet(t)).Append(distroSpecificPackageSet(t))
|
||||
|
||||
// Some excluded packages are part of the @core group package set returned
|
||||
// by coreOsCommonPackageSet(). Ensure that the conflicting packages are
|
||||
// returned from the list of `Include` packages.
|
||||
return ps.ResolveConflictsExclude()
|
||||
}
|
||||
|
||||
// GCE BYOS image
|
||||
func gcePackageSet(t *imageType) rpmmd.PackageSet {
|
||||
return gceCommonPackageSet(t)
|
||||
}
|
||||
|
||||
// edge commit OS package set
|
||||
func edgeCommitPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
ps := rpmmd.PackageSet{
|
||||
|
|
|
|||
|
|
@ -170,6 +170,40 @@ func rhelEc2Pipelines(t *imageType, customizations *blueprint.Customizations, op
|
|||
return pipelines, nil
|
||||
}
|
||||
|
||||
func gcePipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
pipelines := make([]osbuild.Pipeline, 0)
|
||||
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner))
|
||||
|
||||
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, partitionTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pipelines = append(pipelines, *treePipeline)
|
||||
|
||||
diskfile := "disk.raw"
|
||||
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packageSetSpecs[blueprintPkgsKey], customizations.GetKernel().Name)
|
||||
imagePipeline := liveImagePipeline(treePipeline.Name, diskfile, partitionTable, t.arch, kernelVer)
|
||||
pipelines = append(pipelines, *imagePipeline)
|
||||
|
||||
archivePipeline := tarArchivePipeline("archive", imagePipeline.Name, &osbuild.TarStageOptions{
|
||||
Filename: t.Filename(),
|
||||
Format: osbuild.TarArchiveFormatOldgnu,
|
||||
RootNode: osbuild.TarRootNodeOmit,
|
||||
// import of the image to GCP fails in case the options below are enabled, which is the default
|
||||
ACLs: common.BoolToPtr(false),
|
||||
SELinux: common.BoolToPtr(false),
|
||||
Xattrs: common.BoolToPtr(false),
|
||||
})
|
||||
pipelines = append(pipelines, *archivePipeline)
|
||||
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
func tarPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
pipelines := make([]osbuild.Pipeline, 0)
|
||||
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner))
|
||||
|
|
|
|||
|
|
@ -121,6 +121,25 @@ func (ps PackageSet) Append(other PackageSet) PackageSet {
|
|||
return ps
|
||||
}
|
||||
|
||||
// ResolveConflictsExclude resolves conflicting Include and Exclude package lists
|
||||
// content by deleting packages listed as Excluded from the Include list.
|
||||
func (ps PackageSet) ResolveConflictsExclude() PackageSet {
|
||||
excluded := map[string]struct{}{}
|
||||
for _, pkg := range ps.Exclude {
|
||||
excluded[pkg] = struct{}{}
|
||||
}
|
||||
|
||||
newInclude := []string{}
|
||||
for _, pkg := range ps.Include {
|
||||
_, found := excluded[pkg]
|
||||
if !found {
|
||||
newInclude = append(newInclude, pkg)
|
||||
}
|
||||
}
|
||||
ps.Include = newInclude
|
||||
return ps
|
||||
}
|
||||
|
||||
// TODO: the public API of this package should not be reused for serialization.
|
||||
type PackageSpec struct {
|
||||
Name string `json:"name"`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package rpmmdtests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
|
@ -143,3 +144,48 @@ func Test_LoadAllRepositories(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageSetResolveConflictExclude(t *testing.T) {
|
||||
tests := []struct {
|
||||
got rpmmd.PackageSet
|
||||
want rpmmd.PackageSet
|
||||
}{
|
||||
{
|
||||
got: rpmmd.PackageSet{
|
||||
Include: []string{"kernel", "microcode_ctl", "dnf"},
|
||||
Exclude: []string{"microcode_ctl"},
|
||||
},
|
||||
want: rpmmd.PackageSet{
|
||||
Include: []string{"kernel", "dnf"},
|
||||
Exclude: []string{"microcode_ctl"},
|
||||
},
|
||||
},
|
||||
{
|
||||
got: rpmmd.PackageSet{
|
||||
Include: []string{"kernel", "dnf"},
|
||||
Exclude: []string{"microcode_ctl"},
|
||||
},
|
||||
want: rpmmd.PackageSet{
|
||||
Include: []string{"kernel", "dnf"},
|
||||
Exclude: []string{"microcode_ctl"},
|
||||
},
|
||||
},
|
||||
{
|
||||
got: rpmmd.PackageSet{
|
||||
Include: []string{"kernel", "microcode_ctl", "dnf"},
|
||||
Exclude: []string{},
|
||||
},
|
||||
want: rpmmd.PackageSet{
|
||||
Include: []string{"kernel", "microcode_ctl", "dnf"},
|
||||
Exclude: []string{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for idx, tt := range tests {
|
||||
t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) {
|
||||
if !reflect.DeepEqual(tt.got.ResolveConflictsExclude(), tt.want) {
|
||||
t.Errorf("ResolveConflictExclude() returned unexpected result got: %#v\n want: %#v", tt.got.ResolveConflictsExclude(), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,6 +367,7 @@ var imageTypeCompatMapping = map[string]string{
|
|||
"ec2": "ec2",
|
||||
"ec2-ha": "ec2-ha",
|
||||
"oci": "oci",
|
||||
"gce": "GCP",
|
||||
}
|
||||
|
||||
func imageTypeToCompatString(imgType distro.ImageType) string {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
13469
test/data/manifests/centos_9-x86_64-gce-boot.json
Normal file
13469
test/data/manifests/centos_9-x86_64-gce-boot.json
Normal file
File diff suppressed because one or more lines are too long
10468
test/data/manifests/rhel_90-x86_64-gce-boot.json
Normal file
10468
test/data/manifests/rhel_90-x86_64-gce-boot.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -232,6 +232,7 @@
|
|||
"ec2",
|
||||
"ec2-ha",
|
||||
"ec2-sap",
|
||||
"gce",
|
||||
"edge-commit",
|
||||
"edge-container",
|
||||
"edge-installer",
|
||||
|
|
@ -269,6 +270,7 @@
|
|||
"centos-9": {
|
||||
"x86_64": [
|
||||
"ami",
|
||||
"gce",
|
||||
"openstack",
|
||||
"tar",
|
||||
"qcow2",
|
||||
|
|
|
|||
|
|
@ -61,6 +61,17 @@
|
|||
},
|
||||
"overrides": {}
|
||||
},
|
||||
"gce": {
|
||||
"compose-request": {
|
||||
"distro": "",
|
||||
"arch": "",
|
||||
"image-type": "gce",
|
||||
"repositories": [],
|
||||
"filename": "image.tar.gz",
|
||||
"blueprint": {}
|
||||
},
|
||||
"overrides": {}
|
||||
},
|
||||
"edge-commit": {
|
||||
"compose-request": {
|
||||
"distro": "",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue