Skip to content

Commit d386900

Browse files
kola: refactor iso.pxe* tests
1 parent 9d9ca44 commit d386900

8 files changed

Lines changed: 456 additions & 841 deletions

File tree

mantle/kola/tests/iso/common.go

Lines changed: 64 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,34 @@ import (
66
"io"
77
"os"
88
"path/filepath"
9-
"strconv"
109
"strings"
1110
"time"
1211

1312
"github.com/coreos/coreos-assembler/mantle/kola"
1413
"github.com/coreos/coreos-assembler/mantle/kola/cluster"
1514
"github.com/coreos/coreos-assembler/mantle/kola/register"
16-
"github.com/coreos/coreos-assembler/mantle/platform"
17-
"github.com/coreos/coreos-assembler/mantle/platform/conf"
18-
"github.com/coreos/coreos-assembler/mantle/platform/machine/qemu"
19-
coreosarch "github.com/coreos/stream-metadata-go/arch"
2015
"github.com/pkg/errors"
2116
)
2217

2318
const (
2419
installTimeoutMins = 12
20+
21+
// defaultQemuHostIPv4 is documented in `man qemu-kvm`, under the `-netdev` option
22+
defaultQemuHostIPv4 = "10.0.2.2"
2523
)
2624

25+
// This object gets serialized to YAML and fed to coreos-installer:
26+
// https://coreos.github.io/coreos-installer/customizing-install/#config-file-format
27+
type CoreosInstallerConfig struct {
28+
ImageURL string `yaml:"image-url,omitempty"`
29+
IgnitionFile string `yaml:"ignition-file,omitempty"`
30+
Insecure bool `yaml:"insecure,omitempty"`
31+
AppendKargs []string `yaml:"append-karg,omitempty"`
32+
CopyNetwork bool `yaml:"copy-network,omitempty"`
33+
DestDevice string `yaml:"dest-device,omitempty"`
34+
Console []string `yaml:"console,omitempty"`
35+
}
36+
2737
type IsoTestOpts struct {
2838
// Flags().BoolVarP(&instInsecure, "inst-insecure", "S", false, "Do not verify signature on metal image")
2939
instInsecure bool
@@ -62,114 +72,7 @@ func isoTest(name string, run func(c cluster.TestCluster), arch []string) *regis
6272
}
6373
}
6474

65-
func newBaseQemuBuilder(opts IsoTestOpts, outdir string) (*platform.QemuBuilder, error) {
66-
builder := qemu.NewMetalQemuBuilderDefault()
67-
if opts.enableUefiSecure {
68-
builder.Firmware = "uefi-secure"
69-
} else if opts.enableUefi {
70-
builder.Firmware = "uefi"
71-
}
72-
73-
if err := os.MkdirAll(outdir, 0755); err != nil {
74-
return nil, err
75-
}
76-
77-
builder.InheritConsole = opts.console
78-
if !opts.console {
79-
builder.ConsoleFile = filepath.Join(outdir, "console.txt")
80-
}
81-
82-
if kola.QEMUOptions.Memory != "" {
83-
parsedMem, err := strconv.ParseInt(kola.QEMUOptions.Memory, 10, 32)
84-
if err != nil {
85-
return nil, err
86-
}
87-
builder.MemoryMiB = int(parsedMem)
88-
}
89-
90-
// increase the memory for pxe tests with appended rootfs in the initrd
91-
// we were bumping up into the 4GiB limit in RHCOS/c9s
92-
// pxe-offline-install.rootfs-appended.bios tests
93-
if opts.pxeAppendRootfs && builder.MemoryMiB < 5120 {
94-
builder.MemoryMiB = 5120
95-
}
96-
97-
return builder, nil
98-
}
99-
100-
func newQemuBuilder(opts IsoTestOpts, outdir string) (*platform.QemuBuilder, *conf.Conf, error) {
101-
builder, err := newBaseQemuBuilder(opts, outdir)
102-
if err != nil {
103-
return nil, nil, err
104-
}
105-
106-
config, err := conf.EmptyIgnition().Render(conf.FailWarnings)
107-
if err != nil {
108-
return nil, nil, err
109-
}
110-
111-
err = forwardJournal(outdir, builder, config)
112-
if err != nil {
113-
return nil, nil, err
114-
}
115-
116-
return builder, config, nil
117-
}
118-
119-
func forwardJournal(outdir string, builder *platform.QemuBuilder, config *conf.Conf) error {
120-
journalPipe, err := builder.VirtioJournal(config, "")
121-
if err != nil {
122-
return err
123-
}
124-
journalOut, err := os.OpenFile(filepath.Join(outdir, "journal.txt"), os.O_WRONLY|os.O_CREATE, 0644)
125-
if err != nil {
126-
return err
127-
}
128-
129-
go func() {
130-
_, err := io.Copy(journalOut, journalPipe)
131-
if err != nil && err != io.EOF {
132-
fmt.Printf("error copying journal: %v\n", err)
133-
}
134-
}()
135-
136-
return nil
137-
}
138-
139-
func newQemuBuilderWithDisk(opts IsoTestOpts, outdir string) (*platform.QemuBuilder, *conf.Conf, error) {
140-
builder, config, err := newQemuBuilder(opts, outdir)
141-
142-
if err != nil {
143-
return nil, nil, err
144-
}
145-
146-
sectorSize := 0
147-
if opts.enable4k {
148-
sectorSize = 4096
149-
}
150-
151-
disk := platform.Disk{
152-
Size: "12G", // Arbitrary
153-
SectorSize: sectorSize,
154-
MultiPathDisk: opts.enableMultipath,
155-
}
156-
157-
//TBD: see if we can remove this and just use AddDisk and inject bootindex during startup
158-
if coreosarch.CurrentRpmArch() == "s390x" || coreosarch.CurrentRpmArch() == "aarch64" {
159-
// s390x and aarch64 need to use bootindex as they don't support boot once
160-
if err := builder.AddDisk(&disk); err != nil {
161-
return nil, nil, err
162-
}
163-
} else {
164-
if err := builder.AddPrimaryDisk(&disk); err != nil {
165-
return nil, nil, err
166-
}
167-
}
168-
169-
return builder, config, nil
170-
}
171-
172-
func CheckTestOutput(output *os.File, expected []string) error {
75+
func checkTestOutput(output *os.File, expected []string) error {
17376
reader := bufio.NewReader(output)
17477
for _, exp := range expected {
17578
line, err := reader.ReadString('\n')
@@ -192,8 +95,11 @@ func CheckTestOutput(output *os.File, expected []string) error {
19295
return nil
19396
}
19497

195-
func EnsureLiveArtifactsExist() error {
196-
if kola.CosaBuild.Meta.BuildArtifacts.LiveIso == nil || kola.CosaBuild.Meta.BuildArtifacts.LiveKernel == nil {
98+
func ensureLiveArtifactsExist() error {
99+
if kola.CosaBuild.Meta.BuildArtifacts.LiveIso == nil {
100+
return errors.Errorf("Build %s is missing live-iso artifacts\n", kola.CosaBuild.Meta.Name)
101+
}
102+
if kola.CosaBuild.Meta.BuildArtifacts.LiveRootfs == nil || kola.CosaBuild.Meta.BuildArtifacts.LiveKernel == nil || kola.CosaBuild.Meta.BuildArtifacts.LiveInitramfs == nil {
197103
return errors.Errorf("Build %s is missing live artifacts\n", kola.CosaBuild.Meta.Name)
198104
}
199105
if kola.CosaBuild.Meta.BuildArtifacts.Metal == nil || kola.CosaBuild.Meta.BuildArtifacts.Metal4KNative == nil {
@@ -202,59 +108,54 @@ func EnsureLiveArtifactsExist() error {
202108
return nil
203109
}
204110

205-
func awaitCompletion(c cluster.TestCluster, inst *platform.QemuInstance, console bool, outdir string, qchan *os.File, booterrchan chan error, expected []string) error {
206-
ctx := c.Context()
111+
// Sometimes the logs that stream from various virtio streams can be
112+
// incomplete because they depend on services inside the guest.
113+
// When you are debugging earlyboot/initramfs issues this can be
114+
// problematic. Let's add a hook here to enable more debugging.
115+
func renderCosaTestIsoDebugKargs() []string {
116+
if _, ok := os.LookupEnv("COSA_TESTISO_DEBUG"); ok {
117+
return []string{"systemd.log_color=0", "systemd.log_level=debug",
118+
"systemd.journald.forward_to_console=1",
119+
"systemd.journald.max_level_console=debug"}
120+
} else {
121+
return []string{}
122+
}
123+
}
124+
125+
func absSymlink(src, dest string) error {
126+
src, err := filepath.Abs(src)
127+
if err != nil {
128+
return err
129+
}
130+
return os.Symlink(src, dest)
131+
}
207132

208-
errchan := make(chan error)
209-
go func() {
210-
timeout := (time.Duration(installTimeoutMins*(100+kola.Options.ExtendTimeoutPercent)) * time.Minute) / 100
211-
time.Sleep(timeout)
212-
errchan <- fmt.Errorf("timed out after %v", timeout)
213-
}()
214-
if !console {
215-
go func() {
216-
errBuf, err := inst.WaitIgnitionError(ctx)
217-
if err == nil {
218-
if errBuf != "" {
219-
c.Logf("entered emergency.target in initramfs")
220-
path := filepath.Join(outdir, "ignition-virtio-dump.txt")
221-
if err := os.WriteFile(path, []byte(errBuf), 0644); err != nil {
222-
c.Errorf("Failed to write journal: %v", err)
223-
}
224-
err = platform.ErrInitramfsEmergency
225-
}
226-
}
227-
if err != nil {
228-
errchan <- err
229-
}
230-
}()
133+
// setupMetalImage creates a symlink to the metal image.
134+
func setupMetalImage(builddir, metalimg, destdir string) (string, error) {
135+
if err := absSymlink(filepath.Join(builddir, metalimg), filepath.Join(destdir, metalimg)); err != nil {
136+
return "", err
231137
}
232-
go func() {
233-
err := inst.Wait()
234-
// only one Wait() gets process data, so also manually check for signal
235-
//plog.Debugf("qemu exited err=%v", err)
236-
if err == nil && inst.Signaled() {
237-
err = errors.New("process killed")
238-
}
138+
return metalimg, nil
139+
}
140+
141+
func cat(outfile string, infiles ...string) error {
142+
out, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE, 0644)
143+
if err != nil {
144+
return err
145+
}
146+
defer out.Close()
147+
for _, infile := range infiles {
148+
in, err := os.Open(infile)
239149
if err != nil {
240-
errchan <- errors.Wrapf(err, "QEMU unexpectedly exited while awaiting completion")
150+
return err
241151
}
242-
time.Sleep(1 * time.Minute)
243-
errchan <- fmt.Errorf("QEMU exited; timed out waiting for completion")
244-
}()
245-
go func() {
246-
errchan <- CheckTestOutput(qchan, expected)
247-
}()
248-
go func() {
249-
//check for error when switching boot order
250-
if booterrchan != nil {
251-
if err := <-booterrchan; err != nil {
252-
errchan <- err
253-
}
152+
defer in.Close()
153+
_, err = io.Copy(out, in)
154+
if err != nil {
155+
return err
254156
}
255-
}()
256-
err := <-errchan
257-
return err
157+
}
158+
return nil
258159
}
259160

260161
var liveOKSignal = "live-test-OK"

mantle/kola/tests/iso/live-as-disk.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func isoAsDiskUefiSecure(c cluster.TestCluster) {
4343
}
4444

4545
func isoTestAsDisk(c cluster.TestCluster, opts IsoTestOpts) {
46-
if err := EnsureLiveArtifactsExist(); err != nil {
46+
if err := ensureLiveArtifactsExist(); err != nil {
4747
fmt.Println(err)
4848
return
4949
}
@@ -84,7 +84,7 @@ func isoTestAsDisk(c cluster.TestCluster, opts IsoTestOpts) {
8484

8585
// Read line in a goroutine and send errors to channel
8686
go func() {
87-
errchan <- CheckTestOutput(output, []string{liveOKSignal})
87+
errchan <- checkTestOutput(output, []string{liveOKSignal})
8888
}()
8989

9090
isopath := filepath.Join(kola.CosaBuild.Dir, kola.CosaBuild.Meta.BuildArtifacts.LiveIso.Path)

mantle/kola/tests/iso/live-fips.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ ExecStart=grep FIPS etc/crypto-policies/config
4040
RequiredBy=fips-signal-ok.service`
4141

4242
func testLiveFIPS(c cluster.TestCluster) {
43-
if err := EnsureLiveArtifactsExist(); err != nil {
43+
if err := ensureLiveArtifactsExist(); err != nil {
4444
fmt.Println(err)
4545
return
4646
}
@@ -81,7 +81,7 @@ func testLiveFIPS(c cluster.TestCluster) {
8181

8282
// Read line in a goroutine and send errors to channel
8383
go func() {
84-
errchan <- CheckTestOutput(output, []string{liveOKSignal})
84+
errchan <- checkTestOutput(output, []string{liveOKSignal})
8585
}()
8686

8787
isopath := filepath.Join(kola.CosaBuild.Dir, kola.CosaBuild.Meta.BuildArtifacts.LiveIso.Path)

mantle/kola/tests/iso/live-iscsi.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ var iscsi_butane_config string
8989
// - when the system is booted, write a success string to /dev/virtio-ports/testisocompletion
9090
// - as this serial device is mapped to the host serial device, the test concludes
9191
func isoInstalliScsi(c cluster.TestCluster, opts IsoTestOpts) {
92-
if err := EnsureLiveArtifactsExist(); err != nil {
92+
if err := ensureLiveArtifactsExist(); err != nil {
9393
fmt.Println(err)
9494
return
9595
}
@@ -173,7 +173,7 @@ func isoInstalliScsi(c cluster.TestCluster, opts IsoTestOpts) {
173173

174174
// Read line in a goroutine and send errors to channel
175175
go func() {
176-
errchan <- CheckTestOutput(output, []string{"iscsi-boot-ok"})
176+
errchan <- checkTestOutput(output, []string{"iscsi-boot-ok"})
177177
}()
178178

179179
return nil

0 commit comments

Comments
 (0)