Skip to content

Commit

Permalink
qemu: Support monitoring for failures in the initramfs
Browse files Browse the repository at this point in the history
Pairs with coreos/ignition-dracut#146

What we really want is to use this in kola, will do as a
separate followup.
  • Loading branch information
cgwalters committed Mar 26, 2020
1 parent c2759d6 commit 8fed2af
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 5 deletions.
18 changes: 13 additions & 5 deletions mantle/cmd/kola/qemuexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ var (

ignitionFragments []string

forceConfigInjection bool
forceConfigInjection bool
propagateInitramfsFailure bool
)

func init() {
Expand All @@ -65,6 +66,8 @@ func init() {
cmdQemuExec.Flags().IntVarP(&memory, "memory", "m", 0, "Memory in MB")
cmdQemuExec.Flags().StringVarP(&ignition, "ignition", "i", "", "Path to ignition config")
cmdQemuExec.Flags().BoolVarP(&forceConfigInjection, "inject-ignition", "", false, "Force injecting Ignition config using guestfs")
cmdQemuExec.Flags().BoolVar(&propagateInitramfsFailure, "propagate-initramfs-failure", false, "Error out if the system fails in the initramfs")

}

func renderFragments() (string, error) {
Expand Down Expand Up @@ -187,8 +190,13 @@ func runQemuExec(cmd *cobra.Command, args []string) error {
return err
}

// Ignore errors
_ = inst.Wait()

return nil
if propagateInitramfsFailure {
err = inst.WaitAll()
if err != nil {
return err
}
return nil
} else {
return inst.Wait()
}
}
61 changes: 61 additions & 0 deletions mantle/platform/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package platform

import (
"bufio"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -47,6 +48,8 @@ type QemuInstance struct {
qemu exec.Cmd
swtpmTmpd string
swtpm exec.Cmd

JournalPipe os.File
}

func (inst *QemuInstance) Pid() int {
Expand Down Expand Up @@ -111,10 +114,57 @@ func (inst *QemuInstance) SSHAddress() (string, error) {
return "", fmt.Errorf("didn't find an address")
}

// Wait for the qemu process to exit
func (inst *QemuInstance) Wait() error {
return inst.qemu.Wait()
}

// WaitIgnitionError will only return if the instance
// failed inside the initramfs. The resulting string will
// be a newline-delimited stream of JSON strings, as returned
// by `journalctl -o json`.
func (inst *QemuInstance) WaitIgnitionError() (string, error) {
b := bufio.NewReaderSize(&inst.JournalPipe, 64768)
var r strings.Builder
iscorrupted := false
for {
line, prefix, err := b.ReadLine()
if err != nil {
return r.String(), errors.Wrapf(err, "Reading from journal channel")
}
if prefix {
iscorrupted = true
}
if string(line) == "{}" {
break
}
r.Write(line)
}
if iscorrupted {
return r.String(), fmt.Errorf("journal was truncated due to overly long line")
}
return r.String(), nil
}

// WaitAll wraps the process exit as well as WaitIgnitionError,
// returning an error if either fail.
func (inst *QemuInstance) WaitAll() error {
c := make(chan error)
go func() {
_, err := inst.WaitIgnitionError()
// TODO parse buf and try to nicely render something
if err != nil {
c <- err
} else {
c <- fmt.Errorf("instance failed in the initramfs")
}
}()
go func() {
c <- inst.Wait()
}()
return <-c
}

func (inst *QemuInstance) Destroy() {
if inst.qemu != nil {
if err := inst.qemu.Kill(); err != nil {
Expand Down Expand Up @@ -689,6 +739,17 @@ func (builder *QemuBuilder) Exec() (*QemuInstance, error) {
"-tpmdev", "emulator,id=tpm0,chardev=chrtpm", "-device", "tpm-tis,tpmdev=tpm0")
}

// Set up the virtio channel to get Ignition failures by default
journalPipeR, journalPipeW, err := os.Pipe()
if err != nil {
return nil, errors.Wrapf(err, "creating journal pipe")
}
inst.JournalPipe = *journalPipeR
argv = append(argv, "-device", "virtio-serial")
// https://www.redhat.com/archives/libvir-list/2015-December/msg00305.html
argv = append(argv, "-chardev", fmt.Sprintf("file,id=ignition-dracut,path=%s,append=on", builder.AddFd(journalPipeW)))
argv = append(argv, "-device", "virtserialport,chardev=ignition-dracut,name=com.coreos.ignition.journal")

fdnum := 3 // first additional file starts at position 3
for i, _ := range builder.fds {
fdset := i + 1 // Start at 1
Expand Down

0 comments on commit 8fed2af

Please sign in to comment.