diff --git a/cmd/openshift-install/testdata/agent/image/manifests/default_manifests.txt b/cmd/openshift-install/testdata/agent/image/manifests/default_manifests.txt index 48b72a429f0..98c9b4e188d 100644 --- a/cmd/openshift-install/testdata/agent/image/manifests/default_manifests.txt +++ b/cmd/openshift-install/testdata/agent/image/manifests/default_manifests.txt @@ -111,6 +111,7 @@ spec: clusterRef: name: ostest namespace: cluster0 + cpuArchitecture: x86_64 ipxeScriptType: "" nmStateConfigLabelSelector: matchLabels: diff --git a/pkg/asset/agent/image/baseiso.go b/pkg/asset/agent/image/baseiso.go index 66e5df7a3ec..702031b532f 100644 --- a/pkg/asset/agent/image/baseiso.go +++ b/pkg/asset/agent/image/baseiso.go @@ -7,6 +7,7 @@ import ( "os/exec" "time" + "github.com/coreos/stream-metadata-go/arch" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -16,6 +17,7 @@ import ( "github.com/openshift/installer/pkg/asset/agent/manifests" "github.com/openshift/installer/pkg/asset/agent/mirror" "github.com/openshift/installer/pkg/rhcos" + "github.com/openshift/installer/pkg/types" ) // BaseIso generates the base ISO file for the image @@ -23,11 +25,6 @@ type BaseIso struct { File *asset.File } -const ( - // TODO - add support for other architectures - archName = "x86_64" -) - var ( baseIsoFilename = "" ) @@ -40,7 +37,7 @@ func (i *BaseIso) Name() string { } // getIsoFile is a pluggable function that gets the base ISO file -type getIsoFile func() (string, error) +type getIsoFile func(archName string) (string, error) type getIso struct { getter getIsoFile @@ -54,8 +51,7 @@ func newGetIso(getter getIsoFile) *getIso { var GetIsoPluggable = downloadIso // Download the ISO using the URL in rhcos.json -func downloadIso() (string, error) { - +func downloadIso(archName string) (string, error) { ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second) defer cancel() @@ -64,9 +60,6 @@ func downloadIso() (string, error) { if err != nil { return "", err } - - // Defaults to using the x86_64 baremetal ISO for all platforms - // archName := arch.RpmArch(string(config.ControlPlane.Architecture)) streamArch, err := st.GetArchitecture(archName) if err != nil { return "", err @@ -107,10 +100,17 @@ func (i *BaseIso) Generate(dependencies asset.Parents) error { // use the GetIso function to get the BaseIso from the release payload agentManifests := &manifests.AgentManifests{} dependencies.Get(agentManifests) - var baseIsoFileName string var err error + + // Default iso archName to x86_64. + archName := arch.RpmArch(types.ArchitectureAMD64) + if agentManifests.ClusterImageSet != nil { + // If specified, use InfraEnv.Spec.CpuArchitecture for iso archName + if agentManifests.InfraEnv.Spec.CpuArchitecture != "" { + archName = agentManifests.InfraEnv.Spec.CpuArchitecture + } releaseImage := agentManifests.ClusterImageSet.Spec.ReleaseImage pullSecret := agentManifests.GetPullSecretData() registriesConf := &mirror.RegistriesConf{} @@ -135,7 +135,7 @@ func (i *BaseIso) Generate(dependencies asset.Parents) error { logrus.Info("Downloading base ISO") isoGetter := newGetIso(GetIsoPluggable) - baseIsoFileName, err2 := isoGetter.getter() + baseIsoFileName, err2 := isoGetter.getter(archName) if err2 == nil { logrus.Debugf("Using base ISO image %s", baseIsoFileName) i.File = &asset.File{Filename: baseIsoFileName} diff --git a/pkg/asset/agent/image/baseiso_test.go b/pkg/asset/agent/image/baseiso_test.go index c86012ac785..26a4c342b99 100644 --- a/pkg/asset/agent/image/baseiso_test.go +++ b/pkg/asset/agent/image/baseiso_test.go @@ -12,7 +12,7 @@ import ( func TestInfraBaseIso_Generate(t *testing.T) { - GetIsoPluggable = func() (string, error) { + GetIsoPluggable = func(archName string) (string, error) { return "some-openshift-release.iso", nil } diff --git a/pkg/asset/agent/image/ignition.go b/pkg/asset/agent/image/ignition.go index d659cf5a689..c14e9a42178 100644 --- a/pkg/asset/agent/image/ignition.go +++ b/pkg/asset/agent/image/ignition.go @@ -12,6 +12,7 @@ import ( "github.com/coreos/ignition/v2/config/util" igntypes "github.com/coreos/ignition/v2/config/v3_2/types" + "github.com/coreos/stream-metadata-go/arch" "github.com/google/uuid" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -29,6 +30,7 @@ import ( "github.com/openshift/installer/pkg/asset/password" "github.com/openshift/installer/pkg/asset/tls" "github.com/openshift/installer/pkg/rhcos" + "github.com/openshift/installer/pkg/types" "github.com/openshift/installer/pkg/types/agent" "github.com/openshift/installer/pkg/version" ) @@ -126,8 +128,12 @@ func (a *Ignition) Generate(dependencies asset.Parents) error { logrus.Infof("The rendezvous host IP (node0 IP) is %s", nodeZeroIP) a.RendezvousIP = nodeZeroIP + // Default to x86_64 + archName := arch.RpmArch(types.ArchitectureAMD64) + if infraEnv.Spec.CpuArchitecture != "" { + archName = infraEnv.Spec.CpuArchitecture + } - // TODO: don't hard-code target arch releaseImageList, err := releaseImageList(agentManifests.ClusterImageSet.Spec.ReleaseImage, archName) if err != nil { return err diff --git a/pkg/asset/agent/installconfig.go b/pkg/asset/agent/installconfig.go index 6ac168711bb..cf5f2ea3242 100644 --- a/pkg/asset/agent/installconfig.go +++ b/pkg/asset/agent/installconfig.go @@ -96,8 +96,9 @@ func (a *OptionalInstallConfig) validateSupportedArchs(installConfig *types.Inst switch string(installConfig.ControlPlane.Architecture) { case types.ArchitectureAMD64: + case types.ArchitectureARM64: default: - allErrs = append(allErrs, field.NotSupported(fieldPath, installConfig.ControlPlane.Architecture, []string{types.ArchitectureAMD64})) + allErrs = append(allErrs, field.NotSupported(fieldPath, installConfig.ControlPlane.Architecture, []string{types.ArchitectureAMD64, types.ArchitectureARM64})) } for i, compute := range installConfig.Compute { @@ -105,8 +106,9 @@ func (a *OptionalInstallConfig) validateSupportedArchs(installConfig *types.Inst switch string(compute.Architecture) { case types.ArchitectureAMD64: + case types.ArchitectureARM64: default: - allErrs = append(allErrs, field.NotSupported(fieldPath, compute.Architecture, []string{types.ArchitectureAMD64})) + allErrs = append(allErrs, field.NotSupported(fieldPath, compute.Architecture, []string{types.ArchitectureAMD64, types.ArchitectureARM64})) } } diff --git a/pkg/asset/agent/installconfig_test.go b/pkg/asset/agent/installconfig_test.go index 19912451965..f7fc2744c18 100644 --- a/pkg/asset/agent/installconfig_test.go +++ b/pkg/asset/agent/installconfig_test.go @@ -221,13 +221,13 @@ baseDomain: test-domain networking: networkType: OVNKubernetes compute: - - architecture: arm64 + - architecture: s390x hyperthreading: Enabled name: worker platform: {} replicas: 0 controlPlane: - architecture: arm64 + architecture: s390x hyperthreading: Enabled name: master platform: {} @@ -237,7 +237,7 @@ platform: pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"authorization value\"}}}" `, expectedFound: false, - expectedError: "invalid install-config configuration: [ControlPlane.Architecture: Unsupported value: \"arm64\": supported values: \"amd64\", Compute[0].Architecture: Unsupported value: \"arm64\": supported values: \"amd64\"]", + expectedError: "invalid install-config configuration: [ControlPlane.Architecture: Unsupported value: \"s390x\": supported values: \"amd64\", \"arm64\", Compute[0].Architecture: Unsupported value: \"s390x\": supported values: \"amd64\", \"arm64\"]", }, { name: "valid configuration for none platform for sno", diff --git a/pkg/asset/agent/manifests/infraenv.go b/pkg/asset/agent/manifests/infraenv.go index 1ace1082d82..c8bee6f59f8 100644 --- a/pkg/asset/agent/manifests/infraenv.go +++ b/pkg/asset/agent/manifests/infraenv.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" + "github.com/coreos/stream-metadata-go/arch" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -15,6 +16,7 @@ import ( "github.com/openshift/installer/pkg/asset" "github.com/openshift/installer/pkg/asset/agent" "github.com/openshift/installer/pkg/asset/agent/agentconfig" + "github.com/openshift/installer/pkg/types" ) var ( @@ -70,6 +72,12 @@ func (i *InfraEnv) Generate(dependencies asset.Parents) error { }, }, } + + // Use installConfig.Config.ControlPlane.Architecture to determine cpuarchitecture for infraEnv.Spec.CpuArchiteture. + // installConfig.Config.ControlPlance.Architecture uses go/Debian cpuarchitecture values (amd64, arm64) so we must convert to rpmArch because infraEnv.Spec.CpuArchitecture expects x86_64 or aarch64. + if installConfig.Config.ControlPlane.Architecture != "" { + infraEnv.Spec.CpuArchitecture = arch.RpmArch(string(installConfig.Config.ControlPlane.Architecture)) + } if installConfig.Config.Proxy != nil { infraEnv.Spec.Proxy = getProxy(installConfig) } @@ -116,7 +124,10 @@ func (i *InfraEnv) Load(f asset.FileFetcher) (bool, error) { if err := yaml.UnmarshalStrict(file.Data, config); err != nil { return false, errors.Wrapf(err, "failed to unmarshal %s", infraEnvFilename) } - + // If defined, convert to RpmArch amd64 -> x86_64 or arm64 -> aarch64 + if config.Spec.CpuArchitecture != "" { + config.Spec.CpuArchitecture = arch.RpmArch(config.Spec.CpuArchitecture) + } i.File, i.Config = file, config if err = i.finish(); err != nil { return false, err @@ -131,5 +142,11 @@ func (i *InfraEnv) finish() error { return errors.New("missing configuration or manifest file") } + // Throw an error if CpuArchitecture isn't x86_64, aarch64, or "" + switch i.Config.Spec.CpuArchitecture { + case arch.RpmArch(types.ArchitectureAMD64), arch.RpmArch(types.ArchitectureARM64), "": + default: + return errors.Errorf("Config.Spec.CpuArchitecture %s is not supported ", i.Config.Spec.CpuArchitecture) + } return nil }