Skip to content
This repository has been archived by the owner on May 7, 2021. It is now read-only.

Commit

Permalink
platform/qemu: enable console logging in CL images by default
Browse files Browse the repository at this point in the history
Move the old "kola mkimage" functionality into flight and run it by
default on CL.
  • Loading branch information
bgilbert committed Nov 5, 2018
1 parent 90faf14 commit bec530c
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 24 deletions.
1 change: 1 addition & 0 deletions cmd/kola/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func init() {
sv(&kola.QEMUOptions.Board, "board", defaultTargetBoard, "target board")
sv(&kola.QEMUOptions.DiskImage, "qemu-image", "", "path to CoreOS disk image")
sv(&kola.QEMUOptions.BIOSImage, "qemu-bios", "", "BIOS to use for QEMU vm")
bv(&kola.QEMUOptions.UseVanillaImage, "qemu-skip-mangle", false, "don't modify CL disk image to capture console log")
}

// Sync up the command line options if there is dependency
Expand Down
2 changes: 1 addition & 1 deletion platform/machine/qemu/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (qc *Cluster) NewMachineWithOptions(userdata *conf.UserData, options Machin

allDisks := append([]Disk{
{
BackingFile: qc.flight.opts.DiskImage,
BackingFile: qc.flight.diskImagePath,
DeviceOpts: primaryDiskOptions,
},
}, options.AdditionalDisks...)
Expand Down
54 changes: 33 additions & 21 deletions platform/machine/qemu/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,23 @@ var (
primaryDiskOptions = []string{"serial=primary-disk"}
)

// Copy input image to output and specialize output for running kola tests.
// Copy Container Linux input image and specialize copy for running kola tests.
// Return FD to the copy, which is a deleted file.
// This is not mandatory; the tests will do their best without it.
func MakeDiskTemplate(inputPath, outputPath string) (result error) {
func makeCLDiskTemplate(inputPath string) (output *os.File, result error) {
seterr := func(err error) {
if result == nil {
result = err
}
}

// create output file
outputPath, err := mkpath("/var/tmp")
if err != nil {
return nil, err
}
defer os.Remove(outputPath)

// copy file
// cp is used since it supports sparse and reflink.
cp := exec.Command("cp", "--force",
Expand All @@ -56,18 +64,13 @@ func MakeDiskTemplate(inputPath, outputPath string) (result error) {
cp.Stdout = os.Stdout
cp.Stderr = os.Stderr
if err := cp.Run(); err != nil {
return fmt.Errorf("copying file: %v", err)
return nil, fmt.Errorf("copying file: %v", err)
}
defer func() {
if result != nil {
os.Remove(outputPath)
}
}()

// create mount point
tmpdir, err := ioutil.TempDir("", "kola-qemu-")
if err != nil {
return fmt.Errorf("making temporary directory: %v", err)
return nil, fmt.Errorf("making temporary directory: %v", err)
}
defer func() {
if err := os.Remove(tmpdir); err != nil {
Expand All @@ -79,19 +82,19 @@ func MakeDiskTemplate(inputPath, outputPath string) (result error) {
cmd := exec.Command("losetup", "-Pf", "--show", outputPath)
stdout, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("getting stdout pipe: %v", err)
return nil, fmt.Errorf("getting stdout pipe: %v", err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
return fmt.Errorf("running losetup: %v", err)
return nil, fmt.Errorf("running losetup: %v", err)
}
buf, err := ioutil.ReadAll(stdout)
if err != nil {
cmd.Wait()
return fmt.Errorf("reading losetup output: %v", err)
return nil, fmt.Errorf("reading losetup output: %v", err)
}
if err := cmd.Wait(); err != nil {
return fmt.Errorf("setting up loop device: %v", err)
return nil, fmt.Errorf("setting up loop device: %v", err)
}
loopdev := strings.TrimSpace(string(buf))
defer func() {
Expand All @@ -109,12 +112,12 @@ func MakeDiskTemplate(inputPath, outputPath string) (result error) {
return fmt.Errorf("timed out waiting for device node; did you specify a qcow image by mistake?")
})
if err != nil {
return err
return nil, err
}

// mount OEM partition
if err := exec.Command("mount", oemdev, tmpdir).Run(); err != nil {
return fmt.Errorf("mounting OEM partition %s on %s: %v", oemdev, tmpdir, err)
return nil, fmt.Errorf("mounting OEM partition %s on %s: %v", oemdev, tmpdir, err)
}
defer func() {
if err := exec.Command("umount", tmpdir).Run(); err != nil {
Expand All @@ -125,13 +128,18 @@ func MakeDiskTemplate(inputPath, outputPath string) (result error) {
// write console settings to grub.cfg
f, err := os.OpenFile(filepath.Join(tmpdir, "grub.cfg"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return fmt.Errorf("opening grub.cfg: %v", err)
return nil, fmt.Errorf("opening grub.cfg: %v", err)
}
defer f.Close()
if _, err = f.WriteString("set linux_console=\"console=ttyS0,115200\"\n"); err != nil {
return fmt.Errorf("writing grub.cfg: %v", err)
return nil, fmt.Errorf("writing grub.cfg: %v", err)
}

// return fd to output file
output, err = os.Open(outputPath)
if err != nil {
return nil, fmt.Errorf("opening %v: %v", outputPath, err)
}
return
}

Expand Down Expand Up @@ -164,10 +172,14 @@ func setupDiskFromFile(imageFile string) (*os.File, error) {
if err != nil {
return nil, err
}
// keep the COW image from breaking if the "latest" symlink changes
backingFile, err = filepath.EvalSymlinks(backingFile)
if err != nil {
return nil, err
// Keep the COW image from breaking if the "latest" symlink changes.
// Ignore /proc/*/fd/* paths, since they look like symlinks but
// really aren't.
if !strings.HasPrefix(backingFile, "/proc/") {
backingFile, err = filepath.EvalSymlinks(backingFile)
if err != nil {
return nil, err
}
}

qcowOpts := fmt.Sprintf("backing_file=%s,lazy_refcounts=on", backingFile)
Expand Down
35 changes: 33 additions & 2 deletions platform/machine/qemu/flight.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
package qemu

import (
"fmt"
"os"

"github.com/coreos/pkg/capnslog"

"github.com/coreos/mantle/platform"
Expand All @@ -36,12 +39,18 @@ type Options struct {
// It can be a plain name, or a full path.
BIOSImage string

// Don't modify CL disk images to add console logging
UseVanillaImage bool

*platform.Options
}

type flight struct {
*local.LocalFlight
opts *Options

diskImagePath string
diskImageFile *os.File
}

var (
Expand All @@ -55,8 +64,23 @@ func NewFlight(opts *Options) (platform.Flight, error) {
}

qf := &flight{
LocalFlight: lf,
opts: opts,
LocalFlight: lf,
opts: opts,
diskImagePath: opts.DiskImage,
}

if opts.Distribution == "cl" && !opts.UseVanillaImage {
plog.Debug("enabling console logging in base disk")
qf.diskImageFile, err = makeCLDiskTemplate(opts.DiskImage)
if err != nil {
qf.Destroy()
return nil, err
}
// The template file has already been deleted, ensuring that
// it will be cleaned up on exit. Use a path to it that
// will remain stable for the lifetime of the flight without
// extra effort to pass FDs to subprocesses.
qf.diskImagePath = fmt.Sprintf("/proc/%d/fd/%d", os.Getpid(), qf.diskImageFile.Fd())
}

return qf, nil
Expand All @@ -79,3 +103,10 @@ func (qf *flight) NewCluster(rconf *platform.RuntimeConfig) (platform.Cluster, e

return qc, nil
}

func (qf *flight) Destroy() {
qf.LocalFlight.Destroy()
if qf.diskImageFile != nil {
qf.diskImageFile.Close()
}
}

0 comments on commit bec530c

Please sign in to comment.