github.com/openshift/installer@v1.4.17/pkg/asset/imagebased/image/baseiso.go (about)

     1  package image
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/coreos/stream-metadata-go/arch"
    10  	"github.com/coreos/stream-metadata-go/stream"
    11  	"github.com/sirupsen/logrus"
    12  
    13  	"github.com/openshift/installer/pkg/asset"
    14  	"github.com/openshift/installer/pkg/rhcos"
    15  	"github.com/openshift/installer/pkg/rhcos/cache"
    16  	"github.com/openshift/installer/pkg/types"
    17  )
    18  
    19  var (
    20  	defaultCoreOSStreamGetter = rhcos.FetchCoreOSBuild
    21  )
    22  
    23  // BaseIso generates the base ISO file for the image.
    24  type BaseIso struct {
    25  	File *asset.File
    26  
    27  	streamGetter CoreOSBuildFetcher
    28  }
    29  
    30  // CoreOSBuildFetcher will be to used to switch the source of the coreos metadata.
    31  type CoreOSBuildFetcher func(ctx context.Context) (*stream.Stream, error)
    32  
    33  var _ asset.WritableAsset = (*BaseIso)(nil)
    34  
    35  // Name returns the human-friendly name of the asset.
    36  func (i *BaseIso) Name() string {
    37  	return "BaseIso Image"
    38  }
    39  
    40  // Dependencies returns dependencies used by the asset.
    41  func (i *BaseIso) Dependencies() []asset.Asset {
    42  	return []asset.Asset{}
    43  }
    44  
    45  // Generate generates the base ISO.
    46  func (i *BaseIso) Generate(_ context.Context, dependencies asset.Parents) error {
    47  	var err error
    48  	var baseIsoFileName string
    49  
    50  	if urlOverride, ok := os.LookupEnv("OPENSHIFT_INSTALL_OS_IMAGE_OVERRIDE"); ok && urlOverride != "" {
    51  		logrus.Warn("Found override for OS Image. Please be warned, this is not advised.")
    52  		baseIsoFileName, err = cache.DownloadImageFile(urlOverride, cache.ImageBasedApplicationName)
    53  	} else {
    54  		if i.streamGetter == nil {
    55  			i.streamGetter = defaultCoreOSStreamGetter
    56  		}
    57  		// default to the amd64 architecture because the lifecycle-agent CLI is built only for amd64.
    58  		baseIsoFileName, err = i.downloadBaseIso(arch.RpmArch(types.ArchitectureAMD64))
    59  	}
    60  
    61  	if err == nil {
    62  		logrus.Debugf("Using base ISO image %s", baseIsoFileName)
    63  		i.File = &asset.File{Filename: baseIsoFileName}
    64  		return nil
    65  	}
    66  	logrus.Debugf("Failed to download base ISO: %s", err)
    67  
    68  	return fmt.Errorf("failed to get base ISO image: %w", err)
    69  }
    70  
    71  // Files returns the files generated by the asset.
    72  func (i *BaseIso) Files() []*asset.File {
    73  	if i.File != nil {
    74  		return []*asset.File{i.File}
    75  	}
    76  	return []*asset.File{}
    77  }
    78  
    79  // Load is not needed, as Generate uses the rhcos/cache to
    80  // either download the base ISO or return the one found in
    81  // the cache directory.
    82  func (i *BaseIso) Load(f asset.FileFetcher) (bool, error) {
    83  	return false, nil
    84  }
    85  
    86  // Download the RHCOS base ISO via rhcos.json.
    87  func (i *BaseIso) downloadBaseIso(archName string) (string, error) {
    88  	metal, err := i.metalArtifact(archName)
    89  	if err != nil {
    90  		return "", err
    91  	}
    92  
    93  	format, ok := metal.Formats["iso"]
    94  	if !ok {
    95  		return "", fmt.Errorf("no ISO found to download for %s: %w", archName, err)
    96  	}
    97  
    98  	url := format.Disk.Location
    99  	sha := format.Disk.Sha256
   100  	cachedImage, err := cache.DownloadImageFileWithSha(url, cache.ImageBasedApplicationName, sha)
   101  	if err != nil {
   102  		return "", fmt.Errorf("failed to download base ISO image %s: %w", url, err)
   103  	}
   104  
   105  	return cachedImage, nil
   106  }
   107  
   108  func (i *BaseIso) metalArtifact(archName string) (stream.PlatformArtifacts, error) {
   109  	ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
   110  	defer cancel()
   111  
   112  	st, err := i.streamGetter(ctx)
   113  	if err != nil {
   114  		return stream.PlatformArtifacts{}, err
   115  	}
   116  
   117  	streamArch, err := st.GetArchitecture(archName)
   118  	if err != nil {
   119  		return stream.PlatformArtifacts{}, err
   120  	}
   121  
   122  	metal, ok := streamArch.Artifacts["metal"]
   123  	if !ok {
   124  		return stream.PlatformArtifacts{}, fmt.Errorf("coreOs stream data not found for 'metal' artifact")
   125  	}
   126  
   127  	return metal, nil
   128  }