From 63e788234dd495e8746e0bb34d8557f61b13dd1f Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Mon, 6 Jan 2020 15:42:33 -0800 Subject: [PATCH 1/8] *: add support for multi-arch rhcos image lookup This adds an architecture parameter to the RHCOS image lookup process and a corresponding field to MachinePool. This is a backward-compatible change, defaulting the architecture to AMD64 if none has been specified. This also enforces that the control plane and compute nodes share an architecture, since we don't support heterogeneous clusters today. (cherry picked from commit 2583ba4dfb6199860ef57055b8d27f5d53026fa4) --- docs/user/customization.md | 2 ++ pkg/asset/installconfig/installconfig_test.go | 6 ++++++ pkg/asset/manifests/operators_test.go | 14 +++++++++----- pkg/asset/rhcos/bootstrap_image.go | 2 +- pkg/asset/rhcos/image.go | 14 ++++++++------ pkg/rhcos/ami.go | 6 ++++-- pkg/rhcos/azure.go | 6 ++++-- pkg/rhcos/builds.go | 16 +++++++++++++--- pkg/rhcos/gcp.go | 6 ++++-- pkg/rhcos/openstack.go | 6 ++++-- pkg/rhcos/qemu.go | 6 ++++-- pkg/types/defaults/machinepools.go | 3 +++ pkg/types/defaults/machinepools_test.go | 1 + pkg/types/machinepools.go | 12 ++++++++++++ pkg/types/validation/installconfig.go | 7 +++++-- pkg/types/validation/installconfig_test.go | 1 + pkg/types/validation/machinepools.go | 15 +++++++++++++++ pkg/types/validation/machinepools_test.go | 1 + 18 files changed, 97 insertions(+), 27 deletions(-) diff --git a/docs/user/customization.md b/docs/user/customization.md index d655684b902..2a9ca6e2ea4 100644 --- a/docs/user/customization.md +++ b/docs/user/customization.md @@ -69,6 +69,8 @@ For example, 10.0.0.0/16 represents IP addresses 10.0.0.0 through 10.0.255.255. The following machine-pool properties are available: +* `architecture` (optional string): Determines the instruction set architecture of the machines in the pool. Currently, heteregeneous clusters are not supported, so all pools must specify the same architecture. + Valid values are `amd64` (the default). * `hyperthreading` (optional string): Determines the mode of hyperthreading that machines in the pool will utilize. Valid values are `Enabled` (the default) and `Disabled`. * `name` (required string): The name of the machine pool. diff --git a/pkg/asset/installconfig/installconfig_test.go b/pkg/asset/installconfig/installconfig_test.go index 5be5ae82dfd..345c9c01ebd 100644 --- a/pkg/asset/installconfig/installconfig_test.go +++ b/pkg/asset/installconfig/installconfig_test.go @@ -81,12 +81,14 @@ func TestInstallConfigGenerate_FillsInDefaults(t *testing.T) { Name: "master", Replicas: pointer.Int64Ptr(3), Hyperthreading: types.HyperthreadingEnabled, + Architecture: types.ArchitectureAMD64, }, Compute: []types.MachinePool{ { Name: "worker", Replicas: pointer.Int64Ptr(3), Hyperthreading: types.HyperthreadingEnabled, + Architecture: types.ArchitectureAMD64, }, }, Platform: types.Platform{ @@ -145,12 +147,14 @@ pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"authorization value\"}}}" Name: "master", Replicas: pointer.Int64Ptr(3), Hyperthreading: types.HyperthreadingEnabled, + Architecture: types.ArchitectureAMD64, }, Compute: []types.MachinePool{ { Name: "worker", Replicas: pointer.Int64Ptr(3), Hyperthreading: types.HyperthreadingEnabled, + Architecture: types.ArchitectureAMD64, }, }, Platform: types.Platform{ @@ -229,12 +233,14 @@ network: Name: "master", Replicas: pointer.Int64Ptr(3), Hyperthreading: types.HyperthreadingEnabled, + Architecture: types.ArchitectureAMD64, }, Compute: []types.MachinePool{ { Name: "worker", Replicas: pointer.Int64Ptr(3), Hyperthreading: types.HyperthreadingEnabled, + Architecture: types.ArchitectureAMD64, }, }, Platform: types.Platform{ diff --git a/pkg/asset/manifests/operators_test.go b/pkg/asset/manifests/operators_test.go index 25cc50b7635..ba7bc3877cd 100644 --- a/pkg/asset/manifests/operators_test.go +++ b/pkg/asset/manifests/operators_test.go @@ -35,13 +35,15 @@ func TestRedactedInstallConfig(t *testing.T) { ServiceNetwork: []ipnet.IPNet{*ipnet.MustParseCIDR("1.2.3.4/5")}, }, ControlPlane: &types.MachinePool{ - Name: "control-plane", - Replicas: pointer.Int64Ptr(3), + Name: "control-plane", + Replicas: pointer.Int64Ptr(3), + Architecture: types.ArchitectureAMD64, }, Compute: []types.MachinePool{ { - Name: "compute", - Replicas: pointer.Int64Ptr(3), + Name: "compute", + Replicas: pointer.Int64Ptr(3), + Architecture: types.ArchitectureAMD64, }, }, Platform: types.Platform{ @@ -59,10 +61,12 @@ func TestRedactedInstallConfig(t *testing.T) { expectedConfig := createInstallConfig() expectedYaml := `baseDomain: test-domain compute: -- name: compute +- architecture: amd64 + name: compute platform: {} replicas: 3 controlPlane: + architecture: amd64 name: control-plane platform: {} replicas: 3 diff --git a/pkg/asset/rhcos/bootstrap_image.go b/pkg/asset/rhcos/bootstrap_image.go index f8c5805fad1..6fde584b5ba 100644 --- a/pkg/asset/rhcos/bootstrap_image.go +++ b/pkg/asset/rhcos/bootstrap_image.go @@ -51,7 +51,7 @@ func (i *BootstrapImage) Generate(p asset.Parents) error { // Baremetal IPI launches a local VM for the bootstrap node // Hence requires the QEMU image to use the libvirt backend - osimage, err = rhcos.QEMU(ctx) + osimage, err = rhcos.QEMU(ctx, config.ControlPlane.Architecture) default: // other platforms use the same image for all nodes osimage, err = osImage(config) diff --git a/pkg/asset/rhcos/image.go b/pkg/asset/rhcos/image.go index 38800024646..5a067f34a79 100644 --- a/pkg/asset/rhcos/image.go +++ b/pkg/asset/rhcos/image.go @@ -62,6 +62,8 @@ func (i *Image) Generate(p asset.Parents) error { } func osImage(config *types.InstallConfig) (string, error) { + arch := config.ControlPlane.Architecture + var osimage string var err error ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second) @@ -72,19 +74,19 @@ func osImage(config *types.InstallConfig) (string, error) { osimage = config.Platform.AWS.AMIID break } - osimage, err = rhcos.AMI(ctx, config.Platform.AWS.Region) + osimage, err = rhcos.AMI(ctx, arch, config.Platform.AWS.Region) case gcp.Name: - osimage, err = rhcos.GCP(ctx) + osimage, err = rhcos.GCP(ctx, arch) case libvirt.Name: - osimage, err = rhcos.QEMU(ctx) + osimage, err = rhcos.QEMU(ctx, arch) case openstack.Name: if oi := config.Platform.OpenStack.ClusterOSImage; oi != "" { osimage = oi break } - osimage, err = rhcos.OpenStack(ctx) + osimage, err = rhcos.OpenStack(ctx, arch) case azure.Name: - osimage, err = rhcos.VHD(ctx) + osimage, err = rhcos.VHD(ctx, arch) case baremetal.Name: // Check for RHCOS image URL override if oi := config.Platform.BareMetal.ClusterOSImage; oi != "" { @@ -95,7 +97,7 @@ func osImage(config *types.InstallConfig) (string, error) { // Note that baremetal IPI currently uses the OpenStack image // because this contains the necessary ironic config drive // ignition support, which isn't enabled in the UPI BM images - osimage, err = rhcos.OpenStack(ctx) + osimage, err = rhcos.OpenStack(ctx, arch) case none.Name, vsphere.Name: default: return "", errors.New("invalid Platform") diff --git a/pkg/rhcos/ami.go b/pkg/rhcos/ami.go index f6d76767b33..625ba9e80ac 100644 --- a/pkg/rhcos/ami.go +++ b/pkg/rhcos/ami.go @@ -4,11 +4,13 @@ import ( "context" "github.com/pkg/errors" + + "github.com/openshift/installer/pkg/types" ) // AMI fetches the HVM AMI ID of the Red Hat Enterprise Linux CoreOS release. -func AMI(ctx context.Context, region string) (string, error) { - meta, err := fetchRHCOSBuild(ctx) +func AMI(ctx context.Context, arch types.Architecture, region string) (string, error) { + meta, err := fetchRHCOSBuild(ctx, arch) if err != nil { return "", errors.Wrap(err, "failed to fetch RHCOS metadata") } diff --git a/pkg/rhcos/azure.go b/pkg/rhcos/azure.go index 63176489d71..14e8fc30bb2 100644 --- a/pkg/rhcos/azure.go +++ b/pkg/rhcos/azure.go @@ -4,11 +4,13 @@ import ( "context" "github.com/pkg/errors" + + "github.com/openshift/installer/pkg/types" ) // VHD fetches the URL of the public Azure storage bucket containing the RHCOS image -func VHD(ctx context.Context) (string, error) { - meta, err := fetchRHCOSBuild(ctx) +func VHD(ctx context.Context, arch types.Architecture) (string, error) { + meta, err := fetchRHCOSBuild(ctx, arch) if err != nil { return "", errors.Wrap(err, "failed to fetch RHCOS metadata") } diff --git a/pkg/rhcos/builds.go b/pkg/rhcos/builds.go index 4bf6b30038b..eaaf2a2558b 100644 --- a/pkg/rhcos/builds.go +++ b/pkg/rhcos/builds.go @@ -3,10 +3,18 @@ package rhcos import ( "context" "encoding/json" + "fmt" "io/ioutil" + "os" "github.com/openshift/installer/data" "github.com/pkg/errors" + + "github.com/openshift/installer/pkg/types" +) + +var ( + errInvalidArch = fmt.Errorf("no build metadata for given architecture") ) type metadata struct { @@ -37,15 +45,17 @@ type metadata struct { OSTreeVersion string `json:"ostree-version"` } -func fetchRHCOSBuild(ctx context.Context) (*metadata, error) { - file, err := data.Assets.Open("rhcos.json") +func fetchRHCOSBuild(ctx context.Context, arch types.Architecture) (*metadata, error) { + file, err := data.Assets.Open(fmt.Sprintf("rhcos-%s.json", arch)) if err != nil { return nil, err } defer file.Close() body, err := ioutil.ReadAll(file) - if err != nil { + if os.IsNotExist(err) { + return nil, errInvalidArch + } else if err != nil { return nil, err } diff --git a/pkg/rhcos/gcp.go b/pkg/rhcos/gcp.go index 782ceba15a2..e1dc4df66cb 100644 --- a/pkg/rhcos/gcp.go +++ b/pkg/rhcos/gcp.go @@ -4,11 +4,13 @@ import ( "context" "github.com/pkg/errors" + + "github.com/openshift/installer/pkg/types" ) // GCP fetches the URL of the public GCP storage bucket containing the RHCOS image -func GCP(ctx context.Context) (string, error) { - meta, err := fetchRHCOSBuild(ctx) +func GCP(ctx context.Context, arch types.Architecture) (string, error) { + meta, err := fetchRHCOSBuild(ctx, arch) if err != nil { return "", errors.Wrap(err, "failed to fetch RHCOS metadata") } diff --git a/pkg/rhcos/openstack.go b/pkg/rhcos/openstack.go index d5485ef40bf..7f25ac7d815 100644 --- a/pkg/rhcos/openstack.go +++ b/pkg/rhcos/openstack.go @@ -5,12 +5,14 @@ import ( "net/url" "github.com/pkg/errors" + + "github.com/openshift/installer/pkg/types" ) // OpenStack fetches the URL of the Red Hat Enterprise Linux CoreOS release, // for the openstack platform -func OpenStack(ctx context.Context) (string, error) { - meta, err := fetchRHCOSBuild(ctx) +func OpenStack(ctx context.Context, arch types.Architecture) (string, error) { + meta, err := fetchRHCOSBuild(ctx, arch) if err != nil { return "", errors.Wrap(err, "failed to fetch RHCOS metadata") } diff --git a/pkg/rhcos/qemu.go b/pkg/rhcos/qemu.go index 5ada808d48c..f0c0026cc80 100644 --- a/pkg/rhcos/qemu.go +++ b/pkg/rhcos/qemu.go @@ -5,11 +5,13 @@ import ( "net/url" "github.com/pkg/errors" + + "github.com/openshift/installer/pkg/types" ) // QEMU fetches the URL of the Red Hat Enterprise Linux CoreOS release. -func QEMU(ctx context.Context) (string, error) { - meta, err := fetchRHCOSBuild(ctx) +func QEMU(ctx context.Context, arch types.Architecture) (string, error) { + meta, err := fetchRHCOSBuild(ctx, arch) if err != nil { return "", errors.Wrap(err, "failed to fetch RHCOS metadata") } diff --git a/pkg/types/defaults/machinepools.go b/pkg/types/defaults/machinepools.go index e9810c2e9c5..9573e7950b9 100644 --- a/pkg/types/defaults/machinepools.go +++ b/pkg/types/defaults/machinepools.go @@ -17,4 +17,7 @@ func SetMachinePoolDefaults(p *types.MachinePool, platform string) { if p.Hyperthreading == "" { p.Hyperthreading = types.HyperthreadingEnabled } + if p.Architecture == "" { + p.Architecture = types.ArchitectureAMD64 + } } diff --git a/pkg/types/defaults/machinepools_test.go b/pkg/types/defaults/machinepools_test.go index 4746ca72df5..9eb1e43fd16 100644 --- a/pkg/types/defaults/machinepools_test.go +++ b/pkg/types/defaults/machinepools_test.go @@ -14,6 +14,7 @@ func defaultMachinePool(name string) *types.MachinePool { Name: name, Replicas: pointer.Int64Ptr(3), Hyperthreading: types.HyperthreadingEnabled, + Architecture: types.ArchitectureAMD64, } } diff --git a/pkg/types/machinepools.go b/pkg/types/machinepools.go index 16665bdcdf5..331f98792ab 100644 --- a/pkg/types/machinepools.go +++ b/pkg/types/machinepools.go @@ -20,6 +20,14 @@ const ( HyperthreadingDisabled HyperthreadingMode = "Disabled" ) +// Architecture is the instruction set architecture for the machines in a pool. +type Architecture string + +const ( + // ArchitectureAMD64 indicates AMD64 (x86_64). + ArchitectureAMD64 = "amd64" +) + // MachinePool is a pool of machines to be installed. type MachinePool struct { // Name is the name of the machine pool. @@ -38,6 +46,10 @@ type MachinePool struct { // +optional // Default is for hyperthreading to be enabled. Hyperthreading HyperthreadingMode `json:"hyperthreading,omitempty"` + + // Architecture is the instruction set architecture of the machine pool. + // Defaults to amd64. + Architecture Architecture `json:"architecture,omitempty"` } // MachinePoolPlatform is the platform-specific configuration for a machine diff --git a/pkg/types/validation/installconfig.go b/pkg/types/validation/installconfig.go index 5d6509d9b7b..b1c52c6ef09 100644 --- a/pkg/types/validation/installconfig.go +++ b/pkg/types/validation/installconfig.go @@ -91,7 +91,7 @@ func ValidateInstallConfig(c *types.InstallConfig, openStackValidValuesFetcher o } else { allErrs = append(allErrs, field.Required(field.NewPath("controlPlane"), "controlPlane is required")) } - allErrs = append(allErrs, validateCompute(&c.Platform, c.Compute, field.NewPath("compute"))...) + allErrs = append(allErrs, validateCompute(&c.Platform, c.ControlPlane, c.Compute, field.NewPath("compute"))...) if err := validate.ImagePullSecret(c.PullSecret); err != nil { allErrs = append(allErrs, field.Invalid(field.NewPath("pullSecret"), c.PullSecret, err.Error())) } @@ -317,7 +317,7 @@ func validateControlPlane(platform *types.Platform, pool *types.MachinePool, fld return allErrs } -func validateCompute(platform *types.Platform, pools []types.MachinePool, fldPath *field.Path) field.ErrorList { +func validateCompute(platform *types.Platform, control *types.MachinePool, pools []types.MachinePool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} poolNames := map[string]bool{} for i, p := range pools { @@ -329,6 +329,9 @@ func validateCompute(platform *types.Platform, pools []types.MachinePool, fldPat allErrs = append(allErrs, field.Duplicate(poolFldPath.Child("name"), p.Name)) } poolNames[p.Name] = true + if control != nil && control.Architecture != p.Architecture { + allErrs = append(allErrs, field.Invalid(poolFldPath.Child("architecture"), p.Architecture, "heteregeneous multi-arch is not supported; compute pool architecture must match control plane")) + } allErrs = append(allErrs, ValidateMachinePool(platform, &p, poolFldPath)...) } return allErrs diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index 2d37f1d1555..f904fcc86c4 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -884,6 +884,7 @@ func TestValidateInstallConfig(t *testing.T) { }(), expectedError: `Invalid value: "DualStack": dual-stack IPv4/IPv6 is not supported for this platform, specify only one type of address`, }, + // TODO(crawford): add a test to validate that homogeneous clusters are enforced once an additional architecture is added } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/types/validation/machinepools.go b/pkg/types/validation/machinepools.go index 33867a09c14..6c9ed452458 100644 --- a/pkg/types/validation/machinepools.go +++ b/pkg/types/validation/machinepools.go @@ -31,6 +31,18 @@ var ( } return v }() + + validArchitectures = map[types.Architecture]bool{ + types.ArchitectureAMD64: true, + } + + validArchitectureValues = func() []string { + v := make([]string, 0, len(validArchitectures)) + for m := range validArchitectures { + v = append(v, string(m)) + } + return v + }() ) // ValidateMachinePool checks that the specified machine pool is valid. @@ -46,6 +58,9 @@ func ValidateMachinePool(platform *types.Platform, p *types.MachinePool, fldPath if !validHyperthreadingModes[p.Hyperthreading] { allErrs = append(allErrs, field.NotSupported(fldPath.Child("hyperthreading"), p.Hyperthreading, validHyperthreadingModeValues)) } + if !validArchitectures[p.Architecture] { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("architecture"), p.Architecture, validArchitectureValues)) + } allErrs = append(allErrs, validateMachinePoolPlatform(platform, &p.Platform, fldPath.Child("platform"))...) return allErrs } diff --git a/pkg/types/validation/machinepools_test.go b/pkg/types/validation/machinepools_test.go index 44517d78c01..0aaf503a875 100644 --- a/pkg/types/validation/machinepools_test.go +++ b/pkg/types/validation/machinepools_test.go @@ -19,6 +19,7 @@ func validMachinePool(name string) *types.MachinePool { Name: name, Replicas: pointer.Int64Ptr(1), Hyperthreading: types.HyperthreadingDisabled, + Architecture: types.ArchitectureAMD64, } } From be27b9470b92cab498ce8e3dd2b1cbf4e33d9f24 Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Mon, 6 Jan 2020 15:39:38 -0800 Subject: [PATCH 2/8] hack: improve portability of bootimage script Not everyone has python3 installed into /usr/bin/. (cherry picked from commit 8428471c622f8372acc9068cc2a4b7a59d47214d) --- hack/update-rhcos-bootimage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/update-rhcos-bootimage.py b/hack/update-rhcos-bootimage.py index 97e84c1845d..604bbc399b5 100755 --- a/hack/update-rhcos-bootimage.py +++ b/hack/update-rhcos-bootimage.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # Usage: ./hack/update-rhcos-bootimage.py https://releases-art-rhcos.svc.ci.openshift.org/storage/releases/ootpa/410.8.20190401.0/meta.json import codecs,os,sys,json,argparse import urllib.parse From 84d91bc8161dc0a944df75d733cc95b8c7439d07 Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Mon, 6 Jan 2020 15:44:23 -0800 Subject: [PATCH 3/8] hack: update format of rhcos build metadata This splits the RHCOS build metadata into architecture-specific files. This will allow the metadata to contain information about bootimages of multiple architectures. In order to preserve backward compatibility (there are a few users, including certain CI jobs, that pull rhcos.json from GitHub directly), I've opted to use separate files for each architecture. Normally, we could have just symlinked the legacy metadata file, but when hosted on raw.githubcontent.com, the symlinks aren't followed. When updating the RHCOS bootimages, this script will need to be run once for each architecture that is being updated. (cherry picked from commit b1726d2c5e819310e3dab26510e776a5e84f4bf4) --- data/data/rhcos-amd64.json | 135 +++++++++++++++++++++++++++++++++ hack/update-rhcos-bootimage.py | 18 ++++- 2 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 data/data/rhcos-amd64.json diff --git a/data/data/rhcos-amd64.json b/data/data/rhcos-amd64.json new file mode 100644 index 00000000000..aab2523d866 --- /dev/null +++ b/data/data/rhcos-amd64.json @@ -0,0 +1,135 @@ +{ + "amis": { + "ap-northeast-1": { + "hvm": "ami-0ade724aa9d3514b2" + }, + "ap-northeast-2": { + "hvm": "ami-0465f2a5450aa0257" + }, + "ap-south-1": { + "hvm": "ami-05a3e4b22ecffdf62" + }, + "ap-southeast-1": { + "hvm": "ami-00df6135b05c0a02a" + }, + "ap-southeast-2": { + "hvm": "ami-075295f492dbaa347" + }, + "ca-central-1": { + "hvm": "ami-0a27aa00147a3a2d9" + }, + "eu-central-1": { + "hvm": "ami-0e8ca170012209d72" + }, + "eu-north-1": { + "hvm": "ami-0c736720637f6b42d" + }, + "eu-west-1": { + "hvm": "ami-0770d1d7e95da7ba3" + }, + "eu-west-2": { + "hvm": "ami-08499730d4db69065" + }, + "eu-west-3": { + "hvm": "ami-0658bcfda04098635" + }, + "me-south-1": { + "hvm": "ami-0ea763ffb3e1c62cf" + }, + "sa-east-1": { + "hvm": "ami-0298057a4a12e874a" + }, + "us-east-1": { + "hvm": "ami-0523c75e911667e58" + }, + "us-east-2": { + "hvm": "ami-0d8f77b753c0d96dd" + }, + "us-west-1": { + "hvm": "ami-0782247660ad3a3bb" + }, + "us-west-2": { + "hvm": "ami-0f0fac946d1d31e97" + } + }, + "azure": { + "image": "rhcos-43.81.202003111353.0-azure.x86_64.vhd", + "url": "https://rhcos.blob.core.windows.net/imagebucket/rhcos-43.81.202003111353.0-azure.x86_64.vhd" + }, + "baseURI": "https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.3/43.81.202003111353.0/x86_64/", + "buildid": "43.81.202003111353.0", + "gcp": { + "image": "rhcos-43-81-202003111353-0", + "url": "https://storage.googleapis.com/rhcos/rhcos/43.81.202003111353.0.tar.gz" + }, + "images": { + "aws": { + "path": "rhcos-43.81.202003111353.0-aws.x86_64.vmdk.gz", + "sha256": "e4cbc50409d93fb88d711a89e62c56639579abf804bf2d25b210f43929939000", + "size": 814861898, + "uncompressed-sha256": "2383f9687db4b2f40bf70f2a9750f651c135d09973f7e7f7ed02ac05179e0ea2", + "uncompressed-size": 831565312 + }, + "azure": { + "path": "rhcos-43.81.202003111353.0-azure.x86_64.vhd.gz", + "sha256": "a2c75bfb3f1c75bd21bba1d669631b05692c1a91a88802bbcd7a3218e1834ff6", + "size": 802153013, + "uncompressed-sha256": "bd427aaa3fab89261ac565a89b0b6d066e3a559e2d62d1f6cb749294963162df", + "uncompressed-size": 2189996544 + }, + "gcp": { + "path": "rhcos-43.81.202003111353.0-gcp.x86_64.tar.gz", + "sha256": "8baade8d055181d538f75e00367a860c9197c684924062919eb982f5101d27d1", + "size": 801779472 + }, + "initramfs": { + "path": "rhcos-43.81.202003111353.0-installer-initramfs.x86_64.img", + "sha256": "fa01f1eeeaf6924d8d20bf5834d3853985167b670a0de30a32bc80d3f8c700d4" + }, + "iso": { + "path": "rhcos-43.81.202003111353.0-installer.x86_64.iso", + "sha256": "b10975f240769e6f606981be4fe4740536522f7afefe30c95d93f059db48c756" + }, + "kernel": { + "path": "rhcos-43.81.202003111353.0-installer-kernel-x86_64", + "sha256": "4d7f7b0a631a8f3fd34c9d39e7a037655871f05d503af240e7647a5f4e6490c9" + }, + "metal": { + "path": "rhcos-43.81.202003111353.0-metal.x86_64.raw.gz", + "sha256": "de35f0e0b75c907c805aef687120b34c00e158bd5afaaf7aa60097fe3ed65480", + "size": 803474932, + "uncompressed-sha256": "30e867fb2c2490873276c175e178d77646dd304c91e05d8f99493ebfb16c2fef", + "uncompressed-size": 3369074688 + }, + "openstack": { + "path": "rhcos-43.81.202003111353.0-openstack.x86_64.qcow2.gz", + "sha256": "8f17baa5564450eea4d3b6f817df3df58af7c3294583be62de615663c0ec55a5", + "size": 803742118, + "uncompressed-sha256": "4d204e638d365d9de121f5d513cff2567abd9232710f4bb79992efa4ba718008", + "uncompressed-size": 2148728832 + }, + "ostree": { + "path": "rhcos-43.81.202003111353.0-ostree.x86_64.tar", + "sha256": "c1501350436424ec6d7a805c52b3fc665fe490912f5a16d94bf267c9efa2848f", + "size": 722647040 + }, + "qemu": { + "path": "rhcos-43.81.202003111353.0-qemu.x86_64.qcow2.gz", + "sha256": "cd3260155e494efdb38d0b3019a29980675bff2fee05a80162bd7a587a9bdba6", + "size": 804202741, + "uncompressed-sha256": "bee078cfef57f51d11dcdc7211185e5e85016e044081f3aec9b42637ebd05fec", + "uncompressed-size": 2148663296 + }, + "vmware": { + "path": "rhcos-43.81.202003111353.0-vmware.x86_64.ova", + "sha256": "c60c94b3ee918379230c63ca18ea144fed57088bc51eee5f12cf839ceb6c1fb6", + "size": 831580160 + } + }, + "oscontainer": { + "digest": "sha256:eb81a7625f9fc3d1575f92dd4e825b02ec6e362c88a1bd6e048c789a7f965771", + "image": "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + }, + "ostree-commit": "86e3934e5a039782f1f1df0f827ce00be7572f9be2441e0d7631a20dff9b2933", + "ostree-version": "43.81.202003111353.0" +} \ No newline at end of file diff --git a/hack/update-rhcos-bootimage.py b/hack/update-rhcos-bootimage.py index 604bbc399b5..56da03a33b7 100755 --- a/hack/update-rhcos-bootimage.py +++ b/hack/update-rhcos-bootimage.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Usage: ./hack/update-rhcos-bootimage.py https://releases-art-rhcos.svc.ci.openshift.org/storage/releases/ootpa/410.8.20190401.0/meta.json +# Usage: ./hack/update-rhcos-bootimage.py https://releases-art-rhcos.svc.ci.openshift.org/storage/releases/ootpa/410.8.20190401.0/meta.json amd64 import codecs,os,sys,json,argparse import urllib.parse import urllib.request @@ -8,12 +8,13 @@ # builds. Do not try to e.g. point to RHT-internal endpoints. RHCOS_RELEASES_APP = 'https://releases-art-rhcos.svc.ci.openshift.org' -dn = os.path.abspath(os.path.dirname(sys.argv[0])) - parser = argparse.ArgumentParser() parser.add_argument("meta", action='store') +parser.add_argument("arch", action='store', choices=['amd64']) args = parser.parse_args() +metadata_dir = os.path.join(os.path.dirname(sys.argv[0]), "../data/data") + if not args.meta.startswith(RHCOS_RELEASES_APP): raise SystemExit("URL must start with: " + RHCOS_RELEASES_APP) @@ -32,5 +33,14 @@ for entry in meta['amis'] } newmeta['baseURI'] = urllib.parse.urljoin(args.meta, '.') -with open(os.path.join(dn, "../data/data/rhcos.json"), 'w') as f: + +with open(os.path.join(metadata_dir, f"rhcos-{args.arch}.json"), 'w') as f: json.dump(newmeta, f, sort_keys=True, indent=4) + +# Continue to populate the legacy metadata file because there are still +# processes consuming this file directly. This normally could just be a symlink +# but some of these processes reference raw.githubusercontent.com which doesn't +# follow symlinks. +if args.arch == 'amd64': + with open(os.path.join(metadata_dir, "rhcos.json"), 'w') as f: + json.dump(newmeta, f, sort_keys=True, indent=4) From a7dc41cc4555f41c791a1f139993cb7df6b4ba6c Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Mon, 6 Jan 2020 18:17:47 -0800 Subject: [PATCH 4/8] *: enable s390x bootimage support (cherry picked from commit b7d74740800b6f8e754a91d2934ffbfca0dd6b8f) --- hack/update-rhcos-bootimage.py | 16 +++++++++------- pkg/types/machinepools.go | 2 ++ pkg/types/validation/installconfig_test.go | 10 +++++++++- pkg/types/validation/machinepools.go | 1 + 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/hack/update-rhcos-bootimage.py b/hack/update-rhcos-bootimage.py index 56da03a33b7..b27bf9092e1 100755 --- a/hack/update-rhcos-bootimage.py +++ b/hack/update-rhcos-bootimage.py @@ -10,7 +10,7 @@ parser = argparse.ArgumentParser() parser.add_argument("meta", action='store') -parser.add_argument("arch", action='store', choices=['amd64']) +parser.add_argument("arch", action='store', choices=['amd64', 's390x']) args = parser.parse_args() metadata_dir = os.path.join(os.path.dirname(sys.argv[0]), "../data/data") @@ -25,13 +25,15 @@ for k in ['images', 'buildid', 'oscontainer', 'ostree-commit', 'ostree-version', 'azure', 'gcp']: - newmeta[k] = meta[k] -newmeta['amis'] = { - entry['name']: { - 'hvm': entry['hvm'], + if meta.get(k): + newmeta[k] = meta[k] +if meta.get(k): + newmeta['amis'] = { + entry['name']: { + 'hvm': entry['hvm'], + } + for entry in meta['amis'] } - for entry in meta['amis'] -} newmeta['baseURI'] = urllib.parse.urljoin(args.meta, '.') with open(os.path.join(metadata_dir, f"rhcos-{args.arch}.json"), 'w') as f: diff --git a/pkg/types/machinepools.go b/pkg/types/machinepools.go index 331f98792ab..e1be51b827d 100644 --- a/pkg/types/machinepools.go +++ b/pkg/types/machinepools.go @@ -26,6 +26,8 @@ type Architecture string const ( // ArchitectureAMD64 indicates AMD64 (x86_64). ArchitectureAMD64 = "amd64" + // ArchitectureS390X indicates s390x (IBM System Z). + ArchitectureS390X = "s390x" ) // MachinePool is a pool of machines to be installed. diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index f904fcc86c4..93b3241ca9e 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -884,7 +884,15 @@ func TestValidateInstallConfig(t *testing.T) { }(), expectedError: `Invalid value: "DualStack": dual-stack IPv4/IPv6 is not supported for this platform, specify only one type of address`, }, - // TODO(crawford): add a test to validate that homogeneous clusters are enforced once an additional architecture is added + { + name: "cluster is not heteregenous", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + c.Compute[0].Architecture = types.ArchitectureS390X + return c + }(), + expectedError: `^compute\[0\].architecture: Invalid value: "s390x": heteregeneous multi-arch is not supported; compute pool architecture must match control plane$`, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/types/validation/machinepools.go b/pkg/types/validation/machinepools.go index 6c9ed452458..60b33b6e6f9 100644 --- a/pkg/types/validation/machinepools.go +++ b/pkg/types/validation/machinepools.go @@ -34,6 +34,7 @@ var ( validArchitectures = map[types.Architecture]bool{ types.ArchitectureAMD64: true, + types.ArchitectureS390X: true, } validArchitectureValues = func() []string { From 77dfa336f702259bab16eb4b6466e93cf354e0fb Mon Sep 17 00:00:00 2001 From: Prashanth Sundararaman Date: Thu, 5 Mar 2020 14:32:01 -0500 Subject: [PATCH 5/8] add buildmetadata for s390x Similar to commit https://github.com/openshift/installer/commit/b1381e5f9ed9c203cd14fd6805a981a2eca5dd73 for 4.2 This was generated by: ./hack/update-rhcos-bootimage.py https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.3-s390x/43.81.202003172338.0/s390x/meta.json s390x --- data/data/rhcos-s390x.json | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 data/data/rhcos-s390x.json diff --git a/data/data/rhcos-s390x.json b/data/data/rhcos-s390x.json new file mode 100644 index 00000000000..5100a7f8ea4 --- /dev/null +++ b/data/data/rhcos-s390x.json @@ -0,0 +1,57 @@ +{ + "baseURI": "https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.3-s390x/43.81.202003172338.0/s390x/", + "buildid": "43.81.202003172338.0", + "images": { + "dasd": { + "path": "rhcos-43.81.202003172338.0-dasd.s390x.raw.gz", + "sha256": "6b2e0ac527cc33f47154e125be51542291657fea3c51d7e30000a79b46d27446", + "size": 702271061, + "uncompressed-sha256": "789d52cb84fdfd7d5167f6a6b4e1b0803c7696bf96777e7c4911caf6b5ad31a1", + "uncompressed-size": 3171942400 + }, + "initramfs": { + "path": "rhcos-43.81.202003172338.0-installer-initramfs.s390x.img", + "sha256": "fcb4958ab779bc2d59a451deb62e62b929b7d2fb2b404c698d04968c69ee82ea" + }, + "iso": { + "path": "rhcos-43.81.202003172338.0-installer.s390x.iso", + "sha256": "1df3e0cbe8e15c27b3133e59df4a19fd23b01743f37f7cfc5b2283f2129e4cbc" + }, + "kernel": { + "path": "rhcos-43.81.202003172338.0-installer-kernel-s390x", + "sha256": "02084b138d77182a3a58dc2e290ab47ec412c5a0441f6d2989c02a89d60f613a" + }, + "metal": { + "path": "rhcos-43.81.202003172338.0-metal.s390x.raw.gz", + "sha256": "5e9f11b6c0c310daecabe75fd3435eeb810f9283d322e9efc890e5d8a97c0202", + "size": 702238370, + "uncompressed-sha256": "884be2265e5bc9f310874aed3d093dd4deed187caa240a32672d315bbfeddafa", + "uncompressed-size": 3171942400 + }, + "openstack": { + "path": "rhcos-43.81.202003172338.0-openstack.s390x.qcow2.gz", + "sha256": "9784da7eee7b7c8d07d68da3900634ad17e3d59c86b4eb79554b8a8b2b4fcf11", + "size": 702634988, + "uncompressed-sha256": "59d290e40071298b852d233ebcbae9df527836729d2b35862768e0b7e27857d5", + "uncompressed-size": 1978335232 + }, + "ostree": { + "path": "rhcos-43.81.202003172338.0-ostree.s390x.tar", + "sha256": "e85d4cff77aeb3e8fd4c04e3ae578be017995ba16975a62256f68515186ec3a1", + "size": 642109440 + }, + "qemu": { + "path": "rhcos-43.81.202003172338.0-qemu.s390x.qcow2.gz", + "sha256": "5384458dcaa5e8a8795355046106335fda9a7c079cd165addf7729989afd9377", + "size": 703123878, + "uncompressed-sha256": "717e3d74403e56878961d4e654a161c088c9c1ccf94bbd407fd273b302db376d", + "uncompressed-size": 1978204160 + } + }, + "oscontainer": { + "digest": "sha256:0b513016131fdab7760dee9ffeab65f7b1c4a928123e81367a0c34c4393a2c0e", + "image": "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + }, + "ostree-commit": "fed64caf6e88503e9190e84fbb9a57ab63783e12ab3895bf67e68f66d11b84d1", + "ostree-version": "43.81.202003172338.0" +} \ No newline at end of file From 84608d9fd4cedc599f077d1b7cc3cd1a4cf8ec03 Mon Sep 17 00:00:00 2001 From: Prashanth Sundararaman Date: Thu, 5 Mar 2020 16:19:53 -0500 Subject: [PATCH 6/8] add buildmetadata for ppc64le Similar to previous commit, add metadata for ppc64le which is a supported arch 4.3 onwards. This was generated by: ./hack/update-rhcos-bootimage.py https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.3-ppc64le/43.81.202003172241.0/ppc64le/meta.json ppc64le --- data/data/rhcos-ppc64le.json | 50 ++++++++++++++++++++++++++++++++++ hack/update-rhcos-bootimage.py | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 data/data/rhcos-ppc64le.json diff --git a/data/data/rhcos-ppc64le.json b/data/data/rhcos-ppc64le.json new file mode 100644 index 00000000000..f291f3b32fb --- /dev/null +++ b/data/data/rhcos-ppc64le.json @@ -0,0 +1,50 @@ +{ + "baseURI": "https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.3-ppc64le/43.81.202003172241.0/ppc64le/", + "buildid": "43.81.202003172241.0", + "images": { + "initramfs": { + "path": "rhcos-43.81.202003172241.0-installer-initramfs.ppc64le.img", + "sha256": "451bfc5b1a872b92c3567d0892eac101bc43bc2d9934c4d6933c379d1936b409" + }, + "iso": { + "path": "rhcos-43.81.202003172241.0-installer.ppc64le.iso", + "sha256": "9debdc0bfe2380a2ee057cb1db686f80e95ea9d1c0e45ea8ca70a956467622e8" + }, + "kernel": { + "path": "rhcos-43.81.202003172241.0-installer-kernel-ppc64le", + "sha256": "5a78b5099da27cbe6d22032c8e55542c1b2885e8c1e69206f7fc390dae9897b7" + }, + "metal": { + "path": "rhcos-43.81.202003172241.0-metal.ppc64le.raw.gz", + "sha256": "0f62f700d805e104e6d5f7743a42101050ab390f18005c11991c80e7a8a42fd6", + "size": 775658410, + "uncompressed-sha256": "2d9678ffbd09ea9f1536f981e9104c5bc26e6326e9c75aa1b162957f7c83f661", + "uncompressed-size": 3486515200 + }, + "openstack": { + "path": "rhcos-43.81.202003172241.0-openstack.ppc64le.qcow2.gz", + "sha256": "a9c35106ba9ae2c7bf0543d460b5f9278f0624bd39e121b3baaecead68b1326a", + "size": 774596933, + "uncompressed-sha256": "0af1fecc742a46d376a053783d46210188fc77c93e4186e8aa3586d7b09ed0f1", + "uncompressed-size": 2246377472 + }, + "ostree": { + "path": "rhcos-43.81.202003172241.0-ostree.ppc64le.tar", + "sha256": "57da39c5b22ea077e2f7835ca8b140d55c1154c376b911bbf22cd103480f357e", + "size": 692090880 + }, + "qemu": { + "path": "rhcos-43.81.202003172241.0-qemu.ppc64le.qcow2.gz", + "sha256": "cc7b2ae27936cd67be3338432a11f5b24f36edcef0c6c43c5c2807bb20f4ae1c", + "size": 775059270, + "uncompressed-sha256": "caef1dc9cc9d08f56241c37a77e08f90d4f72d448569caead522ae5aba239c8f", + "uncompressed-size": 2246311936 + } + }, + "oscontainer": { + "digest": "sha256:d61cfef76f88a5d3028d28c80b9ecbbb2a20c3dc152d66566375fb5589e9105e", + "image": "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + }, + "ostree-commit": "2212098f5ea4361b60987472185f0406e8d78253b5b16399610809abe74d26cc", + "ostree-version": "43.81.202003172241.0" +} \ No newline at end of file diff --git a/hack/update-rhcos-bootimage.py b/hack/update-rhcos-bootimage.py index b27bf9092e1..b1f98439ac8 100755 --- a/hack/update-rhcos-bootimage.py +++ b/hack/update-rhcos-bootimage.py @@ -10,7 +10,7 @@ parser = argparse.ArgumentParser() parser.add_argument("meta", action='store') -parser.add_argument("arch", action='store', choices=['amd64', 's390x']) +parser.add_argument("arch", action='store', choices=['amd64', 's390x', 'ppc64le']) args = parser.parse_args() metadata_dir = os.path.join(os.path.dirname(sys.argv[0]), "../data/data") From d27e3d748f89ebfd430dd2b9147edc52723cb490 Mon Sep 17 00:00:00 2001 From: Prashanth Sundararaman Date: Wed, 18 Mar 2020 14:04:40 -0400 Subject: [PATCH 7/8] *: enable ppc64le bootimage support --- pkg/types/machinepools.go | 2 ++ pkg/types/validation/installconfig_test.go | 9 +++++++++ pkg/types/validation/machinepools.go | 5 +++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pkg/types/machinepools.go b/pkg/types/machinepools.go index e1be51b827d..5183a2d02fb 100644 --- a/pkg/types/machinepools.go +++ b/pkg/types/machinepools.go @@ -28,6 +28,8 @@ const ( ArchitectureAMD64 = "amd64" // ArchitectureS390X indicates s390x (IBM System Z). ArchitectureS390X = "s390x" + // ArchitecturePPC64LE indicates ppc64 little endian (Power PC) + ArchitecturePPC64LE = "ppc64le" ) // MachinePool is a pool of machines to be installed. diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index 93b3241ca9e..8924e69c23f 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -893,6 +893,15 @@ func TestValidateInstallConfig(t *testing.T) { }(), expectedError: `^compute\[0\].architecture: Invalid value: "s390x": heteregeneous multi-arch is not supported; compute pool architecture must match control plane$`, }, + { + name: "cluster is not heteregenous", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + c.Compute[0].Architecture = types.ArchitecturePPC64LE + return c + }(), + expectedError: `^compute\[0\].architecture: Invalid value: "ppc64le": heteregeneous multi-arch is not supported; compute pool architecture must match control plane$`, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/types/validation/machinepools.go b/pkg/types/validation/machinepools.go index 60b33b6e6f9..7be7c9d0af6 100644 --- a/pkg/types/validation/machinepools.go +++ b/pkg/types/validation/machinepools.go @@ -33,8 +33,9 @@ var ( }() validArchitectures = map[types.Architecture]bool{ - types.ArchitectureAMD64: true, - types.ArchitectureS390X: true, + types.ArchitectureAMD64: true, + types.ArchitectureS390X: true, + types.ArchitecturePPC64LE: true, } validArchitectureValues = func() []string { From 791f248d8675c8ae44af46778497eaa65fd70eae Mon Sep 17 00:00:00 2001 From: Prashanth Sundararaman Date: Fri, 27 Mar 2020 09:34:56 -0400 Subject: [PATCH 8/8] Bump terraform libvirt provider Bump terraform libvirt provider to use the openshift/terraform-provider-libvirt multi_arch branch which has the support for fetching ignition for s390x and ppc64le. The multi_arch branch is based on the 40b0cda5333a29dd9f33d1cfdc206bfad3a8af96 commit of the provider and just adds - https://github.com/dmacvicar/terraform-provider-libvirt/pull/718 --- pkg/terraform/exec/plugins/Gopkg.lock | 5 +- pkg/terraform/exec/plugins/Gopkg.toml | 3 +- .../libvirt/coreos_ignition_def.go | 58 +++-------------- .../libvirt/domain.go | 65 ++++++++++--------- .../libvirt/resource_libvirt_domain.go | 9 +-- 5 files changed, 51 insertions(+), 89 deletions(-) diff --git a/pkg/terraform/exec/plugins/Gopkg.lock b/pkg/terraform/exec/plugins/Gopkg.lock index cf5b3e86a1a..768152fd9ed 100644 --- a/pkg/terraform/exec/plugins/Gopkg.lock +++ b/pkg/terraform/exec/plugins/Gopkg.lock @@ -385,13 +385,16 @@ [[projects]] digest = "1:151f72934298019168adb99a7d17dfa203a65eb49af5da41429775284ea8ce3f" + branch = "multi_arch" + digest = "1:5cf80e7508c8328d4e1d1eec73d4780d5ed075653ab6a34fa5bdd838e089bfae" name = "github.com/dmacvicar/terraform-provider-libvirt" packages = [ "libvirt", "libvirt/helper/suppress", ] pruneopts = "NUT" - revision = "40b0cda5333a29dd9f33d1cfdc206bfad3a8af96" + revision = "312c4360a8bce9e0939b7a1156b848512d311d86" + source = "https://github.com/openshift/terraform-provider-libvirt" [[projects]] branch = "master" diff --git a/pkg/terraform/exec/plugins/Gopkg.toml b/pkg/terraform/exec/plugins/Gopkg.toml index b8327e95417..27874d2046d 100644 --- a/pkg/terraform/exec/plugins/Gopkg.toml +++ b/pkg/terraform/exec/plugins/Gopkg.toml @@ -11,7 +11,8 @@ ignored = [ [[constraint]] name = "github.com/dmacvicar/terraform-provider-libvirt" - revision = "40b0cda5333a29dd9f33d1cfdc206bfad3a8af96" + source = "https://github.com/openshift/terraform-provider-libvirt" + branch = "multi_arch" [[constraint]] name = "github.com/terraform-providers/terraform-provider-aws" diff --git a/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go b/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go index b8154d14357..87ab3994670 100644 --- a/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go +++ b/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go @@ -8,8 +8,6 @@ import ( "io/ioutil" "log" "os" - "os/exec" - "path/filepath" "strings" libvirt "github.com/libvirt/libvirt-go" @@ -52,55 +50,17 @@ func (ign *defIgnition) CreateAndUpload(client *Client) (string, error) { volumeDef := newDefVolume() volumeDef.Name = ign.Name - tmpDir, err := ioutil.TempDir("", "ignition") + ignFile, err := ign.createFile() if err != nil { - return "", fmt.Errorf("Failed to create Ignition directory: %v", err) + return "", err } defer func() { - if err = os.RemoveAll(tmpDir); err != nil { - log.Printf("Error while removing Ignition directory: %v", err) + if err = os.Remove(ignFile); err != nil { + log.Printf("Error while removing tmp Ignition file: %v", err) } }() - ignPath, err := ign.createFile(tmpDir) - if err != nil { - return "", err - } - - arch, err := getHostArchitecture(client.libvirt) - if err != nil { - return "", fmt.Errorf("Error retrieving host architecture: %s", err) - } - - var userdataPath string - switch arch { - case "i686", "x86_64", "aarch64": - userdataPath = ignPath - case "s390", "s390x": - configDrivePath := filepath.Join(tmpDir, "config.iso") - cmd := exec.Command( - "mkisofs", - "-output", - configDrivePath, - "-volid", - "config-2", - "-root", - "openstack/latest", - "-joliet", - "-rock", - ignPath) - - log.Printf("Executing command: %+v", cmd) - if err = cmd.Run(); err != nil { - return "", fmt.Errorf("Failed to create Config Drive ISO image: %v", err) - } - - userdataPath = configDrivePath - default: - return "", fmt.Errorf("Ignition not supported on %q", arch) - } - - img, err := newImage(userdataPath) + img, err := newImage(ignFile) if err != nil { return "", err } @@ -156,12 +116,12 @@ func getIgnitionVolumeKeyFromTerraformID(id string) (string, error) { } // Dumps the Ignition object - either generated by Terraform or supplied as a file - -// to a userdata Ignition file in the provided directory -func (ign *defIgnition) createFile(dir string) (string, error) { +// to a temporary ignition file +func (ign *defIgnition) createFile() (string, error) { log.Print("Creating Ignition temporary file") - tempFile, err := os.Create(filepath.Join(dir, "user_data")) + tempFile, err := ioutil.TempFile("", ign.Name) if err != nil { - return "", fmt.Errorf("Error creating userdata file: %v", err) + return "", fmt.Errorf("Error creating tmp file: %v", err) } defer tempFile.Close() diff --git a/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go b/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go index cd4c4239ed4..284b13e4d00 100644 --- a/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go +++ b/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go @@ -198,26 +198,14 @@ func domainGetIfacesInfo(domain libvirt.Domain, rd *schema.ResourceData) ([]libv return interfaces, nil } -func newDiskForCloudInit(virConn *libvirt.Connect, volumeKey string, arch string) (libvirtxml.DomainDisk, error) { - var target *libvirtxml.DomainDiskTarget - switch arch { - case "s390", "s390x": - target = &libvirtxml.DomainDiskTarget{ - // s390 platform doesn't support IDE controllers - Dev: "vdb", - Bus: "scsi", - } - default: - target = &libvirtxml.DomainDiskTarget{ +func newDiskForCloudInit(virConn *libvirt.Connect, volumeKey string) (libvirtxml.DomainDisk, error) { + disk := libvirtxml.DomainDisk{ + Device: "cdrom", + Target: &libvirtxml.DomainDiskTarget{ // Last device letter possible with a single IDE controller on i440FX Dev: "hdd", Bus: "ide", - } - } - - disk := libvirtxml.DomainDisk{ - Device: "cdrom", - Target: target, + }, Driver: &libvirtxml.DomainDiskDriver{ Name: "qemu", Type: "raw", @@ -269,18 +257,33 @@ func setCoreOSIgnition(d *schema.ResourceData, domainDef *libvirtxml.Domain, vir }, } } - case "s390", "s390x": - // System Z does not support any of the same pass-through - // mechanisms as Ignition. As a temporary workaround, the OpenStack - // Config Drive can be used instead. The Ignition volume already - // contains a Config Drive at this point. - - disk, err := newDiskForCloudInit(virConn, ignitionKey, arch) - if err != nil { - return err + case "s390", "s390x", "ppc64", "ppc64le": + // System Z and PowerPC do not support the Firmware Configuration + // device. After a discussion about the best way to support a similar + // method for qemu in https://github.com/coreos/ignition/issues/928, + // decided on creating a virtio-blk device with a serial of ignition + // which contains the ignition config and have ignition support for + // reading from the device which landed in https://github.com/coreos/ignition/pull/936 + + igndisk := libvirtxml.DomainDisk{ + Device: "disk", + Source: &libvirtxml.DomainDiskSource{ + File: &libvirtxml.DomainDiskSourceFile{ + File: ignitionKey, + }, + }, + Target: &libvirtxml.DomainDiskTarget{ + Dev: "vdb", + Bus: "virtio", + }, + Driver: &libvirtxml.DomainDiskDriver{ + Name: "qemu", + Type: "raw", + }, + ReadOnly: &libvirtxml.DomainDiskReadOnly{}, + Serial: "ignition", } - - domainDef.Devices.Disks = append(domainDef.Devices.Disks, disk) + domainDef.Devices.Disks = append(domainDef.Devices.Disks, igndisk) default: return fmt.Errorf("Ignition not supported on %q", arch) } @@ -303,7 +306,7 @@ func setVideo(d *schema.ResourceData, domainDef *libvirtxml.Domain) error { } func setGraphics(d *schema.ResourceData, domainDef *libvirtxml.Domain, arch string) error { - if arch == "s390x" || arch == "ppc64" { + if arch == "s390x" || strings.HasPrefix(arch, "ppc64") { domainDef.Devices.Graphics = nil return nil } @@ -654,13 +657,13 @@ func setFilesystems(d *schema.ResourceData, domainDef *libvirtxml.Domain) error return nil } -func setCloudinit(d *schema.ResourceData, domainDef *libvirtxml.Domain, virConn *libvirt.Connect, arch string) error { +func setCloudinit(d *schema.ResourceData, domainDef *libvirtxml.Domain, virConn *libvirt.Connect) error { if cloudinit, ok := d.GetOk("cloudinit"); ok { cloudinitID, err := getCloudInitVolumeKeyFromTerraformID(cloudinit.(string)) if err != nil { return err } - disk, err := newDiskForCloudInit(virConn, cloudinitID, arch) + disk, err := newDiskForCloudInit(virConn, cloudinitID) if err != nil { return err } diff --git a/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go b/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go index a594d152654..bfa01903d97 100644 --- a/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go +++ b/pkg/terraform/exec/plugins/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go @@ -491,7 +491,7 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error return err } - if err := setCloudinit(d, &domainDef, virConn, arch); err != nil { + if err := setCloudinit(d, &domainDef, virConn); err != nil { return err } @@ -632,12 +632,7 @@ func resourceLibvirtDomainUpdate(d *schema.ResourceData, meta interface{}) error return err } - arch, err := getHostArchitecture(virConn) - if err != nil { - return fmt.Errorf("Error retrieving host architecture: %s", err) - } - - disk, err := newDiskForCloudInit(virConn, cloudinitID, arch) + disk, err := newDiskForCloudInit(virConn, cloudinitID) if err != nil { return err }