From 9dc1dfe627364395eed1daa62486bc81ca09da00 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 24 Sep 2021 17:41:04 -0400 Subject: [PATCH] testiso: add miniso-install scenario This is like `iso-install`, but exercises the minimal ISO workflow instead. Also, confusingly the install itself is offline, though it does need networking to fetch the rootfs. See comment block about this in `InstallViaISOEmbed`. --- mantle/cmd/kola/testiso.go | 26 +++++++++++++++++++++----- mantle/platform/metal.go | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/mantle/cmd/kola/testiso.go b/mantle/cmd/kola/testiso.go index 2851ec1c6b..52a71c46c0 100644 --- a/mantle/cmd/kola/testiso.go +++ b/mantle/cmd/kola/testiso.go @@ -70,6 +70,8 @@ const ( scenarioPXEInstall = "pxe-install" scenarioISOInstall = "iso-install" + scenarioMinISOInstall = "miniso-install" + scenarioPXEOfflineInstall = "pxe-offline-install" scenarioISOOfflineInstall = "iso-offline-install" @@ -82,6 +84,7 @@ var allScenarios = map[string]bool{ scenarioPXEOfflineInstall: true, scenarioISOInstall: true, scenarioISOOfflineInstall: true, + scenarioMinISOInstall: true, scenarioISOLiveLogin: true, scenarioISOAsDisk: true, } @@ -187,7 +190,8 @@ func init() { cmdTestIso.Flags().BoolVar(&console, "console", false, "Connect qemu console to terminal, turn off automatic initramfs failure checking") cmdTestIso.Flags().BoolVar(&pxeAppendRootfs, "pxe-append-rootfs", false, "Append rootfs to PXE initrd instead of fetching at runtime") cmdTestIso.Flags().StringSliceVar(&pxeKernelArgs, "pxe-kargs", nil, "Additional kernel arguments for PXE") - cmdTestIso.Flags().StringSliceVar(&scenarios, "scenarios", []string{scenarioPXEInstall, scenarioISOOfflineInstall, scenarioPXEOfflineInstall, scenarioISOLiveLogin, scenarioISOAsDisk}, fmt.Sprintf("Test scenarios (also available: %v)", []string{scenarioISOInstall})) + // XXX: add scenarioMinISOInstall to the default set once the feature is stable + cmdTestIso.Flags().StringSliceVar(&scenarios, "scenarios", []string{scenarioPXEInstall, scenarioISOOfflineInstall, scenarioPXEOfflineInstall, scenarioISOLiveLogin, scenarioISOAsDisk}, fmt.Sprintf("Test scenarios (also available: %v)", []string{scenarioISOInstall, scenarioMinISOInstall})) cmdTestIso.Args = cobra.ExactArgs(0) root.AddCommand(cmdTestIso) @@ -299,6 +303,7 @@ func runTestIso(cmd *cobra.Command, args []string) error { if noiso { delete(targetScenarios, scenarioISOInstall) delete(targetScenarios, scenarioISOOfflineInstall) + delete(targetScenarios, scenarioMinISOInstall) delete(targetScenarios, scenarioISOLiveLogin) } @@ -375,7 +380,7 @@ func runTestIso(cmd *cobra.Command, args []string) error { } ranTest = true instIso := baseInst // Pretend this is Rust and I wrote .copy() - if err := testLiveIso(ctx, instIso, filepath.Join(outputDir, scenarioISOInstall), false); err != nil { + if err := testLiveIso(ctx, instIso, filepath.Join(outputDir, scenarioISOInstall), false, false); err != nil { return errors.Wrapf(err, "scenario %s", scenarioISOInstall) } printSuccess(scenarioISOInstall) @@ -386,7 +391,7 @@ func runTestIso(cmd *cobra.Command, args []string) error { } ranTest = true instIso := baseInst // Pretend this is Rust and I wrote .copy() - if err := testLiveIso(ctx, instIso, filepath.Join(outputDir, scenarioISOOfflineInstall), true); err != nil { + if err := testLiveIso(ctx, instIso, filepath.Join(outputDir, scenarioISOOfflineInstall), true, false); err != nil { return errors.Wrapf(err, "scenario %s", scenarioISOOfflineInstall) } printSuccess(scenarioISOOfflineInstall) @@ -417,6 +422,17 @@ func runTestIso(cmd *cobra.Command, args []string) error { fmt.Printf("%s unsupported on %s; skipping\n", scenarioISOAsDisk, system.RpmArch()) } } + if _, ok := targetScenarios[scenarioMinISOInstall]; ok { + if kola.CosaBuild.Meta.BuildArtifacts.LiveIso == nil { + return fmt.Errorf("build %s has no live ISO", kola.CosaBuild.Meta.Name) + } + ranTest = true + instIso := baseInst // Pretend this is Rust and I wrote .copy() + if err := testLiveIso(ctx, instIso, filepath.Join(outputDir, scenarioMinISOInstall), false, true); err != nil { + return errors.Wrapf(err, "scenario %s", scenarioMinISOInstall) + } + printSuccess(scenarioMinISOInstall) + } if !ranTest { panic("Nothing was tested!") @@ -552,7 +568,7 @@ func testPXE(ctx context.Context, inst platform.Install, outdir string, offline return awaitCompletion(ctx, mach.QemuInst, outdir, completionChannel, mach.BootStartedErrorChannel, []string{liveOKSignal, signalCompleteString}) } -func testLiveIso(ctx context.Context, inst platform.Install, outdir string, offline bool) error { +func testLiveIso(ctx context.Context, inst platform.Install, outdir string, offline, minimal bool) error { tmpd, err := ioutil.TempDir("", "kola-testiso") if err != nil { return err @@ -589,7 +605,7 @@ func testLiveIso(ctx context.Context, inst platform.Install, outdir string, offl targetConfig.AddSystemdUnit("coreos-test-installer-multipathed.service", multipathedRoot, conf.Enable) } - mach, err := inst.InstallViaISOEmbed(nil, liveConfig, targetConfig, outdir, offline) + mach, err := inst.InstallViaISOEmbed(nil, liveConfig, targetConfig, outdir, offline, minimal) if err != nil { return errors.Wrapf(err, "running iso install") } diff --git a/mantle/platform/metal.go b/mantle/platform/metal.go index be77226e4d..837eaf94e5 100644 --- a/mantle/platform/metal.go +++ b/mantle/platform/metal.go @@ -541,7 +541,7 @@ func (inst *Install) runPXE(kern *kernelSetup, offline bool) (*InstalledMachine, return &instmachine, nil } -func (inst *Install) InstallViaISOEmbed(kargs []string, liveIgnition, targetIgnition conf.Conf, outdir string, offline bool) (*InstalledMachine, error) { +func (inst *Install) InstallViaISOEmbed(kargs []string, liveIgnition, targetIgnition conf.Conf, outdir string, offline, minimal bool) (*InstalledMachine, error) { if !inst.Native4k && inst.CosaBuild.Meta.BuildArtifacts.Metal == nil { return nil, fmt.Errorf("Build %s must have a `metal` artifact", inst.CosaBuild.Meta.OstreeVersion) } else if inst.Native4k && inst.CosaBuild.Meta.BuildArtifacts.Metal4KNative == nil { @@ -550,6 +550,9 @@ func (inst *Install) InstallViaISOEmbed(kargs []string, liveIgnition, targetIgni if inst.CosaBuild.Meta.BuildArtifacts.LiveIso == nil { return nil, fmt.Errorf("Build %s must have a live ISO", inst.CosaBuild.Meta.Name) } + if minimal && offline { // ideally this'd be one enum parameter + panic("Can't run minimal install offline") + } // XXX: we do support this now, via `coreos-installer iso kargs` if len(inst.kargs) > 0 { @@ -623,7 +626,34 @@ func (inst *Install) InstallViaISOEmbed(kargs []string, liveIgnition, targetIgni http.Serve(listener, mux) }() baseurl := fmt.Sprintf("http://%s:%d", defaultQemuHostIPv4, port) - srcOpt = fmt.Sprintf("--image-url %s/%s", baseurl, metalname) + + // This is subtle but: for the minimal case, while we need networking to fetch the + // rootfs, the primary install flow will still rely on osmet. So let's keep srcOpt + // as "" to exercise that path. In the future, this could be a separate scenario + // (likely we should drop the "offline" naming and have a "remote" tag on the + // opposite scenarios instead which fetch the metal image, so then we'd have + // "[min]iso-install" and "[min]iso-remote-install"). + if !minimal { + srcOpt = fmt.Sprintf("--image-url %s/%s", baseurl, metalname) + } + + if minimal { + minisopath := filepath.Join(tempdir, "minimal.iso") + // This is obviously also available in the build dir, but to be realistic, + // let's take it from --rootfs-output + rootfs_path := filepath.Join(tempdir, "rootfs.img") + // Ideally we'd use the coreos-installer of the target build here, because it's part + // of the test workflow, but that's complex... Sadly, probably easiest is to spin up + // a VM just to get the minimal ISO. + cmd := exec.Command("coreos-installer", "iso", "extract", "minimal-iso", srcisopath, + "--output", minisopath, "--rootfs-output", rootfs_path, + "--rootfs-url", baseurl+"/rootfs.img") + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return nil, errors.Wrapf(err, "running coreos-installer iso extract minimal") + } + srcisopath = minisopath + } // In this case; the target config is jut a tiny wrapper that wants to // fetch our hosted target.ign config