Skip to content

Commit b64d699

Browse files
cgwaltersstaebler
andcommitted
Add stream metadata for RHCOS
This implements part of the plan from: openshift/os#477 When we originally added the pinned RHCOS metadata `rhcos.json` to the installer, we also changed the coreos-assembler `meta.json` format into an arbitrary new format in the name of some cleanups. In retrospect, this was a big mistake because we now have two formats. Then Fedora CoreOS appeared and added streams JSON as a public API. We decided to unify on streams metadata; there's now a published Go library for it: https://github.com/coreos/stream-metadata-go Among other benefits, it is a single file that supports multiple architectures. UPI installs should now use stream metadata, particularly to find public cloud images. This is exposed via a new `openshift-install coreos print-stream-json` command. This is an important preparatory step for exposing this via `oc` as well as having something in the cluster update to it. HOWEVER as a (really hopefully temporary) hack, we *duplicate* the metadata so that IPI installs use the new stream format, and UPI CI jobs can still use the old format (with different RHCOS versions). We will port the UPI docs and CI jobs after this merges. Co-authored-by: Matthew Staebler <[email protected]>
1 parent a61a5bb commit b64d699

16 files changed

+639
-312
lines changed

data/data/rhcos-stream.json

Lines changed: 398 additions & 0 deletions
Large diffs are not rendered by default.

docs/user/aws/install_upi.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ $ openshift-install create install-config
2121
### Optional: Create Encrypted AMIs
2222

2323
The IPI-based installer creates an encrypted AMI by default. If you wish to have an encrypted AMI for UPI-based
24-
installs, you will need to create it directly. You can find a list of the appropriate base AMIs
25-
[here](../../../data/data/rhcos.json).
24+
installs, you will need to create it directly. See [CoreOS bootimages](../overview.md#coreos-bootimages) for more information
25+
about bootimages, including how to find the AMI identifiers.
2626

2727
You will make an encrypted copy of the AMI according to the [AWS documentation][encrypted-copy].
2828

docs/user/metal/customization_ipi.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424

2525
When doing a disconnected installation, the baremetal platform has the
2626
additional requirement that we have locations to download the RHCOS
27-
images. The installer downloads these from a location described in
28-
[/data/data/rhcos.json](/data/data/rhcos.json), but they can be
27+
images. The installer downloads these from a CoreOS stream metadata
28+
embedded in the installer code, but they can be
2929
overridden to point to a local mirror.
3030

31-
The SHA256 parameter in the URLs are required, and should match the
32-
uncompressed SHA256 from rhcos.json.
31+
See [CoreOS bootimages](../overview.md#coreos-bootimages) for more information
32+
about bootimages.
3333

34+
The SHA256 parameter in the URL is required, and should match the
35+
uncompressed SHA256 from the stream metadata JSON.
3436

3537
* `bootstrapOSImage` (optional string): Override the image used for the
3638
bootstrap virtual machine.

docs/user/openstack/customization.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,18 @@ sshKey: ssh-ed25519 AAAA...
112112
113113
## Image Overrides
114114
115-
Normally the installer downloads the RHCOS image from a predetermined location described in [data/data/rhcos.json](/data/data/rhcos.json)). But the download URL can be overridden, notably for disconnected installations.
115+
The OpenShift installer pins the version of RHEL CoreOS and normally handles uploading the image to the target OpenStack instance.
116116
117-
To do so and upload binary data from a custom location the user may set `clusterOSImage` parameter in the install config that points to that location, and then start the installation. In all other respects the process will be consistent with the default.
117+
If you want to download the image manually, see [CoreOS bootimages](../overview.md#coreos-bootimages) for more information
118+
about bootimages. This is useful, for example, to perform a disconnected installation. To do this,
119+
download the `qcow2` and host it at a custom location. Then set the `openstack.clusterOSImage`
120+
parameter field in the install config to point to that location. The install process will
121+
then use that mirrored image.
122+
In all other respects the process will be consistent with the default.
118123

119124
**NOTE:** For this to work, the parameter value must be a valid http(s) URL.
120125

121-
**NOTE:** The optional `sha256` query parameter can be attached to the URL, which will force the installer to check the image file checksum before uploading it into Glance.
126+
**NOTE:** The optional `sha256` query parameter can be attached to the URL. This will force the installer to check the uncompressed image file checksum before uploading it into Glance.
122127

123128
Example:
124129

docs/user/overview.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,33 @@ As the unstable warning suggests, the presence of `manifests` and the names and
8484
It is occasionally useful to make alterations like this as one-off changes, but don't expect them to work on subsequent installer releases.
8585

8686
[cluster-version]: https://github.com/openshift/cluster-version-operator/blob/master/docs/dev/clusterversion.md
87+
88+
### CoreOS bootimages
89+
90+
The `openshift-install` binary contains pinned versions of RHEL CoreOS "bootimages" (e.g. OpenStack `qcow2`, AWS AMI, bare metal `.iso`).
91+
Fully automated installs use these by default.
92+
93+
For UPI (User Provisioned Infrastructure) installs, you can use the `openshift-install coreos print-stream-json` command to access information
94+
about the bootimages in [CoreOS Stream Metadata](https://github.com/coreos/stream-metadata-go) format.
95+
96+
For example, this command will print the `x86_64` AMI for `us-west-1`:
97+
98+
```
99+
$ openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.images.aws.regions["us-west-1"].image'
100+
ami-0c548bdf93b74cd59
101+
```
102+
103+
For on-premise clouds (e.g. OpenStack) with UPI installs, you may need to manually copy
104+
a bootimage into the infrastructure. Here's an example command to print the `x86_64` `qcow2` file for `openstack`:
105+
106+
```
107+
$ openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.artifacts.openstack.formats["qcow2.gz"]'
108+
{
109+
"disk": {
110+
"location": "https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.8/48.83.202102230316-0/x86_64/rhcos-48.83.202102230316-0-openstack.x86_64.qcow2.gz",
111+
"signature": "https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.8/48.83.202102230316-0/x86_64/rhcos-48.83.202102230316-0-openstack.x86_64.qcow2.gz.sig",
112+
"sha256": "abc2add9746eb7be82e6919ec13aad8e9eae8cf073d8da6126d7c95ea0dee962",
113+
"uncompressed-sha256": "9ed73a4e415ac670535c2188221e5a4a5f3e945bc2e03a65b1ed4fc76e5db6f2"
114+
}
115+
}
116+
```

hack/update-rhcos-bootimage.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
11
#!/usr/bin/env python3
2+
# As of 4.8 we are aiming to switch to stream metadata:
3+
# https://github.com/openshift/enhancements/pull/679
4+
# That transition hasn't yet fully completed; there are two copies of the
5+
# RHCOS metadata:
6+
#
7+
# - data/data/rhcos-4.8.json (stream format, 4.8+)
8+
# - data/data/rhcos-$arch.json (openshift/installer specific, 4.7 and below)
9+
#
10+
# See https://github.com/coreos/coreos-assembler/pull/2000 in particular.
11+
#
12+
# The initial file data/data/rhcos-4.8 was generated this way:
13+
#
14+
# $ plume cosa2stream --name rhcos-4.8 --distro rhcos x86_64=48.83.202102230316-0 s390x=47.83.202102090311-0 ppc64le=47.83.202102091015-0 > data/data/rhcos-4.8.json
15+
#
16+
# To update the bootimage for one or more architectures, use e.g.
17+
#
18+
# $ plume cosa2stream --target data/data/rhcos-4.8.json --distro rhcos x86_64=48.83.202102230316-0 s390x=47.83.202102090311-0 ppc64le=47.83.202102091015-0
19+
#
20+
# To update the legacy metadata, use:
221
# Usage: ./hack/update-rhcos-bootimage.py https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.6/46.82.202008260918-0/x86_64/meta.json amd64
322
import codecs,os,sys,json,argparse
423
import urllib.parse

pkg/asset/cluster/tfvars.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strings"
1010

1111
igntypes "github.com/coreos/ignition/v2/config/v3_2/types"
12+
coreosarch "github.com/coreos/stream-metadata-go/arch"
1213
gcpprovider "github.com/openshift/cluster-api-provider-gcp/pkg/apis/gcpprovider/v1beta1"
1314
kubevirtprovider "github.com/openshift/cluster-api-provider-kubevirt/pkg/apis/kubevirtprovider/v1alpha1"
1415
kubevirtutils "github.com/openshift/cluster-api-provider-kubevirt/pkg/utils"
@@ -338,16 +339,30 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
338339
}
339340
preexistingnetwork := installConfig.Config.GCP.Network != ""
340341

341-
imageRaw, err := rhcospkg.GCPRaw(ctx, installConfig.Config.ControlPlane.Architecture)
342+
archName := coreosarch.RpmArch(string(installConfig.Config.ControlPlane.Architecture))
343+
st, err := rhcospkg.FetchCoreOSBuild(ctx)
342344
if err != nil {
343-
return errors.Wrap(err, "failed to find Raw GCP image URL")
345+
return err
346+
}
347+
streamArch, err := st.GetArchitecture(archName)
348+
if err != nil {
349+
return err
350+
}
351+
352+
img := streamArch.Images.Gcp
353+
if img == nil {
354+
return fmt.Errorf("%s: No GCP build found", st.FormatPrefix(archName))
344355
}
356+
// For backwards compatibility, we generate this URL to the image (only applies to RHCOS, not FCOS/OKD)
357+
// right now. It will only be used if nested virt or other licenses are enabled, which we
358+
// really should deprecate and remove - xref https://github.com/openshift/installer/pull/4696
359+
imageURL := fmt.Sprintf("https://storage.googleapis.com/rhcos/rhcos/%s.tar.gz", img.Name)
345360
data, err := gcptfvars.TFVars(
346361
gcptfvars.TFVarsSources{
347362
Auth: auth,
348363
MasterConfigs: masterConfigs,
349364
WorkerConfigs: workerConfigs,
350-
ImageURI: imageRaw,
365+
ImageURI: imageURL,
351366
ImageLicenses: installConfig.Config.GCP.Licenses,
352367
PublicZoneName: publicZoneName,
353368
PublishStrategy: installConfig.Config.Publish,

pkg/asset/rhcos/bootstrap_image.go

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package rhcos
33

44
import (
55
"context"
6+
"fmt"
67
"time"
78

9+
"github.com/coreos/stream-metadata-go/arch"
10+
811
"github.com/openshift/installer/pkg/asset"
912
"github.com/openshift/installer/pkg/asset/installconfig"
1013
"github.com/openshift/installer/pkg/rhcos"
@@ -37,28 +40,44 @@ func (i *BootstrapImage) Generate(p asset.Parents) error {
3740
p.Get(ic)
3841
config := ic.Config
3942

40-
var osimage string
41-
var err error
4243
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
4344
defer cancel()
45+
4446
switch config.Platform.Name() {
4547
case baremetal.Name:
46-
// Check for RHCOS image URL override
47-
if boi := config.Platform.BareMetal.BootstrapOSImage; boi != "" {
48-
osimage = boi
49-
break
48+
archName := arch.RpmArch(string(config.ControlPlane.Architecture))
49+
st, err := rhcos.FetchCoreOSBuild(ctx)
50+
if err != nil {
51+
return err
52+
}
53+
streamArch, err := st.GetArchitecture(archName)
54+
if err != nil {
55+
return err
5056
}
5157

58+
// Check for CoreOS image URL override
59+
if boi := config.Platform.BareMetal.BootstrapOSImage; boi != "" {
60+
*i = BootstrapImage(boi)
61+
return nil
62+
}
5263
// Baremetal IPI launches a local VM for the bootstrap node
5364
// Hence requires the QEMU image to use the libvirt backend
54-
osimage, err = rhcos.QEMU(ctx, config.ControlPlane.Architecture)
65+
if a, ok := streamArch.Artifacts["qemu"]; ok {
66+
u, err := rhcos.FindArtifactURL(a)
67+
if err != nil {
68+
return err
69+
}
70+
*i = BootstrapImage(u)
71+
return nil
72+
}
73+
return fmt.Errorf("%s: No qemu build found", st.FormatPrefix(archName))
5574
default:
5675
// other platforms use the same image for all nodes
57-
osimage, err = osImage(config)
58-
}
59-
if err != nil {
60-
return err
76+
u, err := osImage(config)
77+
if err != nil {
78+
return err
79+
}
80+
*i = BootstrapImage(u)
81+
return nil
6182
}
62-
*i = BootstrapImage(osimage)
63-
return nil
6483
}

pkg/asset/rhcos/image.go

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"os"
88
"time"
99

10-
"github.com/pkg/errors"
10+
"github.com/coreos/stream-metadata-go/arch"
1111
"github.com/sirupsen/logrus"
1212

1313
"github.com/openshift/installer/pkg/asset"
@@ -66,67 +66,95 @@ func (i *Image) Generate(p asset.Parents) error {
6666
}
6767

6868
func osImage(config *types.InstallConfig) (string, error) {
69-
arch := config.ControlPlane.Architecture
70-
71-
var osimage string
72-
var err error
7369
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
7470
defer cancel()
71+
72+
archName := arch.RpmArch(string(config.ControlPlane.Architecture))
73+
74+
st, err := rhcos.FetchCoreOSBuild(ctx)
75+
if err != nil {
76+
return "", err
77+
}
78+
streamArch, err := st.GetArchitecture(archName)
79+
if err != nil {
80+
return "", err
81+
}
7582
switch config.Platform.Name() {
7683
case aws.Name:
7784
if len(config.Platform.AWS.AMIID) > 0 {
78-
osimage = config.Platform.AWS.AMIID
79-
break
85+
return config.Platform.AWS.AMIID, nil
8086
}
8187
region := config.Platform.AWS.Region
8288
if !configaws.IsKnownRegion(config.Platform.AWS.Region) {
8389
region = "us-east-1"
8490
}
85-
osimage, err = rhcos.AMI(ctx, arch, region)
91+
osimage, err := st.GetAMI(archName, region)
92+
if err != nil {
93+
return "", err
94+
}
8695
if region != config.Platform.AWS.Region {
8796
osimage = fmt.Sprintf("%s,%s", osimage, region)
8897
}
98+
return osimage, nil
8999
case gcp.Name:
90-
osimage, err = rhcos.GCP(ctx, arch)
100+
if streamArch.Images.Gcp != nil {
101+
img := streamArch.Images.Gcp
102+
return fmt.Sprintf("projects/%s/global/images/%s", img.Project, img.Name), nil
103+
}
104+
return "", fmt.Errorf("%s: No GCP build found", st.FormatPrefix(archName))
91105
case libvirt.Name:
92-
osimage, err = rhcos.QEMU(ctx, arch)
93-
case openstack.Name:
94-
if oi := config.Platform.OpenStack.ClusterOSImage; oi != "" {
95-
osimage = oi
96-
break
106+
// 𝅘𝅥𝅮 Everything's going to be a-ok 𝅘𝅥𝅮
107+
if a, ok := streamArch.Artifacts["qemu"]; ok {
108+
return rhcos.FindArtifactURL(a)
109+
}
110+
return "", fmt.Errorf("%s: No qemu build found", st.FormatPrefix(archName))
111+
case ovirt.Name, kubevirt.Name, openstack.Name:
112+
op := config.Platform.OpenStack
113+
if op != nil {
114+
if oi := op.ClusterOSImage; oi != "" {
115+
return oi, nil
116+
}
117+
}
118+
if a, ok := streamArch.Artifacts["openstack"]; ok {
119+
return rhcos.FindArtifactURL(a)
97120
}
98-
osimage, err = rhcos.OpenStack(ctx, arch)
99-
case ovirt.Name:
100-
osimage, err = rhcos.OpenStack(ctx, arch)
101-
case kubevirt.Name:
102-
osimage, err = rhcos.OpenStack(ctx, arch)
121+
return "", fmt.Errorf("%s: No openstack build found", st.FormatPrefix(archName))
103122
case azure.Name:
104-
osimage, err = rhcos.VHD(ctx, arch)
123+
ext := streamArch.RHELCoreOSExtensions
124+
if ext == nil {
125+
return "", fmt.Errorf("%s: No azure build found", st.FormatPrefix(archName))
126+
}
127+
azd := ext.AzureDisk
128+
if azd == nil {
129+
return "", fmt.Errorf("%s: No azure build found", st.FormatPrefix(archName))
130+
}
131+
return azd.URL, nil
105132
case baremetal.Name:
106-
// Check for RHCOS image URL override
133+
// Check for image URL override
107134
if oi := config.Platform.BareMetal.ClusterOSImage; oi != "" {
108-
osimage = oi
109-
break
135+
return oi, nil
110136
}
111137

112138
// Note that baremetal IPI currently uses the OpenStack image
113139
// because this contains the necessary ironic config drive
114140
// ignition support, which isn't enabled in the UPI BM images
115-
osimage, err = rhcos.OpenStack(ctx, arch)
141+
if a, ok := streamArch.Artifacts["openstack"]; ok {
142+
return rhcos.FindArtifactURL(a)
143+
}
144+
return "", fmt.Errorf("%s: No openstack build found", st.FormatPrefix(archName))
116145
case vsphere.Name:
117-
// Check for RHCOS image URL override
146+
// Check for image URL override
118147
if config.Platform.VSphere.ClusterOSImage != "" {
119-
osimage = config.Platform.VSphere.ClusterOSImage
120-
break
148+
return config.Platform.VSphere.ClusterOSImage, nil
121149
}
122150

123-
osimage, err = rhcos.VMware(ctx, arch)
151+
if a, ok := streamArch.Artifacts["vmware"]; ok {
152+
return rhcos.FindArtifactURL(a)
153+
}
154+
return "", fmt.Errorf("%s: No vmware build found", st.FormatPrefix(archName))
124155
case none.Name:
156+
return "", nil
125157
default:
126-
return "", errors.New("invalid Platform")
127-
}
128-
if err != nil {
129-
return "", err
158+
return "", fmt.Errorf("invalid platform %v", config.Platform.Name())
130159
}
131-
return osimage, nil
132160
}

pkg/rhcos/ami.go

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)