Documentation
¶
Overview ¶
Package qemu provides a Go API for starting QEMU VMs.
qemu is mainly suitable for running QEMU-based integration tests.
The environment variable `VMTEST_QEMU` overrides the path to QEMU and the first few arguments. For example:
VMTEST_QEMU='qemu-system-x86_64 -L . -m 4096 -enable-kvm'
Other environment variables:
VMTEST_ARCH (used when Arch is empty or ArchUseEnvv is set) VMTEST_QEMU_APPEND (always added to QEMU arguments) VMTEST_KERNEL (used when Options.Kernel is empty) VMTEST_KERNEL_APPEND (always added to kernel args) VMTEST_INITRAMFS (used when Options.Initramfs is empty) VMTEST_TIMEOUT (used when Options.VMTimeout is empty)
Index ¶
- Variables
- func SkipIfNotArch(tb testing.TB, allowed ...Arch)
- func SkipWithoutQEMU(tb testing.TB)
- type Arch
- type Fn
- func All(fn ...Fn) Fn
- func ArbitraryArgs(aa ...string) Fn
- func ByArch(m map[Arch]Fn) Fn
- func HaltOnKernelPanic() Fn
- func IDEBlockDevice(file string) Fn
- func IfArch(arch Arch, fn Fn) Fn
- func IfNotArch(arch Arch, fn Fn) Fn
- func LogSerialByLine(callback LinePrinter) Fn
- func P9BootDirectory(dir string) Fn
- func P9Directory(dir string, tag string) Fn
- func ReadOnlyDirectory(dir string) Fn
- func VirtioRandom() Fn
- func WithAppendKernel(args ...string) Fn
- func WithInitramfs(initramfs string) Fn
- func WithKernel(kernel string) Fn
- func WithQEMUArgs(aa ...string) Fn
- func WithQEMUCommand(cmd string) Fn
- func WithSerialOutput(w ...io.WriteCloser) Fn
- func WithTask(t ...Task) Fn
- func WithVMTimeout(timeout time.Duration) Fn
- func WithVmtestIdent() Fn
- type IDAllocator
- type LinePrinter
- func DefaultPrint(prefix string, printer func(fmt string, arg ...any)) LinePrinter
- func Prefix(prefix string, printer LinePrinter) LinePrinter
- func PrintLine(printer func(fmt string, arg ...any)) LinePrinter
- func RelativeTS(printer LinePrinter) LinePrinter
- func TS(format string, printer LinePrinter) LinePrinter
- type Notifications
- type Options
- type Task
- type VM
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidDir = errors.New("no directory specified")
ErrInvalidDir is used when no directory is specified for file sharing.
var ErrInvalidTag = errors.New("no tag specified for 9P file system")
ErrInvalidTag is used when no tag is specified for 9P file system sharing.
var ErrInvalidTimeout = errors.New("could not parse VMTEST_TIMEOUT")
ErrInvalidTimeout is returned when VMTEST_TIMEOUT could not be parsed.
var ErrIsNotDir = errors.New("file system sharing requires directory")
ErrIsNotDir is used when the directory specified for file sharing is not a directory.
var ErrKernelRequiredForArgs = errors.New("KernelArgs can only be used when Kernel is also specified due to how QEMU bootloader works")
ErrKernelRequiredForArgs is returned when KernelArgs is populated but Kernel is empty.
var ErrUnsupportedArch = errors.New("unsupported guest architecture specified -- guest arch is required to decide some QEMU command-line arguments")
ErrUnsupportedArch is returned when an unsupported guest architecture value is used.
var SupportedArches = []Arch{ ArchAMD64, ArchI386, ArchArm64, ArchArm, ArchRiscv64, }
SupportedArches are the supported guest architecture values.
Functions ¶
func SkipIfNotArch ¶
SkipIfNotArch skips this test if GuestArch() (which is either VMTEST_ARCH or runtime.GOARCH) is not one of the given values.
func SkipWithoutQEMU ¶
SkipWithoutQEMU skips the test when the QEMU environment variable is not set.
Types ¶
type Arch ¶
type Arch string
Arch is the QEMU guest architecture.
const ( // ArchUseEnvv will derive the architecture from the VMTEST_ARCH env var. ArchUseEnvv Arch = "" // ArchAMD64 is the x86 64bit architecture. ArchAMD64 Arch = "amd64" // ArchI386 is the x86 32bit architecture. ArchI386 Arch = "i386" // ArchArm64 is the aarch64 architecture. ArchArm64 Arch = "arm64" // ArchArm is the arm 32bit architecture. ArchArm Arch = "arm" // ArchRiscv64 is the riscv 64bit architecture. ArchRiscv64 Arch = "riscv64" )
Architecture values are derived from GOARCH values.
type Fn ¶
type Fn func(*IDAllocator, *Options) error
Fn is a QEMU configuration option supplied to Start or OptionsFor.
Fns rely on a QEMU architecture already having been determined.
func All ¶
All applies all given configurators in order. If an error occurs, it returns the error early.
func ArbitraryArgs ¶
ArbitraryArgs adds arbitrary arguments to the QEMU command line.
func HaltOnKernelPanic ¶
func HaltOnKernelPanic() Fn
HaltOnKernelPanic passes args to QEMU and kernel to halt when the kernel panics.
Linux's default behavior is to hang forever, which is not great test behavior.
func IDEBlockDevice ¶
IDEBlockDevice emulates an AHCI/IDE block device.
func LogSerialByLine ¶
func LogSerialByLine(callback LinePrinter) Fn
LogSerialByLine processes serial output from the guest one line at a time and calls callback on each full line.
func P9BootDirectory ¶
P9BootDirectory adds QEMU args that expose a directory as a Plan9 (9p) read-write filesystem in the VM as the boot device.
The directory will be used as the root volume. There can only be one boot 9pfs at a time. The tag used will be /dev/root, and Linux kernel args will be appended to mount it as the root file system.
func P9Directory ¶
P9Directory adds QEMU args that expose a directory as a Plan9 (9p) read-write filesystem in the VM.
dir is the directory to expose as read-write 9p filesystem.
tag is an identifier that is used within the VM when mounting an fs, e.g. 'mount -t 9p my-vol-ident mountpoint'. The tag must be unique for each dir.
P9Directory will add a kernel cmdline argument in the style of VMTEST_MOUNT9P_$qemuID=$tag. Likely this is only useful on Linux. The vmmount command in vminit/vmmount can be used to mount 9P directories passed to the VM this way at /mount/9p/$tag in the guest. See the example in ./examples/shareddir.
func ReadOnlyDirectory ¶
ReadOnlyDirectory adds args that expose a directory as a /dev/sda1 readonly vfat partition in the VM guest.
func VirtioRandom ¶
func VirtioRandom() Fn
VirtioRandom adds QEMU args that expose a PCI random number generator to the guest VM.
func WithAppendKernel ¶
WithAppendKernel appends kernel arguments.
func WithInitramfs ¶
WithInitramfs sets the path to the initramfs.
func WithQEMUArgs ¶
WithQEMUArgs adds arguments to the QEMU command line.
func WithQEMUCommand ¶
WithQEMUCommand sets a QEMU command. It's expected to provide a QEMU binary and optionally some arguments.
cmd may contain additional QEMU args, such as "qemu-system-x86_64 -enable-kvm -m 1G". They will be appended to the command-line.
func WithSerialOutput ¶
func WithSerialOutput(w ...io.WriteCloser) Fn
WithSerialOutput writes serial output to w as well.
func WithTask ¶
WithTask adds a goroutine running alongside the guest.
Task goroutines are started right before the guest is started.
VM.Wait waits for all tasks to complete before returning an error. Errors produced by tasks are returned by VM.Wait.
A task is expected to exit either when ctx is canceled or when the QEMU subprocess exits. When the context is canceled, the QEMU subprocess is expected to exit as well, and when the QEMU subprocess exits, the context is canceled.
func WithVMTimeout ¶
WithVMTimeout is a timeout for the QEMU guest subprocess.
func WithVmtestIdent ¶
func WithVmtestIdent() Fn
WithVmtestIdent adds VMTEST_IN_GUEST=1 to kernel commmand-line.
Tests may use this env var to identify they are running inside a vmtest using guest.SkipIfNotInVM or guest.SkipIfInVM.
type IDAllocator ¶
type IDAllocator struct {
// contains filtered or unexported fields
}
IDAllocator is used to ensure no overlapping QEMU option IDs.
func NewIDAllocator ¶
func NewIDAllocator() *IDAllocator
NewIDAllocator returns a new ID allocator for QEMU option IDs.
func (*IDAllocator) ID ¶
func (a *IDAllocator) ID(prefix string) string
ID returns the next available ID for the given prefix.
type LinePrinter ¶
type LinePrinter func(line string)
LinePrinter prints one line to some output.
func DefaultPrint ¶
func DefaultPrint(prefix string, printer func(fmt string, arg ...any)) LinePrinter
DefaultPrint is the default LinePrinter, adding a prefix and relative timestamp.
func Prefix ¶
func Prefix(prefix string, printer LinePrinter) LinePrinter
Prefix returns a LinePrinter that prefixes the given LinePrinter with "prefix: ".
func PrintLine ¶
func PrintLine(printer func(fmt string, arg ...any)) LinePrinter
PrintLine is a LinePrinter that prints to a standard "formatter" like testing.TB.Logf or fmt.Printf.
func RelativeTS ¶
func RelativeTS(printer LinePrinter) LinePrinter
RelativeTS prefixes line printer output with "[%06.4fs] " seconds since the first log line.
func TS ¶
func TS(format string, printer LinePrinter) LinePrinter
TS prefixes line printer output with a timestamp since the first log line.
format can be any Time.Format format string. Recommendations are time.TimeOnly or time.DateTime.
type Notifications ¶
type Notifications struct { // VMStarted will be closed when the VM is started. VMStarted chan struct{} // VMExited will receive exactly 1 event when the VM exits and then be closed. VMExited chan error }
Notifications gives tasks the option to wait for certain VM events.
Tasks must not be required to listen on notifications; there must be no blocking channel I/O.
type Options ¶
type Options struct { // QEMUCommand is QEMU binary to invoke and some additional args. // // If empty, the VMTEST_QEMU env var will be used. QEMUCommand string // Path to the kernel to boot. // // If empty, VMTEST_KERNEL env var will be used. Kernel string // Path to the initramfs. // // If empty, VMTEST_INITRAMFS env var will be used. Initramfs string // Extra kernel command-line arguments. // // VMTEST_KERNEL_APPEND env var will always be prepended. KernelArgs string // Where to send serial output. SerialOutput []io.WriteCloser // Tasks are goroutines running alongside the guest. // // Task goroutines are started right before the guest is started. // // A task is expected to exit either when ctx is canceled or when the // QEMU subprocess exits. When the context is canceled, the QEMU // subprocess is expected to exit as well, and when the QEMU subprocess // exits, the context is canceled. // // Tasks may depend on ExtraFiles or SerialOutput to be closed to exit. Tasks []Task // Additional QEMU cmdline arguments. QEMUArgs []string // VMTimeout is a timeout for the QEMU subprocess. VMTimeout time.Duration // ExtraFiles are extra files passed to QEMU on start. ExtraFiles []*os.File // contains filtered or unexported fields }
Options are VM start-up parameters.
func OptionsFor ¶
OptionsFor evaluates the given config functions and returns an Options object.
func (*Options) AddFile ¶
AddFile adds the file to the QEMU process and returns the FD it will be in the child process.
func (*Options) AppendKernel ¶
AppendKernel appends to kernel args.
func (*Options) AppendQEMU ¶
AppendQEMU appends args to the QEMU command line.
func (*Options) Cmdline ¶
Cmdline returns the command line arguments used to start QEMU. These arguments are derived from the given QEMU struct.
func (*Options) Start ¶
Start starts a QEMU VM and its associated task goroutines.
When the context is done, the QEMU subprocess will be killed and all associated goroutines cleaned up as long as VM.Wait() is called.
SerialOutput will be relayed only if VM.Wait is also called some time after the VM starts.
type Task ¶
type Task func(ctx context.Context, n *Notifications) error
A Task is a goroutine running alongside the guest.
Tasks are started before the guest process is started. A task is expected to exit either when ctx is canceled or when the QEMU subprocess exits.
VM.Wait waits for all tasks to finish after the guest process exits, and returns their non-nil errors.
func Cleanup ¶
Cleanup adds a function to be run after the VM process exits. If the function returns an error, Wait will return that error.
func WaitVMStarted ¶
WaitVMStarted waits until the VM has started before starting t, or never starts t if context is canceled before the VM is started.
type VM ¶
type VM struct { // Console provides in/output to the QEMU subprocess. Console *expect.Console // Options are the options that were used to start the VM. // // They are not used once the VM is started. Options *Options // contains filtered or unexported fields }
VM is a running QEMU virtual machine.
func Start ¶
Start starts a QEMU VM and its associated task goroutines with the given config.
SerialOutput will be relayed only if VM.Wait is also called some time after the VM starts.
func StartContext ¶
StartContext starts a QEMU VM and its associated task goroutines with the given config.
When the context is done, the QEMU subprocess will be killed and all associated goroutines cleaned up as long as VM.Wait() is called.
SerialOutput will be relayed only if VM.Wait is also called some time after the VM starts.
func StartT ¶
StartT starts a QEMU VM and its associated task goroutines with the given config.
Logs serial console to t.Logf using name as a prefix, with relative timestamps.
If the start fails, the test fails. At the end of the test, the command-line invocation for the VM is logged for reproduction. Also ensures that vm.Wait() was called by the end of the test, as it is required to drain console output.
SerialOutput will be relayed only if VM.Wait is also called some time after the VM starts.
func (*VM) CmdlineQuoted ¶
CmdlineQuoted quotes any of QEMU's command line arguments containing a space so it is easy to copy-n-paste into a shell for debugging.
func (*VM) Kill ¶
Kill kills the QEMU subprocess.
Callers are still responsible for calling VM.Wait after calling kill to clean up task goroutines and to get remaining serial console output.
func (*VM) Signal ¶
Signal signals the QEMU subprocess.
Callers are still responsible for calling VM.Wait if the subprocess exits due to this signal to clean up task goroutines and to get remaining serial console output.
Directories
¶
Path | Synopsis |
---|---|
Package qcoverage allows collecting kernel and Go integration test coverage.
|
Package qcoverage allows collecting kernel and Go integration test coverage. |
Package qevent implements a JSON-based event channel between guest and host.
|
Package qevent implements a JSON-based event channel between guest and host. |
Package qfirmware provides firmware configurators for use with the Go qemu API.
|
Package qfirmware provides firmware configurators for use with the Go qemu API. |
Package qnetwork provides net device configurators for use with the Go qemu API.
|
Package qnetwork provides net device configurators for use with the Go qemu API. |
Package quimage provides a Go API for creating QEMU VMs with u-root uimage initramfses.
|
Package quimage provides a Go API for creating QEMU VMs with u-root uimage initramfses. |