qemu

package
v0.0.0-...-2e3d018 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 11, 2023 License: Apache-2.0 Imports: 13 Imported by: 5

Documentation

Overview

Package qemu provides an interface for interacting with running QEMU instances.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrBlockDeviceNotFound is returned given when a block device is not found
	ErrBlockDeviceNotFound = errors.New("block device not found")
)

Functions

This section is empty.

Types

type BlockDevice

type BlockDevice struct {
	Device   string `json:"device"`
	Inserted struct {
		BackingFile      string `json:"backing_file"`
		BackingFileDepth int    `json:"backing_file_depth"`
		BPS              int    `json:"bps"`
		BPSRead          int    `json:"bps_rd"`
		BPSWrite         int    `json:"bps_wr"`
		Cache            struct {
			Direct    bool `json:"direct"`
			NoFlush   bool `json:"no-flush"`
			Writeback bool `json:"writeback"`
		} `json:"cache"`
		DetectZeroes         string `json:"detect_zeroes"`
		Driver               string `json:"drv"`
		Encrypted            bool   `json:"encrypted"`
		EncryptionKeyMissing bool   `json:"encryption_key_missing"`
		File                 string `json:"file"`
		Image                Image  `json:"image"`
		IOPs                 int    `json:"iops"`
		IOPsRead             int    `json:"iops_rd"`
		IOPsWrite            int    `json:"iops_wr"`
		NodeName             string `json:"node-name"`
		ReadOnly             bool   `json:"ro"`
		WriteThreshold       int    `json:"write_threshold"`
	} `json:"inserted"`
	IOStatus  string `json:"io-status"`
	Locked    bool   `json:"locked"`
	Removable bool   `json:"removable"`
	Type      string `json:"type"`
}

BlockDevice represents a QEMU block device.

func (BlockDevice) Commit

func (bd BlockDevice) Commit(d *Domain, overlay, jobID string, timeout time.Duration) error

Commit synchronously merges an overlay image onto a block device's root backing image. Once the operation is complete, CompleteJob() must be called to pivot the domain back to the original backing image.

func (BlockDevice) Mirror

func (bd BlockDevice) Mirror(d *Domain, dest string, timeout time.Duration) error

Mirror copies a block device to the given destination. The destination path specified by dest must be absolute.

func (BlockDevice) Snapshot

func (bd BlockDevice) Snapshot(d *Domain, overlay, nodeName string) error

Snapshot creates a point in time snapshot. The disk's image is given a new QCOW2 overlay, leaving the underlying image in a state that is considered safe for copying.

type BlockJob

type BlockJob struct {
	Busy     bool   `json:"busy"`
	Device   string `json:"device"`
	IOStatus string `json:"io-status"`
	Len      int    `json:"len"`
	Offset   int    `json:"offset"`
	Paused   bool   `json:"paused"`
	Ready    bool   `json:"ready"`
	Speed    int    `json:"speed"`
	Type     string `json:"type"`
}

BlockJob represents a QEMU blockjob.

func (BlockJob) Cancel

func (job BlockJob) Cancel(d *Domain, timeout time.Duration) error

Cancel a running block job. For block-mirror operations, this cancels the block job.

func (BlockJob) Complete

func (job BlockJob) Complete(d *Domain, timeout time.Duration) error

Complete a running block job. For blockcommit backups, this performs the "pivot" back to the original backing image.

type BlockStats

type BlockStats struct {
	// Device does not actually appear QEMU's output, but is added
	// by this package.
	Device string `json:"-"`

	AccountFailed             bool   `json:"account_failed"`
	AccountInvalid            bool   `json:"account_invalid"`
	FailedFlushOperations     int    `json:"failed_flush_operations"`
	FailedReadOperations      int    `json:"failed_rd_operations"`
	FailedWriteOperations     int    `json:"failed_wr_operations"`
	FlushOperations           int    `json:"flush_operations"`
	FlushTotalTimeNanoseconds int64  `json:"flush_total_time_ns"`
	IdleTimeNanoseconds       int64  `json:"idle_time_ns"`
	InvalidFlushOperations    int    `json:"invalid_flush_operations"`
	InvalidReadOperations     int    `json:"invalid_rd_operations"`
	InvalidWriteOperations    int    `json:"invalid_wr_operations"`
	ReadBytes                 uint64 `json:"rd_bytes"`
	ReadMerged                int    `json:"rd_merged"`
	ReadOperations            int    `json:"rd_operations"`
	ReadTotalTimeNanoseconds  int    `json:"rd_total_time_ns"`
	WriteBytes                uint64 `json:"wr_bytes"`
	WriteHighestOffset        int64  `json:"wr_highest_offset"`
	WriteMerged               int    `json:"wr_merged"`
	WriteOperations           int    `json:"wr_operations"`
	WriteTotalTimeNanoseconds int64  `json:"wr_total_time_ns"`
}

BlockStats represents QEMU block device statistics.

type CPU

type CPU struct {
	CPU     int  `json:"cpu"`
	Current bool `json:"current"`
	Halted  bool `json:"halted"`
	PC      int  `json:"pc"`
}

CPU represents a QEMU CPU.

type Domain

type Domain struct {
	Name string
	// contains filtered or unexported fields
}

Domain represents a QEMU instance.

func NewDomain

func NewDomain(m qmp.Monitor, name string) (*Domain, error)

NewDomain returns a new QEMU domain identified by the given name. QMP communication is handled by the provided monitor socket.

Example

This example demonstrates how to use qemu.NewDomain with a qmp.Monitor to perform actions on a Domain.

Typically, these actions would be performed using an actual monitor of type qmp.LibvirtRPCMonitor or qmp.SocketMonitor, instead of using qmptest.NewMonitor.

package main

import (
	"fmt"
	"log"

	"github.com/digitalocean/go-qemu/qemu"
	"github.com/digitalocean/go-qemu/qmp"
	"github.com/digitalocean/go-qemu/qmp/qmptest"
)

// This example demonstrates how to use qemu.NewDomain with a qmp.Monitor to
// perform actions on a Domain.
//
// Typically, these actions would be performed using an actual monitor of type
// qmp.LibvirtRPCMonitor or qmp.SocketMonitor, instead of using
// qmptest.NewMonitor.
func main() {
	// Use qmptest.NewMonitor to create an "example" qmp.Monitor, that returns
	// mock data from another function.
	//
	// Normally, qmp.NewLibvirtRPCMonitor or qmp.NewSocketMonitor would be used
	// here instead.
	mon := qmptest.NewMonitor(func(cmd qmp.Command) (interface{}, error) {
		return exampleRun(cmd)
	})

	// Monitor must be connected before it can be used.
	if err := mon.Connect(); err != nil {
		log.Fatalf("failed to connect monitor: %v", err)
	}

	// Wrap monitor in a qemu.Domain to perform higher-level management actions.
	dom, err := qemu.NewDomain(mon, "example")
	if err != nil {
		log.Fatalf("failed to create domain: %v", err)
	}

	// Return the domain's QEMU version.
	version, err := dom.Version()
	if err != nil {
		log.Fatalf("failed to check domain QEMU version: %v", err)
	}

	// List the available QMP commands supported by the domain.
	commands, err := dom.Commands()
	if err != nil {
		log.Fatalf("failed to list domain commands: %v", err)
	}

	// Print some information about the domain.
	fmt.Printf("%s - QEMU %s\n", dom.Name, version)
	fmt.Println("  - commands:")
	for _, c := range commands {
		fmt.Printf("    - %s\n", c)
	}

	// Close the domain to clean up its resources and underlying monitor.
	if err := dom.Close(); err != nil {
		log.Fatalf("failed to close domain: %v", err)
	}

}

func exampleRun(cmd qmp.Command) (interface{}, error) {
	switch cmd.Execute {
	case "query-commands":
		return runQueryCommands(), nil
	case "query-version":
		return runQueryVersion(), nil
	}

	return nil, fmt.Errorf("unknown command: %q", cmd.Execute)
}

func runQueryCommands() interface{} {
	var response struct {
		ID     string        `json:"id"`
		Return []nameWrapper `json:"return"`
	}

	commands := []string{
		"query-block",
		"query-commands",
		"query-version",
	}

	response.Return = make([]nameWrapper, 0, len(commands))
	for _, c := range commands {
		response.Return = append(response.Return, nameWrapper{
			Name: c,
		})
	}

	return response
}

func runQueryVersion() interface{} {
	var response struct {
		ID     string      `json:"id"`
		Return qmp.Version `json:"return"`
	}
	response.Return.QEMU.Major = 2

	return response
}

type nameWrapper struct {
	Name string `json:"name"`
}
Output:

example - QEMU 2.0.0
  - commands:
    - query-block
    - query-commands
    - query-version

func (*Domain) BlockDevice

func (d *Domain) BlockDevice(name string) (BlockDevice, error)

BlockDevice searches a domain for the given block device. If found, a BlockDevice is returned. If the device is not found, the returned error will be ErrBlockDeviceNotFound.

func (*Domain) BlockDevices

func (d *Domain) BlockDevices() ([]BlockDevice, error)

BlockDevices returns a domain's block devices.

func (*Domain) BlockJobs

func (d *Domain) BlockJobs() ([]BlockJob, error)

BlockJobs returns active block job operations.

func (*Domain) BlockStats

func (d *Domain) BlockStats() ([]BlockStats, error)

BlockStats returns block device statistics for a domain.

func (*Domain) CPUs

func (d *Domain) CPUs() ([]CPU, error)

CPUs returns a domain's CPUs.

func (*Domain) Close

func (d *Domain) Close() error

Close cleans up internal resources of a Domain and disconnects the underlying qmp.Monitor. Close must be called when done with a Domain to avoid leaking resources.

func (*Domain) Commands

func (d *Domain) Commands() ([]string, error)

Commands returns all QMP commands supported by the domain.

func (*Domain) Events

func (d *Domain) Events() (chan qmp.Event, chan struct{}, error)

Events streams QEMU QMP events. Two channels are returned, the first contains events emitted by the domain. The second is used to signal completion of event processing. It is the responsibility of the caller to always close this channel when finished.

func (*Domain) PCIDevices

func (d *Domain) PCIDevices() ([]PCIDevice, error)

PCIDevices returns a domain's PCI devices.

func (*Domain) PackageVersion

func (d *Domain) PackageVersion() (string, error)

PackageVersion returns the domain's QEMU package version, the full build information for QEMU.

func (*Domain) Run

func (d *Domain) Run(c qmp.Command) ([]byte, error)

Run executes the given QMP command against the domain. The returned []byte is the raw output from the QMP monitor.

Run should be used with caution, as it allows the execution of arbitrary QMP commands against the domain.

func (*Domain) ScreenDump

func (d *Domain) ScreenDump() (io.ReadCloser, error)

ScreenDump captures the domain's screen and creates an output PPM image stream. ScreenDump will only work if the Domain resides on a local hypervisor; not a remote one connected over SSH or TCP socket.

If needed, a PPM image can be decoded using Go's package image and a PPM decoder, such as https://godoc.org/github.com/jbuchbinder/gopnm.

func (*Domain) Status

func (d *Domain) Status() (Status, error)

Status returns the current status of the domain.

func (*Domain) Supported

func (d *Domain) Supported(cmd string) (bool, error)

Supported returns true if the provided command is supported by the domain.

func (*Domain) SystemPowerdown

func (d *Domain) SystemPowerdown() error

SystemPowerdown sends a system power down event to the domain.

func (*Domain) SystemReset

func (d *Domain) SystemReset() error

SystemReset sends a system reset event to the domain.

func (*Domain) Version

func (d *Domain) Version() (string, error)

Version returns the domain's QEMU version.

type Image

type Image struct {
	ActualSize            uint64 `json:"actual-size"`
	BackingFilename       string `json:"backing-filename"`
	BackingFilenameFormat string `json:"backing-filename-format"`
	BackingImage          struct {
		ActualSize  uint64 `json:"actual-size"`
		Dirty       bool   `json:"dirty-flag"`
		Filename    string `json:"filename"`
		Format      string `json:"format"`
		VirtualSize uint64 `json:"virtual-size"`
	} `json:"backing-image"`
	ClusterSize    int    `json:"cluster-size"`
	Dirty          bool   `json:"dirty-flag"`
	Filename       string `json:"filename"`
	Format         string `json:"format"`
	FormatSpecific struct {
		Data struct {
			Compat        string `json:"compat"`
			Corrupt       bool   `json:"corrupt"`
			LazyRefcounts bool   `json:"lazy-refcounts"`
			RefcountBits  int    `json:"refcount-bits"`
		} `json:"data"`
		Type string `json:"type"`
	} `json:"format-specific"`
	VirtualSize uint64 `json:"virtual-size"`
}

Image represents a BlockDevice backing image.

type PCIDevice

type PCIDevice struct {
	Bus       int    `json:"bus"`
	QdevID    string `json:"qdev_id"`
	Slot      int    `json:"slot"`
	ClassInfo struct {
		Class int    `json:"class"`
		Desc  string `json:"desc"`
	} `json:"class_info"`
	ID struct {
		Device int `json:"device"`
		Vendor int `json:"vendor"`
	} `json:"id"`
	Function int `json:"function"`
	Regions  []struct {
		Prefetch  bool   `json:"prefetch"`
		MemType64 bool   `json:"mem_type_64"`
		Bar       int    `json:"bar"`
		Size      int    `json:"size"`
		Address   int64  `json:"address"`
		Type      string `json:"type"`
	} `json:"regions"`
}

PCIDevice represents a QEMU PCI device.

type Status

type Status int

Status represents the current status of the domain.

const (
	StatusDebug         Status = Status(raw.RunStateDebug)
	StatusFinishMigrate Status = Status(raw.RunStateFinishMigrate)
	StatusGuestPanicked Status = Status(raw.RunStateGuestPanicked)
	StatusIOError       Status = Status(raw.RunStateIOError)
	StatusInMigrate     Status = Status(raw.RunStateInmigrate)
	StatusInternalError Status = Status(raw.RunStateInternalError)
	StatusPaused        Status = Status(raw.RunStatePaused)
	StatusPostMigrate   Status = Status(raw.RunStatePostmigrate)
	StatusPreLaunch     Status = Status(raw.RunStatePrelaunch)
	StatusRestoreVM     Status = Status(raw.RunStateRestoreVM)
	StatusRunning       Status = Status(raw.RunStateRunning)
	StatusSaveVM        Status = Status(raw.RunStateSaveVM)
	StatusShutdown      Status = Status(raw.RunStateShutdown)
	StatusSuspended     Status = Status(raw.RunStateSuspended)
	StatusWatchdog      Status = Status(raw.RunStateWatchdog)
)

Status constants which indicate the status of a domain.

func (Status) String

func (i Status) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL