machina

package module
v0.0.0-...-ede35a2 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2023 License: MIT Imports: 16 Imported by: 0

README

machina Go Reference Go Report Card

Machina is a lightweight and opinionated virtual machine manager. It uses QEMU to start and stop kernel virtual machines on linux systems. Each virtual machine is operated as a systemd unit.

This software is experimental. There are no gaurantees about API compatibility, file format compatibility, or fitness for purpose.

The systemd units generated by machina currently require the QEMU process to be run as root. This presents a security concern should a malicious virtual machine process ever escape from its containment. In light of this, machina is not yet recommended for production use.

The machina library and program are written in Go.

Core Design Goals and Principals

1. No external dependencies

The machina program is distributed as a single binary with no dependencies beyond those of QEMU itself.

2. Direct invocation of QEMU via systemd

While machina is involved in the generation of systemd unit files and assists with virtual machine preparation and teardown, it is not responsible for launching the QEMU process. Instead, systemd launches the QEMU process directly.

This approach removes machina as a point of failure during normal operation, and allows machina to be updated without interrupting the virtual machines managed by it.

3. Reusable configuration via tagging

The machina design encourages creation and use of virtual machine tags. Tags define a common set of attributes for virtual machines. This reduces the amount of configuration that must be managed for each virtual machine.

4. Explicitly defined system configuration

Instead of interrogating a running environment, machina expects host system configuration to be defined explicitly. As a result, machina can be used to generate systemd units for remote and offline hosts, as long as the host configuration files are available.

5. Succinct virtual machine definitions

Other virtual machine managers tend to haul around a lot of configuration data for each virtual machine in order to reproduce its environment precisely. The machina system goes in the opposite direction, attempting to reduce the per-machine configuration to its most necessary and succinct components.

Users of machina should think about high level concepts for their virtual machines:

  • What disk volumes does it need?
  • Where are my disk images stored?
  • How many cores and how much RAM does it need?
  • What network connections should it have?

The primary task of machina is to translate these concepts into QEMU command lines that can be invoked by systemd. The opinions of the machina designers are expressed in this process, making decisions about PCI Express bus layouts, what QEMU device implementations to use, and other similar concerns.

6. Portable virtual machine definitions

Host system configuration is separate from virtual machine guest configuration.

Virtual machine definitions can easily be relocated to new hosts without modification.

Non-Goals

Support for other hypervisors

The machina design is focused on supporting QEMU and KVM.

Features

Windows and linux guest support

Virtual machines can easily be configured to enable Hyper-V Enlightenments used by Windows guests.

OVMF firmware support

Virtual machines can be supplied with OVMF firmware, allowing the virtual machines to run in the context of a modern UEFI BIOS.

Mediated device support

Machina supports the use of mediated devices provided by some graphics hardware vendors. This allows virtual machines to share access to hardware resources that provide this feature.

Orderly shutdowns

The systemd units will attempt an orderly shutdown of their virtual machines when systemd asks the unit to stop. This is accomplished by issuing QMP shutdown commands which are delivered to the virtual environment as ACPI power commands.

Consistent identifiers

The only identifiers that must be provided for each virtual machine are its name and its machine-wide unique identifier, the UUID.

While machina allows for explicit configuration of MAC addresses, volume serial numbers and other such identifiers, it is capable of producing stable identifiers as needed. It accomplishes this by deriving identifiers from the machine's UUID and name via hashing.

Planned features

Reduced QEMU privileges

The QEMU process that manages a virtual machine should run as a non-root user with least privileges.

Virtual machine dissolution

While virtual machines can easily be disabled via machina disable, there is no facility for removal of their systemd units.

Improved variable handling, patterns and expressions

The currently supported patterns are very rudimentary and don't allow for evaluation of mathematical expressions when determining things like port numbers.

Graphical Configuration Manager

A graphical user interface for creation and management of machina configuration files would be neat.

Features not supported

QCOW disk formats

The designers of machina prefer to operate their virtual machines as raw disk images stored on zfs datasets. This allows for images to be efficiently snapshotted and for snapshots to be efficiently transported. Support for qcow2 and other disk formats has not been a focus, though it would not be difficult to add.

Live migration

There is no support for live migration at this time.

Virtual machine destruction

There is no facility for total annihilation of virtual machines, which would include permanent deletion of their disk volumes.

This is an inherantly dangerous ability and won't be added without much consideration.

Known Issues

Bash completion when using sudo

Bash completion doesn't work when using sudo, as in sudo machina <command>.

Update considerations

Newer versions of machina might make different choices or use different default values when generating systemd units. This can result in changes to the virtual hardware environment of the machines that it manages.

While this poses some risk, most guest operating systems are tolerant of hardware changes.

Usage

Usage: machina <command>

Manages kernel virtual machines via QEMU.

Flags:
  -h, --help    Show context-sensitive help.

Commands:
  install
    Installs the machina command in the system path.

  cat [<machines> ...]
    Displays the machina configuration for virtual machines.

  list
    Lists all of the virtual machines present.

  status <machines> ...
    Displays the systemd unit status for virtual machines.

  observe <machines> ...
    Reports QMP events for virtual machines.

  generate <machines> ...
    Generates systemd unit configuration files from /etc/machina/machine.conf.d/*.conf.json.

  enable <machines> ...
    Enables the systemd units for virtual machines.

  disable <machines> ...
    Disables the systemd units for virtual machines.

  start <machines> ...
    Starts the systemd units for virtual machines.

  stop <machines> ...
    Stops the systemd units for virtual machines.

  shutdown <machines> ...
    Sends a shutdown command to one or more virtual machines.

  prepare <machines> ...
    Prepares the host environment for a virtual machine to start.

  teardown <machines> ...
    Removes host resources prepared for a virtual machine.

  connect <machines-or-connections> ...
    Connects a whole virtual machine or individual connections to the network.

  disconnect <machines-or-connections> ...
    Disconnects a whole virtual machine or individual connections from the network.

  query pci <machines> ...
    Describes the PCI Bus in running virtual machines.

  query cpu <machines> ...
    Describes the virtual CPUs present in running virtual machines.

  gen-id
    Generate a random machine identifier.

  gen-mac
    Generate a random MAC hardware address.

  args <machines> ...
    Displays the QEMU arguments for virtual machines.

  run [<machine>]
    Run a virtual machine directly via QEMU.

Run "machina <command> --help" for more information on a command.

Configuration

The machina design divides configuration into two portions:

  1. System (host) configuration
  2. Virtual machine (guest) configuration

When machina builds a systemd unit for a virtual machine, it reads two files and uses their content to produce the systemd unit:

  1. The system host configuration file (/etc/machina/machina.conf.json)
  2. The virtual machine guest configuration file (/etc/machina/machine.conf.d/[guest-name].conf.json)

The system configuration file defines the storage location, available networks, and interpretation of tags on a particular system. It describes the environmental features that are unique to that particular host.

The virtual machine configuration file defines the name, ID, tags and attributes of a virtual machine. It describes the features of a guest and what it expects from its host.

If a virtual machine definition is relocated to a new host, it gets combined with a different system configuration file, and thus produces a systemd unit that is suitable for that host.

Example Configuration

Note: The configuration file format is subject to change, and this example configuration could fall out of sync as changes are made.

Machine configuration files are stored in individual conf.json files within /etc/machina/machine.conf.d. Here's an example for a theoretical test-vm, which would be placed in a /etc/machina/machine.conf.d/test-vm.conf.json file:

{
	"id": "8b18191a-234f-45ce-b43c-b46e28cd2f70",
	"description": "Test VM (2023-04-27)",
	"tags": ["vdi-employee", "vdi-cad", "windows", "windows-10-media", "firmware-202302"],
	"vars": {
		"employee-id": "9000"
	}
}

System configuration is stored in the /etc/machina/machina.conf.json file. Here's an example that provides definitions for the tags used by the example test machine:

{
	"storage": {
		"guest-firmware-vars": {
			"path": "/zfs-tank/",
			"pattern": "${machine-name}/os/${machine-name}-${volume}.vars.bin",
			"type": "firmware"
		},
		"guest-data": {
			"path": "/zfs-tank/",
			"pattern": "${machine-name}/os/${machine-name}-${volume}.raw",
			"type": "raw"
		},
		"firmware-code": {
			"path": "/usr/lib/machina/firmware/",
			"pattern": "${volume}.code.bin",
			"type": "firmware",
			"readonly": true
		},
		"iso-ahci": {
			"path": "/usr/lib/machina/iso/",
			"pattern": "${volume}.iso",
			"type": "iso-ahci"
		},
		"iso-scsi": {
			"path": "/usr/lib/machina/iso/",
			"pattern": "${volume}.iso",
			"type": "iso-scsi"
		}
	},
	"network": {
		"local": {
			"device": "kvmbr0"
		}
	},
	"mdev": {
		"nvidia-rtx8000": {
			"address": "0000:c1:00.0",
			"types": {
				"cad-standard": "GRID RTX8000-6Q"
			}
		}
	},
	"tag": {
		"vdi-employee": {
			"attrs": {
				"spice": {
					"enabled": true,
					"port-pattern": "5${employee-id}",
					"displays": 1
				},
				"agent": {
					"qemu": {
						"enabled": true,
						"port-pattern": "4${employee-id}"
					}
				}
			}
		},
		"vdi-cad": {
			"attrs": {
				"cpu": {"sockets": 1, "cores": 4},
				"memory": {"ram": 32768}
			},
			"volumes": [
				{"name": "os", "storage": "guest-data", "bootable": true}
			],
			"connections": [
				{
					"name": "0",
					"network": "local"
				}
			],
			"devices": [
				{
					"name": "vgpu",
					"class": "cad-standard"
				}
			]
		},
		"windows": {
			"attrs": {
				"enlightenments": {"enabled": true},
				"qmp": {
					"enabled": true
				}
			},
			"volumes": [
				{"storage": "iso-ahci", "name": "virtio-win-latest"}
			]
		},
		"windows-10-media": {
			"volumes": [
				{"storage": "iso-scsi", "name": "win10"}
			]
		},
		"firmware-202302": {
			"attrs": {
				"firmware": {
					"code": {"storage": "firmware-code", "name": "ovmf-stable202302"},
					"vars": {"storage": "guest-firmware-vars", "name": "firmware"}
				}
			}
		}
	}
}

Here is the resulting summary offered by machina cat test-vm:

  Name: test-vm
  Description: Test VM (2023-04-27)
  ID: 8b18191a-234f-45ce-b43c-b46e28cd2f70
  Tags: vdi-employee,vdi-cad,windows,windows-10-media,firmware-202302
  Vars:
    employee-id: 9000
  Firmware Code (read-only): ovmf-stable202302: firmware-code
  Firmware Variables (read/write): firmware: guest-firmware-vars
  Sockets: 1
  Cores: 4
  RAM: 32768M
  Hyper-V Enlightenments: Enabled
  QMP: Enabled
  QMP Socket Path: /run/machina/test-vm/systemd.0.qmp.socket
  QMP Socket Path: /run/machina/test-vm/command.0.qmp.socket
  QMP Socket Path: /run/machina/test-vm/command.1.qmp.socket
  QEMU Guest Agent: Enabled
  QEMU Guest Agent Port: 49000
  Spice Display: Enabled
  Spice Port: 59000
  Spice Display Count: 1
  Volumes:
    os: guest-data (wwn: 0x5525400908FE6258, serial: 9IQ4PUV68QOCNS2C75OKUS04I4, bootable)
    virtio-win-latest: iso-ahci (wwn: 0x5525400982DB87CE, serial: JAVJJVPOOPTIV73ONECE40VFD4)
    win10: iso-scsi (wwn: 0x5525400F7C2ED5D0, serial: 0V17D9DH4EVT9SFOCV9CFTR0BK)
  Connections:
    0: local (mac: 52:54:00:26:77:fa)
  Devices:
    vgpu: cad-standard (3e2cee4d-1002-4989-af98-3e03b8ad3197)

Here is the resulting systemd unit file, as shown by machina generate --preview test-vm:

[Unit]
Description=machina KVM test-vm
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=1m0s
StartLimitBurst=2

[Service]
Type=simple
ExecStart=qemu-system-x86_64 \
-uuid 8b18191a-234f-45ce-b43c-b46e28cd2f70 \
-name test-vm \
-enable-kvm \
-nodefaults \
-nographic \
-machine type=q35,vmport=off,pflash0=ovmf-stable202302,pflash1=test-vm-firmware \
-cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time \
-smp sockets=1,cores=4 \
-m size=32768M \
-rtc base=utc,clock=host,driftfix=slew \
-mon chardev=qmp.0,mode=control \
-mon chardev=qmp.1,mode=control \
-mon chardev=qmp.2,mode=control \
-spice port=59000,addr=127.0.0.1,disable-ticketing=on \
-global driver=cfi.pflash01,property=secure,value=on \
-global driver=qxl-vga,property=ram_size,value=67108864 \
-global driver=qxl-vga,property=vram_size,value=67108864 \
-boot menu=on,reboot-timeout=5000 \
-object iothread,id=iothread.0 \
-blockdev driver=file,node-name=ovmf-stable202302,read-only=on,filename=/usr/lib/machina/firmware/ovmf-stable202302.code.bin \
-blockdev driver=file,node-name=test-vm-firmware,filename=/zfs-tank/test-vm/os/test-vm-firmware.vars.bin \
-blockdev driver=file,node-name=test-vm-os-file,filename=/zfs-tank/test-vm/os/test-vm-os.raw \
-blockdev driver=raw,node-name=test-vm-os,file=test-vm-os-file \
-blockdev driver=file,node-name=virtio-win-latest,read-only=on,filename=/usr/lib/machina/iso/virtio-win-latest.iso \
-blockdev driver=file,node-name=win10,read-only=on,filename=/usr/lib/machina/iso/win10.iso \
-chardev socket,id=qmp.0,server=on,wait=off,path=/run/machina/test-vm/systemd.0.qmp.socket \
-chardev socket,id=qmp.1,server=on,wait=off,path=/run/machina/test-vm/command.0.qmp.socket \
-chardev socket,id=qmp.2,server=on,wait=off,path=/run/machina/test-vm/command.1.qmp.socket \
-chardev socket,id=guestagent,host=127.0.0.1,port=49000,server=on,wait=off,nodelay=on \
-chardev spicevmc,id=vdagent,debug=0,name=vdagent \
-chardev spicevmc,id=usbredir.0,debug=0,name=usbredir \
-chardev spicevmc,id=usbredir.1,debug=0,name=usbredir \
-netdev tap,id=net.0,ifname=test-vm.0,script=/usr/bin/machina-ifup,downscript=/usr/bin/machina-ifdown \
-device ioh3420,id=pcie.1.0,chassis=0,bus=pcie.0,addr=1.0,multifunction=on \
-device virtio-serial-pci,id=serial,bus=pcie.1.0 \
-device virtserialport,id=serial.0.0,bus=serial.0,nr=1,chardev=guestagent,name=org.qemu.guest_agent.0 \
-device virtserialport,id=serial.0.1,bus=serial.0,nr=2,chardev=vdagent,name=com.redhat.spice.0 \
-device qxl-vga,id=qxl.0,bus=pcie.0,addr=1.1 \
-device ioh3420,id=pcie.1.2,chassis=2,bus=pcie.0,addr=1.2 \
-device qemu-xhci,id=usb,bus=pcie.1.2,p2=4,p3=4 \
-device usb-tablet,id=usb.0.1,bus=usb.0,port=1 \
-device usb-redir,id=usb.0.2,bus=usb.0,port=2,chardev=usbredir.0 \
-device usb-redir,id=usb.0.3,bus=usb.0,port=3,chardev=usbredir.1 \
-device ioh3420,id=pcie.1.3,chassis=3,bus=pcie.0,addr=1.3 \
-device virtio-scsi-pci,id=scsi,bus=pcie.1.3,iothread=iothread.0,num_queues=4 \
-device scsi-hd,id=scsi.0.0,bus=scsi.0,channel=0,scsi-id=0,lun=0,drive=test-vm-os,wwn=0x5525400908FE6258,serial=9IQ4PUV68QOCNS2C75OKUS04I4,bootindex=1 \
-device scsi-cd,id=scsi.0.1,bus=scsi.0,channel=0,scsi-id=0,lun=1,drive=win10 \
-device ide-cd,id=sata.0,bus=ide.1,drive=virtio-win-latest \
-device ioh3420,id=pcie.1.5,chassis=5,bus=pcie.0,addr=1.5 \
-device virtio-net-pci,bus=pcie.1.5,mac=52:54:00:26:77:fa,netdev=net.0 \
-device ioh3420,id=pcie.1.6,chassis=6,bus=pcie.0,addr=1.6 \
-device vfio-pci,id=vfio.0,bus=pcie.1.6,sysfsdev=/sys/bus/mdev/devices/3e2cee4d-1002-4989-af98-3e03b8ad3197
ExecStartPre=machina prepare test-vm
ExecStop=machina shutdown --system --timeout 1m25s test-vm
ExecStopPost=machina teardown test-vm
RestartSec=10s
TimeoutStopSec=1m30s
Restart=on-failure
RuntimeDirectory=machina/test-vm

[Install]
WantedBy=multi-user.target

Documentation

Index

Constants

View Source
const (
	LinuxBinDir            = "/usr/bin"
	LinuxConfDir           = "/etc/machina"
	LinuxMachineDir        = "/etc/machina/machine.conf.d"
	LinuxUnitDir           = "/etc/systemd/system"
	LinuxRunDir            = "/run/machina"
	LinuxBashCompletionDir = "/usr/share/bash-completion/completions"
)

Common paths assumed by machina's code generators.

View Source
const (
	RawStorage      = StorageType("raw")
	ISOStorage      = StorageType("iso")
	FirmwareStorage = StorageType("firmware")
)

Storage types.

Variables

This section is empty.

Functions

func MakeLinkName

func MakeLinkName(machine MachineName, conn Connection) string

MakeLinkName returns the network interface name for a connection.

func MakeQMPSocketPaths

func MakeQMPSocketPaths(info MachineInfo, names ...string) (paths []string)

MakeQMPSocketPaths returns a QMP socket path for each name for the given machine.

If info lacks necessary details to build a QMP socket path, it returns nil.

Types

type Agent

type Agent struct {
	QEMU QEMUAgent `json:"qemu,omitempty"`
}

Agent describes the attributes of a machine's guest agent support.

func (*Agent) Config

func (a *Agent) Config(vars Vars, out summary.Interface)

Config adds the agent configuration to the summary.

type Attributes

type Attributes struct {
	Firmware       Firmware       `json:"firmware,omitempty"`
	CPU            CPU            `json:"cpu,omitempty"`
	Memory         Memory         `json:"memory,omitempty"`
	Enlightenments Enlightenments `json:"enlightenments,omitempty"`
	QMP            QMP            `json:"qmp,omitempty"`
	Agent          Agent          `json:"agent,omitempty"`
	Spice          Spice          `json:"spice,omitempty"`
}

Attributes describe various attributes of a machine.

func MergeAttributes

func MergeAttributes(attrs ...Attributes) Attributes

MergeAttributes merges a set of attributes in order. If an attribute value is defined more than once, the first definition is used.

func (*Attributes) Config

func (a *Attributes) Config(info MachineInfo, vars Vars, out summary.Interface)

Config adds the attributes configuration to the summary.

type CPU

type CPU struct {
	Sockets int `json:"sockets,omitempty"`
	Cores   int `json:"cores,omitempty"`
}

CPU describes the attributes of a machine's central processing units.

func (*CPU) Config

func (cpu *CPU) Config(out summary.Interface)

Config adds the cpu configuration to the summary.

type Connection

type Connection struct {
	Name    ConnectionName `json:"name"`
	Network NetworkName    `json:"network"`
	IP      string         `json:"ip"`
	MAC     string         `json:"mac"`
}

Connection describes a network connection.

func MergeConnections

func MergeConnections(conns ...Connection) []Connection

MergeConnections merges a set of connections in order. If more than one connection exists with the same name, only the first is included.

func (*Connection) Config

func (c *Connection) Config(out summary.Interface)

Config adds the connection configuration to the summary.

func (Connection) Populate

func (c Connection) Populate(seed Seed) Connection

Populate returns a copy of the connection with a hardware address, if one is not already present.

The provided machine seed is used to generate the address.

func (Connection) String

func (c Connection) String() string

String returns a string representation of the network connection configuration.

type ConnectionName

type ConnectionName string

ConnectionName is the name of a network connection on a machine.

type Definition

type Definition struct {
	Vars        Vars         `json:"vars,omitempty"`
	Attributes  Attributes   `json:"attrs,omitempty"`
	Volumes     []Volume     `json:"volumes,omitempty"`
	Connections []Connection `json:"connections,omitempty"`
	Devices     []Device     `json:"devices,omitempty"`
}

Definition holds the definition of a machine tag.

func Build

func Build(m Machine, sys System) (merged Definition, err error)

Build takes the machina virtual machine definition present in m and merges it with the applicable tag definitions present in sys. It returns the merged definition.

func MergeDefinitions

func MergeDefinitions(defs ...Definition) Definition

MergeDefinitions merges a set of definitions in order. If more than one volume exists with the same name, only the first is included.

func (*Definition) Config

func (d *Definition) Config(info MachineInfo, out summary.Interface)

Config adds the attributes configuration to the summary.

type Device

type Device struct {
	Name  DeviceName  `json:"name"`
	Class DeviceClass `json:"class"`
	ID    DeviceID    `json:"id,omitempty"`
}

Device identifies a mediated or passthrough host device required by a machine.

The type of device is identified by its class, which must match a device classification on the system. The ID optionally provides a unique identifier in UUID format that can be used by some device types.

func MergeDevices

func MergeDevices(devs ...Device) []Device

MergeDevices merges a set of connections in order. If more than one device exists with the same ID, only the first is included.

func (Device) Config

func (d Device) Config(out summary.Interface)

Config adds the device configuration to the summary.

func (Device) Populate

func (d Device) Populate(seed Seed) Device

Populate returns a copy of the device with a device ID, if one is not already present.

The provided machine seed is used to generate the device ID.

func (Device) String

func (d Device) String() string

String returns a string representation of the device configuration.

type DeviceAddress

type DeviceAddress string

DeviceAddress is a device address on the host system.

type DeviceClass

type DeviceClass string

DeviceClass identifies a class of device on the host system that can be assigned to a virtual machine.

type DeviceID

type DeviceID UUID

DeviceID is a universally uniqued identifer for a device.

func (DeviceID) IsZero

func (d DeviceID) IsZero() bool

IsZero returns true if the device ID holds a zero value.

func (DeviceID) MarshalText

func (d DeviceID) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface.

func (DeviceID) String

func (d DeviceID) String() string

String returns a string representation of the device ID.

func (*DeviceID) UnmarshalText

func (d *DeviceID) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

type DeviceName

type DeviceName string

DeviceName is the name of a device on a machine.

type Enlightenments

type Enlightenments struct {
	Enabled bool `json:"enabled,omitempty"`
}

Enlightenments describe Hyper-V features for guests running Windows.

https://github.com/qemu/qemu/blob/master/docs/hyperv.txt

func (*Enlightenments) Config

func (e *Enlightenments) Config(out summary.Interface)

Config adds the enlightenments configuration to the summary.

type Firmware

type Firmware struct {
	Code Volume `json:"code,omitempty"`
	Vars Volume `json:"vars,omitempty"`
}

Firmware describes the attributes of a machine's firmware.

func (*Firmware) Config

func (f *Firmware) Config(out summary.Interface)

Config adds the firmware configuration to the summary.

type IntPattern

type IntPattern string

IntPattern is a pattern that can undergo variable expansion to produce integer values.

func (IntPattern) Expand

func (pattern IntPattern) Expand(mapper PatternMapper) (int, error)

Expand returns the expanded integer for the given mapper. If the expanded value cannot be converted to an integer, an error is returned.

type Machine

type Machine struct {
	Name        MachineName `json:"name,omitempty"`
	Description string      `json:"description,omitempty"`
	ID          MachineID   `json:"id,omitempty"`
	Tags        []Tag       `json:"tags,omitempty"`
	Definition
}

Machine describes an individual virtual machine in machina. It contains identity information, tags, and a definition.

If tags are present, the machine's definition can be merged with its tag definitions through use of the Build function.

The Machine structure is intended to be marshaled to and from JSON. It defines the format of files in the machina.conf.d directory.

func (Machine) Info

func (m Machine) Info() MachineInfo

Info returns copy of the machine's entity information by itself.

func (Machine) Summary

func (m Machine) Summary() string

Summary returns a multiline string summarizing the machine configuration.

type MachineConnection

type MachineConnection struct {
	Machine MachineName
	Connection
}

MachineConnection describes a connection for a machine.

type MachineID

type MachineID UUID

MachineID is a universally unique identifer for a machine.

func (MachineID) IsZero

func (m MachineID) IsZero() bool

IsZero returns true if the machine ID holds a zero value.

func (MachineID) MarshalText

func (m MachineID) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface.

func (MachineID) String

func (m MachineID) String() string

String returns a string representation of the machine ID.

func (*MachineID) UnmarshalText

func (m *MachineID) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

type MachineInfo

type MachineInfo struct {
	ID          MachineID
	Description string
	Name        MachineName
}

MachineInfo holds identifying information for a machine.

func (MachineInfo) Seed

func (info MachineInfo) Seed() Seed

Seed returns an identity generation seed for the machine info.

func (MachineInfo) Vars

func (info MachineInfo) Vars() Vars

Vars returns a set of identifying machine variables. These can be used as variables for expansion.

type MachineName

type MachineName string

MachineName is the name of a machina virtual machine.

TODO: Document restrictions on machine names and add validity checks. These names are used in various places when generating QEMU arguments. Spaces in particular could lead to argument parsing badness.

type MediatedDevice

type MediatedDevice struct {
	Address DeviceAddress       `json:"address"`
	Types   MediatedDeviceTypes `json:"types,omitempty"`
}

MediatedDevice describes a mediated device available on the host system.

func (MediatedDevice) Config

func (dev MediatedDevice) Config(out summary.Interface)

Config adds the mediated device configuration to the summary.

type MediatedDeviceList

type MediatedDeviceList []MediatedDevice

MediatedDeviceList holds a sortable list of mediated devices on the host system.

func (MediatedDeviceList) Len

func (a MediatedDeviceList) Len() int

func (MediatedDeviceList) Less

func (a MediatedDeviceList) Less(i, j int) bool

func (MediatedDeviceList) Swap

func (a MediatedDeviceList) Swap(i, j int)

type MediatedDeviceMap

type MediatedDeviceMap map[MediatedDeviceName]MediatedDevice

MediatedDeviceMap describes a set of mediated devices on the host system.

func (MediatedDeviceMap) WithClass

func (m MediatedDeviceMap) WithClass(class DeviceClass) (devices MediatedDeviceList)

WithClass returns zero or more mediated devices that supply the given device class.

type MediatedDeviceName

type MediatedDeviceName string

MediatedDeviceName is the name of a mediated device on the host system.

type MediatedDeviceType

type MediatedDeviceType string

MediatedDeviceType is a device type offered by a mediated device.

type MediatedDeviceTypes

type MediatedDeviceTypes map[DeviceClass]MediatedDeviceType

MediatedDeviceTypes map device classes to mediated device types on the host system.

type Memory

type Memory struct {
	RAM int `json:"ram,omitempty"`
}

Memory describes the attributes of a machine's memory.

func (*Memory) Config

func (m *Memory) Config(out summary.Interface)

Config adds the memory configuration to the summary.

type Network

type Network struct {
	Device string `json:"device"`
	Up     string `json:"up"`
	Down   string `json:"down"`
}

Network defines a network that a machine can be connected to.

func (Network) String

func (n Network) String() string

String returns a string representation of the network configuration.

type NetworkMap

type NetworkMap map[NetworkName]Network

NetworkMap maps network names to networks on the local system.

type NetworkName

type NetworkName string

NetworkName identifies a network on the local system by a well-known name.

TODO: Document restrictions on network names and add validity checks. These names are used in various places when generating QEMU arguments. Spaces in particular could lead to argument parsing badness.

type PatternMapper

type PatternMapper func(string) string

PatternMapper is a function that can map variables to values.

type PortPattern

type PortPattern string

PortPattern is a pattern that can undergo variable expansion to produce network port numbers.

func (PortPattern) Expand

func (pattern PortPattern) Expand(mapper PatternMapper) (int, error)

Expand returns the expanded integer for the given mapper. If the expanded value cannot be converted to an integer, an error is returned.

type QEMUAgent

type QEMUAgent struct {
	Enabled     bool        `json:"enabled,omitempty"`
	Port        int         `json:"port,omitempty"`
	PortPattern PortPattern `json:"port-pattern,omitempty"`
}

QEMUAgent describes the attributes of a machine's QEMU guest agent.

func (*QEMUAgent) Config

func (qga *QEMUAgent) Config(vars Vars, out summary.Interface)

Config adds the QEMU guest configuration to the summary.

func (QEMUAgent) EffectivePort

func (qga QEMUAgent) EffectivePort(vars Vars) (int, error)

EffectivePort returns the configured QEMU Agent port, either through explicit assignment or pattern expansion.

type QMP

type QMP struct {
	Enabled bool       `json:"enabled,omitempty"`
	Sockets QMPSockets `json:"sockets,omitempty"`
}

QMP describes the attributes of QEMU Machine Protocol support.

func (*QMP) AllSocketPaths

func (q *QMP) AllSocketPaths(info MachineInfo) (paths []string)

AllSocketPaths returns the entire set of QMP socket paths for the given machine. The returned paths include the standard machina system and command socket paths, as well as any custom socket paths specified for the machine.

func (*QMP) CommandSocketPaths

func (q *QMP) CommandSocketPaths(info MachineInfo) (paths []string)

CommandSocketPaths returns a set of QMP socket paths for use by command line utilities.

func (*QMP) Config

func (q *QMP) Config(info MachineInfo, out summary.Interface)

Config adds the QEMU Machine Protocol configuration to the summary.

func (*QMP) CustomSocketPaths

func (q *QMP) CustomSocketPaths(info MachineInfo) (paths []string)

CustomSocketPaths returns a set of QMP socket paths specified in the configuration. Named sockets will be returned as absolute paths in the standard machina socket directory. Pathed sockets will be retured verbatim.

func (*QMP) SystemSocketPaths

func (q *QMP) SystemSocketPaths(info MachineInfo) []string

SystemSocketPaths returns a set of QMP socket paths for use by systemd.

type QMPSockets

type QMPSockets struct {
	Names []string `json:"names,omitempty"`
	Paths []string `json:"paths,omitempty"`
}

QMPSockets holds a set of custom QMP sockets that will be created for a virtual machine. These are in addition to the standard system and command sockets provided by machina.

Named sockets will be created in the standard machina socket directory following its socket naming convention.

Pathed sockets will be created at the given socket paths.

type Seed

type Seed struct {
	// contains filtered or unexported fields
}

Seed holds a seed state for generating various machina identities in a consistent and deterministic way.

func (Seed) DeviceID

func (s Seed) DeviceID(components ...[]byte) DeviceID

DeviceID constructs a device identifier from a hash of the seed and components.

func (Seed) HardwareAddr

func (s Seed) HardwareAddr(components ...[]byte) net.HardwareAddr

HardwareAddr constructs an IEEE 802 MAC-48/EUI-48 hardware address from a hash of the seed and components.

The address returned will have the well-known prefix of 52:54:00, which identifies it as a locally administered address issued to a KVM virtual machine. This leaves 24 bits of unique value per address, which may not be enough to avoid collisions on a large network.

For more details about locally administered addresses, see RFC 5342 Section 2.1. For an excellent treatment of MAC addresses in general, see the MAC Address FAQ from AllDataFeeds.

func (Seed) SerialNumber

func (s Seed) SerialNumber(components ...[]byte) string

SerialNumber constructs a 128-bit serial number from a hash of the seed and components. The value is returned as a string encoded with Base 32 Encoding with Extended Hex Alphabet.

See RFC 4648 Section 7 for more details about the encoding.

func (Seed) UUID

func (s Seed) UUID(components ...[]byte) UUID

UUID constructs a UUID from a hash of the seed and components.

func (Seed) WWN

func (s Seed) WWN(components ...[]byte) wwn.Value

WWN constructs a 64-bit World Wide Name from a hash of the seed and components.

The name returned will use Network Address Authority type 5 and IEEE OUI value 52:54:00, which identifies it as a locally administered address issued to a KVM virtual machine. This leaves 36 bits of unique value per name.

For more details about locally administered addresses, see RFC 5342 Section 2.1.

type Spice

type Spice struct {
	Enabled     bool        `json:"enabled,omitempty"`
	Port        int         `json:"port,omitempty"`
	PortPattern PortPattern `json:"port-pattern,omitempty"`
	Displays    int         `json:"displays,omitempty"` // TODO: Does this belong here?
}

Spice describes the attributes of a machine's spice protocol configuration.

func (*Spice) Config

func (s *Spice) Config(vars Vars, out summary.Interface)

Config adds the spice configuration to the summary.

func (Spice) EffectivePort

func (s Spice) EffectivePort(vars Vars) (int, error)

EffectivePort returns the configured spice port, either through explicit assignment or pattern expansion.

type Storage

type Storage struct {
	Path     StoragePath    `json:"path"`
	Pattern  StoragePattern `json:"pattern,omitempty"`
	Type     StorageType    `json:"type,omitempty"`
	ReadOnly bool           `json:"readonly,omitempty"`
}

Storage defines the common parameters for a storage pool.

func (Storage) Volume

func (s Storage) Volume(machine MachineInfo, vars Vars, volume VolumeName) VolumePath

Volume returns the path of a volume.

type StorageMap

type StorageMap map[StorageName]Storage

StorageMap maps storage names to storage pools on the local system.

type StorageName

type StorageName string

StorageName is the name of a storage pool on the host system.

type StoragePath

type StoragePath string

StoragePath is the path of a storage pool on the host system.

type StoragePattern

type StoragePattern StringPattern

StoragePattern is a file storage naming pattern.

func (StoragePattern) Expand

func (p StoragePattern) Expand(mapper PatternMapper) StoragePath

Expand returns the storage path for the given machine and volume.

TODO: Consider allowing other attributes or arbitrary values to be used as variables.

type StorageType

type StorageType string

StorageType identifies the type of storage provided by a storage pool.

type StringPattern

type StringPattern string

StringPattern is a pattern that can undergo variable expansion to produce string values.

func (StringPattern) Expand

func (pattern StringPattern) Expand(mapper PatternMapper) string

Expand returns the expanded string for the given mapper.

type System

type System struct {
	// Storage defines storage pools available on the host system.
	Storage StorageMap `json:"storage,omitempty"`

	// Network defines network pools available on the host system.
	Network NetworkMap `json:"network,omitempty"`

	// MediatedDevices is a list of mediated devices available on the host
	// system.
	MediatedDevices MediatedDeviceMap `json:"mdev,omitempty"`

	// Tag defines tags available on the host system.
	Tag TagMap `json:"tag,omitempty"`
}

System holds configuration for the virtual machine host system.

func (System) Summary

func (sys System) Summary() string

Summary returns a multiline string summarizing the system configuration.

type Tag

type Tag string

Tag is an identifying tag for a machine tag.

type TagMap

type TagMap map[Tag]Definition

TagMap maps tag names to tag definitions.

func (TagMap) Collect

func (m TagMap) Collect(tags ...Tag) ([]Definition, error)

Collect returns the requested tag definitions, in order.

If a tag is not present in the map an error is returned.

type Template

type Template struct {
	Tags    []Tag
	Volumes []Volume
}

Template describes a common set of values for a new virtual machine.

Templates are not fully implemented yet.

type UUID

type UUID = uuid.UUID

UUID is a 16 byte universally unique identifier.

type Vars

type Vars map[string]string

Vars hold a set of machine variables that can be expanded in various places.

func MergeVars

func MergeVars(sets ...Vars) Vars

MergeVars merges zero or more sets of variables in order. If more than one variable exists with the same name, only the first is included.

func (Vars) Map

func (v Vars) Map(s string) string

Map is a PatternMapper function for v.

type Volume

type Volume struct {
	Name         VolumeName         `json:"name"`
	Storage      StorageName        `json:"storage"`
	WWN          wwn.Value          `json:"wwn"`
	SerialNumber VolumeSerialNumber `json:"serial"`
	Bootable     bool               `json:"bootable"`
}

Volume describes a storage volume for a machine.

func MergeVolumes

func MergeVolumes(volumes ...Volume) []Volume

MergeVolumes merges a set of volumes in order. If more than one volume exists with the same name, only the first is included.

func (*Volume) Config

func (v *Volume) Config(out summary.Interface)

Config adds the volume configuration to the summary.

func (Volume) IsEmpty

func (v Volume) IsEmpty() bool

IsEmpty returns true if the volume is empty.

func (Volume) Populate

func (v Volume) Populate(seed Seed) Volume

Populate returns a copy of the volume with a world wide name and serial number, if not already present.

The provided machine seed is used to generate the identifiers.

func (Volume) String

func (v Volume) String() string

String returns a string representation of the volume configuration.

func (Volume) Vars

func (v Volume) Vars() Vars

Vars returns a set of volume variables. These can be used as variables for expansion.

type VolumeName

type VolumeName string

VolumeName is the name of a volume on a machine.

func (VolumeName) Vars

func (v VolumeName) Vars() Vars

Vars returns a volume name variable. This can be used a variable for expansion.

type VolumePath

type VolumePath string

VolumePath is the path to a volume within a storage pool.

type VolumeSerialNumber

type VolumeSerialNumber string

VolumeSerialNumber is the serial number of a volume on a machine.

Directories

Path Synopsis
cmd
Package mdevfs facilitates communication with mediated devices through the local sysfs file system.
Package mdevfs facilitates communication with mediated devices through the local sysfs file system.
Package qemu provides fundamental types for describing options to QEMU.
Package qemu provides fundamental types for describing options to QEMU.
qdev
Package qdev describes PCI Express device topologies of a QEMU guest.
Package qdev describes PCI Express device topologies of a QEMU guest.
qguest
Package qguest describes non-device properties of a QEMU guest.
Package qguest describes non-device properties of a QEMU guest.
qhost
Package qhost identifies and describes host resources that are contributed to a QEMU guest.
Package qhost identifies and describes host resources that are contributed to a QEMU guest.
qhost/blockdev
Package blockdev articulates the QEMU block layer.
Package blockdev articulates the QEMU block layer.
qhost/chardev
Package chardev desribes the QEMU character device layer.
Package chardev desribes the QEMU character device layer.
qvm
Package qemugen translates the high level concepts used by Machina into concrete virtual machine descriptions use by QEMU.
Package qemugen translates the high level concepts used by Machina into concrete virtual machine descriptions use by QEMU.
qmp
Package qmp implments part of the QEMU Machine Protocol Specification.
Package qmp implments part of the QEMU Machine Protocol Specification.
qmpcmd
Package qmpcmd defines a subset of possible QMP commands that are used by machina.
Package qmpcmd defines a subset of possible QMP commands that are used by machina.
qmpmsg
Package qmpmsg defines types used to marshal and umarshal QMP messages.
Package qmpmsg defines types used to marshal and umarshal QMP messages.
Package systemd facilitates systemd status queries via dbus.
Package systemd facilitates systemd status queries via dbus.

Jump to

Keyboard shortcuts

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