vmshared

package
v0.2026286.932 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 23 Imported by: 10

Documentation

Overview

Code-assisted alias surface for the CUE-single-source cutover (WF-B THE REPOINT).

Every charly hand param struct that has a spec counterpart is now a zero-churn Go type alias onto charly/spec — the generated (cue exp gengotypes) types plus the hand-written union/state types, exposed under their charly names via spec/charly_names.go. The hand struct DEFINITIONS were deleted; these aliases keep every existing reference (`BoxConfig{…}`, `[]ServiceEntry`, …) compiling against the single CUE source of truth. Pure methods moved INTO package spec; methods that reach package-main internals are free functions here taking a *spec.X. See CHANGELOG.

NOT aliased (name collisions where the package-main type is a DIFFERENT concept, kept hand-written): CalVer (version.go computation struct, vs the spec.CalVer scalar), CandyRef (refs.go ref struct, vs the spec.CandyRef scalar), Candy (layers.go resolved-candy runtime struct, vs spec.Candy the param — aliased as CandyYAML instead).

Index

Constants

View Source
const (
	PollLocal  = poll.PollLocal
	PollRemote = poll.PollRemote
	PollHeavy  = poll.PollHeavy

	ReadinessAbsoluteCapFallback     = poll.ReadinessAbsoluteCapFallback
	ReadinessIntervalHeavyFallback   = poll.ReadinessIntervalHeavyFallback
	ReadinessIntervalLocalFallback   = poll.ReadinessIntervalLocalFallback
	ReadinessIntervalRemoteFallback  = poll.ReadinessIntervalRemoteFallback
	ReadinessNoProgressFallback      = poll.ReadinessNoProgressFallback
	ReadinessPerAttemptFallback      = poll.ReadinessPerAttemptFallback
	ReadinessPerAttemptHeavyFallback = poll.ReadinessPerAttemptHeavyFallback
	ReadinessStopGraceFallback       = poll.ReadinessStopGraceFallback
)
View Source
const VmImageDirEnv = "CHARLY_VM_IMAGE_DIR"

VmImageDirEnv overrides the VM image root (the "vm.image_dir" setting's env counterpart, mirroring CHARLY_VM_STATE_DIR). Relative values resolve against the working project; absolute values pin it globally.

View Source
const VmStateDirEnv = "CHARLY_VM_STATE_DIR"

vm_state_root.go — the ONE root-path resolver for per-VM host state (~/.local/share/charly/vm/<domain>/ — ssh keys, known_hosts, seed ISO, the per-domain disk overlay, snapshots/, instance.yml). Bed-robustness batch item 6 (the "global ~/.local/share/charly/vm non-worktree-scoping footgun"): a libvirt DOMAIN name is derived PURELY from the deploy name (VmDomainIdentity), with no project/worktree component, so two concurrent checkouts (separate `git worktree`s, the project's own standing multi-worktree / multi-teammate development model) that happen to run the SAME bed/deploy name — the common case, since bed names like "check-charly-vm" are fixed identifiers shared across every worktree of the same repo — collide on the SAME host state directory (and, more severely, the SAME libvirt domain). VmStateRoot is the single override point: set CHARLY_VM_STATE_DIR to a worktree-distinct path (e.g. in a per-worktree wrapper/.envrc) and every VM state file for that invocation lands under it instead of the shared default — the SAME env-var-override pattern already established for CHARLY_REPO_CACHE / CHARLY_REPO_OVERRIDE / CHARLY_PROJECT_DIR. Default behavior (no env var set) is UNCHANGED — this is purely additive, zero-risk for the common single-worktree case. Every VM state-path call site (charly core, candy/plugin-vm, candy/plugin-deploy-vm, this package's own vm_snapshot.go) routes through this ONE function (R3 — the literal `filepath.Join(home, ".local", "share", "charly", "vm")` was previously duplicated across 7+ files) so the override applies uniformly, never partially.

Variables

View Source
var (
	BoolPtrDefaultTrue       = boolPtrDefaultTrue
	BoolPtrToYesNo           = boolPtrToYesNo
	BoolPtrTrue              = boolPtrTrue
	ComposePackages          = composePackages
	ComposeRunCmd            = composeRunCmd
	ComposeUsers             = composeUsers
	DefaultMachineForArch    = defaultMachineForArch
	FormatForDistroID        = hostenv.FormatForDistroID
	LoadRegistry             = loadRegistry
	OpenOutputPath           = openOutputPath
	OvmfCandidatesForDistro  = ovmfCandidatesForDistro
	ParseGlibcVersion        = hostenv.ParseGlibcVersion
	RegistryPath             = registryPath
	ResolveCloudInitSSHUser  = resolveCloudInitSSHUser
	ResolveCPUDefaults       = resolveCPUDefaults
	SaveRegistry             = saveRegistry
	SnapshotExternalDiskPath = snapshotExternalDiskPath
	SnapshotsDir             = snapshotsDir
	SplitOsReleaseLine       = hostenv.SplitOsReleaseLine
	SplitPortForward         = splitPortForward
	VmDiskPath               = vmDiskPath
	WriterForPath            = writerForPath
)

Re-exported functions.

View Source
var (
	CreateInternalSnapshot    func(opts SnapshotCreateOpts) error
	DeleteInternalSnapshot    func(vmName string, entry *SnapshotEntry) error
	RevertInternalSnapshot    func(vmName string, entry *SnapshotEntry) error
	PromoteInternalToExternal func(vmName string, entry *SnapshotEntry, outPath string) error
	CreateExternalSnapshot    func(opts SnapshotCreateOpts, outFile string) error
	DeleteExternalSnapshot    func(vmName string, entry *SnapshotEntry) error
	RevertExternalSnapshot    func(vmName string, entry *SnapshotEntry) error
)

Snapshot backends. Core wires host-side RPC wrappers (vm_snapshot_client.go) that drive the out-of-process plugin; the plugin wires the in-process go-libvirt implementations (vm_snapshot_internal.go / vm_snapshot_libvirt.go).

View Source
var (
	ErrPollStalled     = poll.ErrPollStalled
	ErrPollCapExceeded = poll.ErrPollCapExceeded
	ErrPollFatal       = poll.ErrPollFatal
	ErrPollConfig      = poll.ErrPollConfig

	// ResolveReadiness + PollUntil are re-exported functions (the resolver + the
	// poll driver).
	ResolveReadiness = poll.ResolveReadiness
	PollUntil        = poll.PollUntil
)
View Source
var CompareGlibc = hostenv.CompareGlibc

CompareGlibc re-exports hostenv.CompareGlibc. See spec/hostenv/hostdistro.go.

View Source
var DetectHostDistro = hostenv.DetectHostDistro

DetectHostDistro re-exports hostenv.DetectHostDistro. See spec/hostenv/hostdistro.go.

View Source
var DetectHostGlibc = hostenv.DetectHostGlibc

DetectHostGlibc re-exports hostenv.DetectHostGlibc. See spec/hostenv/hostdistro.go.

View Source
var ParseLibvirtURI = spec.ParseLibvirtURI

ParseLibvirtURI re-exports spec.ParseLibvirtURI. See spec/spec/libvirt_uri.go.

View Source
var SnapshotBackingStaleProbe = SnapshotBackingStalePath

SnapshotBackingStaleProbe reports the stale backing file (non-empty == stale) for an external snapshot, or ("", nil) when fresh. Defaults to SnapshotBackingStalePath (the qemu-img --backing-chain mtime probe); it is a seam so the capture path's stale-re-capture decision is unit-testable without a real qcow2 chain on disk. A consumer that does not override it gets the real probe — the seam is only for tests.

View Source
var SplitVmAddress = spec.SplitVmAddress

SplitVmAddress re-exports spec.SplitVmAddress. See spec/spec/vm_domain.go.

View Source
var StartLibvirtUserSession = hostenv.StartLibvirtUserSession

StartLibvirtUserSession re-exports hostenv.StartLibvirtUserSession. Stubbable per-package (a caller that stubs THIS var must also call THIS var — plugin-vm does). See spec/hostenv/libvirt_session.go.

View Source
var UnmarshalEmbeddedDefaults func(dst any)

UnmarshalEmbeddedDefaults decodes the consumer's embedded build vocabulary (the ovmf_paths directive the OVMF resolver reads) into dst. Core reads its embedded charly.yml; the plugin reads its embedded build_defaults.yml.

It used to decode ovmf_distro_aliases too. That half is now spec.DistroOvmfFamilies, generated from the distro vocabulary, so this hook covers the PATH data only.

View Source
var ValidateEgress func(kind, label string, data []byte) error

ValidateEgress gates a generated cloud-init document against its CUE egress schema before the bytes are emitted (RenderCloudInit in cloud_init_render.go).

View Source
var VmDomainIdentity = spec.VmDomainIdentity
View Source
var VmNameFromDeployName = spec.VmNameFromDeployName

VmNameFromDeployName re-exports spec.VmNameFromDeployName. See spec/spec/vm_domain.go.

Functions

func DecrementSnapshotRefcount

func DecrementSnapshotRefcount(vmName, snapName string) error

DecrementSnapshotRefcount decreases the refcount. Floors at 0.

func DeleteSnapshot

func DeleteSnapshot(opts SnapshotDeleteOpts) error

DeleteSnapshot is the mode-aware deletion. Refuses while refcount > 0 unless Force is set.

func DetectRuntimeHostVendor

func DetectRuntimeHostVendor() string

DetectRuntimeHostVendor reads /proc/cpuinfo to identify the host CPU vendor (GenuineIntel | AuthenticAMD | ""). Used by RenderDomain / RenderQemuArgv to auto-append the correct nested-virt feature (vmx vs svm).

func EnsurePerVmNvram

func EnsurePerVmNvram(templatePath, perVmDir string) (string, error)

EnsurePerVmNvram copies the OVMF_VARS template to a per-VM NVRAM file on first use. Returns the absolute path of the per-VM NVRAM (which is what rt.NVRAMPath should be set to). Idempotent: if the per-VM file already exists, it's preserved (contains the guest's accumulated UEFI variables).

func IncrementSnapshotRefcount

func IncrementSnapshotRefcount(vmName, snapName string) error

IncrementSnapshotRefcount increases the refcount on the named snapshot. Used by clone/ephemeral instantiation paths.

func IsDeviceElement

func IsDeviceElement(snippet string) bool

IsDeviceElement returns true if the XML snippet's root element belongs inside <devices>.

func KeyToRootTmpfilesD

func KeyToRootTmpfilesD(pubkey string) string

KeyToRootTmpfilesD converts an SSH public key to a systemd tmpfiles.d config that creates /root/.ssh/authorized_keys. Matches bcvk's key_to_root_tmpfiles_d.

func KeyToUserTmpfilesD

func KeyToUserTmpfilesD(user, home, pubkey string) string

KeyToUserTmpfilesD generates a systemd tmpfiles.d config that delivers a per-VM SSH key for the named user. The user account itself must already exist in the rootfs (created at build time by the bootloader install template OR by cloud-init); this function only delivers the *key*, never bakes one into the image.

SMBIOS-vs-cloud-init priority: the key is written to a ROOT-owned, sshd- checked file at /etc/ssh/authorized_keys.d/<user>, and a sshd_config.d drop-in widens AuthorizedKeysFile to check BOTH ~/.ssh/authorized_keys (cloud-init's domain) AND that file. systemd-tmpfiles applies this BEFORE sshd starts, so the SMBIOS key is ALWAYS accepted even if cloud-init later rewrites the user's own authorized_keys — SMBIOS owns the drop-in location, cloud-init owns ~/.ssh, and sshd honors both. The key is ALSO written to ~/.ssh/authorized_keys as a fallback for any guest sshd that ignores the drop-in (so the key works whether or not the widened path takes effect).

The home path defaults to /home/<user> when empty.

func KillQemuByPID

func KillQemuByPID(stateDir string)

KillQemuByPID force-kills a direct-QEMU VM by the PID recorded in its state dir (the last-resort path when QMP graceful/force shutdown is unavailable). Pure OS process kill — no govmm.

func LibvirtSessionSocket

func LibvirtSessionSocket() string

LibvirtSessionSocket returns the path to the user's libvirt session socket. Modern libvirt (≥ 8.0) uses per-driver modular daemons (virtqemud-sock); legacy libvirt (< 8.0) uses the monolithic libvirt-sock. Probe the modular socket first (every current distro), then the monolithic one. Returns "" when neither exists — never a path that was not found.

func LibvirtSessionSocketWithProbes

func LibvirtSessionSocketWithProbes() (picked string, probed []string)

func QemuAlive added in v0.2026226.1201

func QemuAlive(stateDir string) bool

QemuAlive reports whether the QEMU process recorded in <stateDir>/qemu.pid is still running AND is the process that pidfile belongs to.

A pidfile alone is not liveness, and neither is a bare Signal(0) probe: PIDs are recycled, so a dead VM's stale pidfile can name a PID that now belongs to something else entirely. Two checks close that:

  1. Signal(0) — the PID exists and is signalable.
  2. /proc/<pid>/cmdline contains "-pidfile <stateDir>/qemu.pid" — the running process is not merely SOME qemu, it is the qemu started for THIS state dir. Matching the bare "qemu-system" substring is not enough: a PID recycled onto a DIFFERENT VM's qemu would satisfy it, and the caller would treat a stopped VM as running.

The second check rests on a CALLER invariant, not a renderer guarantee, and the distinction matters to anyone adding a launch path. RenderQemuArgv appends `-pidfile` CONDITIONALLY — `if paths.PidFile != ""` (qemu_render.go) — so an empty PidFile is explicitly permitted there. What makes the argv reliable is that every production launch sets it: VmRuntimePaths.PidFile is always `<vmStateDir>/qemu.pid`, byte-identical to what this function computes, and `vm start` relaunches from the persisted command file rendered with that same argv. A future caller that leaves PidFile empty would make QemuAlive report its VMs DEAD — the worse failure direction, since callers act on "not running" by starting a second qemu. Set PidFile, or teach this predicate the new launch shape.

/proc/<pid>/cmdline is NUL-separated, so the flag and its value are two adjacent NUL-terminated entries rather than one space-joined string.

Shared by `vm start` (the idempotent already-running guard), `vm list` (the state scan), and the preempt arbiter's holder probe — one liveness predicate, R3. A weaker copy in any of them means one caller can believe a stopped VM is running (or the reverse) while another does not.

func QemuSystemBinary

func QemuSystemBinary() string

QemuSystemBinary returns the architecture-appropriate QEMU binary name.

func RenderCloudInit

func RenderCloudInit(spec *VmSpec, rt CloudInitRuntimeParams) (userData, metaData, networkConfig string, err error)

RenderCloudInit produces the three NoCloud seed ISO payloads from a VmSpec plus runtime parameters. Pure function — no filesystem or network calls.

- userData → written to cidata/user-data (prefixed with #cloud-config) - metaData → written to cidata/meta-data (instance-id + hostname) - networkCfg → written to cidata/network-config (optional; empty if unset)

Defaults applied automatically (D15):

  1. VmSsh.User added to users: with sudo + ssh_authorized_keys (if the key-injection channel is enabled AND SSHPublicKey != "")

  2. Minimum packages: {<ssh-pkg>, curl, tar} unioned with the user's Packages, where <ssh-pkg> is `openssh-server` on debian/ubuntu and `openssh` elsewhere. Delivered via the `packages:` cloud-config key on every distro EXCEPT pacman-family (arch/archarm/manjaro/endeavouros/cachyos), where it is instead PREPENDED to runcmd as `pacman -Sy --needed --noconfirm <union>` (db refresh + install-only; a bare -S 404s on rotated mirrors, and a full -Syu destabilizes the live guest — see the runcmd comment) and the `packages:` key is omitted entirely. Why: cloud-init's own package-install module invokes `pacman -S` without `--needed`, so on an image that already ships the minimum set it REINSTALLS them, and reinstalling openssh re-triggers its host-key-regen hook while the base image's socket-activated sshd is already listening — racing a live key-file rewrite against new connections. apt/dnf installs are naturally no-op-idempotent when the package is present, so only the pacman-family path needs the rewrite.

    The branch reads Source.Distro DIRECTLY. That field is REQUIRED and closed to #DistroID (schema/vm.cue), so there is nothing to infer: an omitted or misspelled distro is a validation error at author time. An earlier revision left it optional and inferred `arch`/`alpine` from base_user, defaulting everything else to Arch/Fedora conventions — which rendered `openssh` and `enable --now sshd` onto Debian-family guests and left them unreachable. That inference is DELETED, not narrowed — the renderer no longer guesses a distro.

  3. Minimum runcmd: the sshd START prepended (after the pacman install command on pacman-family distros, per #2). On systemd it is `systemctl enable --now <unit>` — `ssh` on debian/ubuntu, `sshd` elsewhere, chosen by sshUnitForDistro from the required Source.Distro. On OpenRC (Alpine) it is `rc-update add sshd default && rc-service sshd start`.

  4. charly_install: NOT a cloud-init concern — the vm deploy's PrepareVenue delivers charly post-boot (auto/scp stage it; skip verifies). No charly download runcmd.

  5. VmCloudInit.Extra: raw cloud-config YAML appended as a second document (separated by ---) if non-empty

func RenderInstallerSeed added in v0.2026242.940

func RenderInstallerSeed(inst *spec.DistroInstaller, ctx spec.InstallerSeedContext) (map[string]string, error)

RenderInstallerSeed renders a distro's unattended-installer answers volume.

The split is deliberate and is the whole design: the DISTRO owns the FORMAT (which files, with what names, in what syntax — archinstall JSON, kickstart, preseed, Subiquity autoinstall), and the VM ENTITY owns the DATA (this username, this disk, these SSH keys). A renderer that guessed the format from the distro name is the failure mode validateSourceDistro's own comment records as having burned this codebase already.

Pure: no filesystem, no network, no crypt(). The caller hashes the password before building ctx, so a PLAINTEXT password never reaches a template, a log, or a temp file.

Returns path-inside-the-volume -> rendered content, ready for WriteLabeledISO.

func RenderQemuArgv

func RenderQemuArgv(spec *VmSpec, rt VmRuntimeParams, paths QemuRuntimePaths) []string

RenderQemuArgv produces the full argv for `qemu-system-<arch>` from a VmSpec + VmRuntimeParams + QemuRuntimePaths. Pure function — no filesystem or process state side effects.

Covers the intersection of libvirt schema features that map cleanly to QEMU: machine, cpu (D16 defaults), firmware (D17 pflash), disks (root + seed iso D5 + additional), network (user-mode hostfwd), SMBIOS credentials (D13), RNG, balloon, qemu-guest-agent channel.

Structured libvirt features without a QEMU mapping (virtiofs, launch_security beyond SEV, PCI hostdev, graphics/spice, TPM) are skipped with a warning comment inserted via the caller's log output — this function only returns argv.

func ResolveKeyInjectionChannels

func ResolveKeyInjectionChannels(spec *VmSpec) (smbios, cloudInit bool)

ResolveKeyInjectionChannels applies the D13 auto-defaults and explicit-wins merging to produce the effective (smbios, cloudInit) toggle state for a VmSpec. Returns the booleans persisted into VmDeployState.KeyInjectionResolved.

func ResolveOvmfForSpec

func ResolveOvmfForSpec(spec *VmSpec, vmStateDir string) (codePath, nvramPath string, err error)

ResolveOvmfForSpec is a convenience wrapper: detects the host distro, picks the correct OVMF_CODE/OVMF_VARS pair for the VmSpec's firmware setting, and provisions the per-VM NVRAM file. Returns (CodePath, NVRAMPath) — the two values needed to populate VmRuntimeParams.

Returns ("", "", nil) when firmware == "bios" (BIOS boot needs no firmware images).

func ResolveVmCpus

func ResolveVmCpus(spec *VmSpec) int

ResolveVmCpus picks the spec-declared CPU count or falls back to 2.

func ResolveVmRam

func ResolveVmRam(spec *VmSpec) string

ResolveVmRam picks the spec-declared RAM or falls back to "4G".

func RevertSnapshot

func RevertSnapshot(vmName, snapName string) error

RevertSnapshot is the mode-aware revert.

func SeedFileNames added in v0.2026242.940

func SeedFileNames(files map[string]string) []string

SeedFileNames returns the rendered file paths in sorted order. Only for diagnostics and tests — the ISO writer sorts internally so its output is reproducible.

func SmbiosCredForSSH

func SmbiosCredForSSH(user, home, pubkey string) string

SmbiosCredForSSH generates the SMBIOS type 11 credential string that delivers a per-VM SSH key to the named user via systemd-tmpfiles. When user == "" or user == "root", the key is delivered to /root/.ssh. Returns: "io.systemd.credential.binary:tmpfiles.extra=<base64>"

func SnapshotBackingStalePath added in v0.2026258.1713

func SnapshotBackingStalePath(entry *SnapshotEntry) (string, error)

SnapshotBackingStalePath reports whether an external snapshot's backing chain has been REBUILT after the snapshot was captured, returning the offending backing file path. A non-empty return means the snapshot is STALE.

Why a snapshot goes stale: the guest filesystem captured inside the snapshot (btrfs, ext4) references inodes in the BASE disks of its backing chain. When a later `vm build` rewrites one of those base disks (a re-provision, a disk-root change), the snapshot's superblock still points at the OLD data, so any clone backed by it boots into a broken/grub-rescue guest. The mtime ordering — a backing file newer than the snapshot's `Created` — is the detectable proxy.

This is the ONE staleness definition (R3). The clone path (candy/plugin-vm) and the capture path (CreateSnapshot below) MUST agree on it: the clone guard already refuses a stale snapshot with an actionable error, so if capture did not also treat the same snapshot as stale it would refuse to refresh it (`already exists`), making the clone guard's promised recovery impossible.

Second-precision comparison: the registry stores `Created` at RFC3339 second precision while a capture-finalization write can land sub-second later, so a same-second mtime is NOT stale (a false STALE would force needless re-captures).

func VmDiskDir

func VmDiskDir(vmName string) (string, error)

VmDiskDir returns the per-VM directory holding a built disk image (disk.qcow2) and, for cloud_image/bootstrap/clone sources, its NoCloud seed.iso. The path is namespaced by the DISK SOURCE (the kind:vm ENTITY), so it is the shared read-only BASE every per-deploy overlay backs onto — building or creating one entity never reuses a SIBLING entity's disk or — critically — its stale seed.iso, whose embedded SSH key would mismatch this VM's own id_ed25519 and silently break the deploy's authentication.

The root is CONFIGURABLE (vm.image_dir setting / CHARLY_VM_IMAGE_DIR env, default "image") — never a hardcoded literal (the former "output" default was a footgun: it read as disposable build scratch, so it got deleted as such while live VMs' backing chains still pointed into it). The (string, error) shape mirrors VmStateRoot: a root-resolution failure is PROPAGATED, never silently substituted with a different root (which would point a live VM at a path its backing chain does not use — the exact failure mode this replaces).

func VmDiskRoot added in v0.2026258.154

func VmDiskRoot() (string, error)

VmDiskRoot resolves the root directory for built VM disk images. Precedence: the CHARLY_VM_IMAGE_DIR env var > the `vm.image_dir` config setting > the built-in default "image". A relative result is intentionally returned as-is: call sites resolve it against the working project (the disk is a build product of the project's own VMs), exactly like the former hardcoded relative path.

A MISSING config is not an error (LoadRuntimeConfig returns a zero config, nil) — the "image" default applies. A non-nil error means the config file exists but could not be read; that is PROPAGATED (never masked by substituting a root).

func VmStateRoot added in v0.2026203.730

func VmStateRoot() (string, error)

VmStateRoot resolves the root directory for per-VM host state. Honors CHARLY_VM_STATE_DIR when set (trimmed, must be non-empty, must be absolute — a relative override would resolve against whatever cwd happens to be active at each call site, defeating the whole point of a stable per-worktree pin); otherwise falls back to the default ~/.local/share/charly/vm.

func WriteJSON

func WriteJSON(w io.Writer, v any) error

WriteJSON encodes v as indented JSON to w (the `--json` output helper; the `charly vm snapshot list --json` path uses it).

func WriteLabeledISO added in v0.2026242.940

func WriteLabeledISO(outPath, volumeID string, files map[string]string) error

WriteLabeledISO packs files into an ISO9660+Joliet+RockRidge image at outPath, labelled volumeID. The map is path-inside-the-volume -> content; keys must be plain names or relative paths, and content is written verbatim.

The LABEL is what an unattended installer discovers the volume by — "CIDATA" for cloud-init NoCloud, "OEMDRV" for Anaconda kickstart — so it is a parameter rather than a constant. Case is preserved exactly as given: xorriso's -volid writes what it is handed, verified both ways, which is why a distro's #DistroInstaller.volume_id can be matched case-sensitively without needing a vfat fallback.

func WriteSeedISO

func WriteSeedISO(outPath, userData, metaData, networkConfig string) error

WriteSeedISO builds a NoCloud cidata ISO at outPath. Takes the three rendered strings from RenderCloudInit (user-data, meta-data, and optional network-config) and shells out to xorriso to pack them into an ISO9660+Joliet+RockRidge image labeled cloudInitVolumeID.

The guest's cloud-init scans for a filesystem labeled "CIDATA" or "cidata" (it tries both cases) on first boot. Files inside:

user-data       — the #cloud-config YAML (required)
meta-data       — instance-id + hostname (required, can be empty)
network-config  — v2 network schema (optional)

Returns an error if xorriso isn't installed or the ISO write fails. charly doctor checks for xorriso and suggests the install package.

This is a thin convenience over WriteLabeledISO: cloud-init's NoCloud datasource is one answers-volume format among several, and an unattended distro installer (archinstall, kickstart, preseed, autoinstall) wants the same ISO writer with a different label and a different file set. There is exactly ONE ISO writer here, and this is its NoCloud face.

Types

type AURPackages

type AURPackages = spec.AUR

type AgentConfig

type AgentConfig = spec.Agent

type AliasConfig

type AliasConfig = spec.AliasConfig

type AliasYAML

type AliasYAML = spec.AliasYAML

type AlpineBootstrapDef

type AlpineBootstrapDef = spec.AlpineBootstrap

type AndroidAdbEndpoint

type AndroidAdbEndpoint = spec.AdbEndpoint

--- nested types renamed in spec (charly name != cue-def name) ---

type AndroidGoogleAccount

type AndroidGoogleAccount = spec.GoogleAccount

type AndroidSpec

type AndroidSpec = spec.AndroidSpec

type ApkPackageSpec

type ApkPackageSpec = spec.ApkPackageSpec

type BaseUserDef

type BaseUserDef = spec.BaseUser

type BootloaderDef

type BootloaderDef = spec.Bootloader

type BootstrapDef

type BootstrapDef = spec.Bootstrap

type BoxConfig

type BoxConfig = spec.BoxConfig

type BuildStageContext added in v0.2026189.748

type BuildStageContext = spec.BuildStageContext

type BuilderDef

type BuilderDef = spec.BuilderDef

type CacheMountDef

type CacheMountDef = spec.CacheMount

type CandyArtifact

type CandyArtifact = spec.CandyArtifact

type CandyArtifactRewrite

type CandyArtifactRewrite = spec.CandyArtifactRewrite

type CandyCapabilities

type CandyCapabilities = spec.CandyCapabilities

type CandyPluginDecl

type CandyPluginDecl = spec.Plugin

type CandyYAML

type CandyYAML = spec.CandyYAML

type CloudInitRuntimeParams

type CloudInitRuntimeParams = spec.CloudInitRuntimeParams

CloudInitRuntimeParams — SPIKE (value-type relocation, #55 cluster 4): relocated to spec.CloudInitRuntimeParams (spec/spec/cloud_init_runtime_params.go). Zero-churn alias; RenderCloudInit (behavior) is unaffected.

type CopyDef

type CopyDef = spec.Copy

type CredentialMount

type CredentialMount = spec.CredentialMount

type DataYAML

type DataYAML = spec.DataYAML

type DebootstrapDef

type DebootstrapDef = spec.Debootstrap

type DebootstrapRepo

type DebootstrapRepo = spec.DebootstrapRepo

type DeployExpose

type DeployExpose = spec.DeployExpose

type DeployNode added in v0.2026250.527

type DeployNode = spec.DeployNode

type DeployProbes

type DeployProbes = spec.DeployProbes

type DeployResources

type DeployResources = spec.DeployResources

type DeploySecretConfig

type DeploySecretConfig = spec.DeploySecret

type DeployStorage

type DeployStorage = spec.DeployStorage

type DeployVolumeConfig

type DeployVolumeConfig = spec.DeployVolume

type DistroDef

type DistroDef = spec.ResolvedDistro

type DistroPackages

type DistroPackages = spec.DistroPackages

type DnfConfig

type DnfConfig = spec.Dnf

type EnvDependency

type EnvDependency = spec.EnvDependency

type EphemeralLifetime

type EphemeralLifetime = spec.EphemeralLifetime

type EphemeralRuntime

type EphemeralRuntime = spec.EphemeralRuntime

type ExtractYAML

type ExtractYAML = spec.ExtractYAML

type FormatDef

type FormatDef = spec.Format

type FormatRule

type FormatRule = spec.FormatRule

type GpuSelector

type GpuSelector = spec.GpuSelector

type HooksConfig

type HooksConfig = spec.HooksConfig

type HostDistro

type HostDistro = hostenv.HostDistro

HostDistro re-exports hostenv.HostDistro (its PopulateTags/PrimaryTag/FormatHint methods ride the alias). See spec/hostenv/hostdistro.go.

type InitDef

type InitDef = spec.InitDef

type InstallContext added in v0.2026189.748

type InstallContext = spec.InstallContext

type InstallOptsConfig

type InstallOptsConfig = spec.InstallOptsConfig

type IterateConfig

type IterateConfig = spec.IterateConfig

type KubernetesDeployConfig added in v0.2026223.1626

type KubernetesDeployConfig = spec.KubernetesDeploy

type KubernetesGatewayAPI added in v0.2026223.1626

type KubernetesGatewayAPI = spec.KubernetesGatewayAPI

type KubernetesHostname added in v0.2026223.1626

type KubernetesHostname = spec.KubernetesHostname

type KubernetesImagesDefaults added in v0.2026223.1626

type KubernetesImagesDefaults = spec.KubernetesImagesDefaults

type KubernetesIngressDefaults added in v0.2026223.1626

type KubernetesIngressDefaults = spec.KubernetesIngressDefaults

type KubernetesObservability added in v0.2026223.1626

type KubernetesObservability = spec.KubernetesObservability

type KubernetesPatch added in v0.2026223.1626

type KubernetesPatch = spec.KubernetesPatch

type KubernetesPodDefaults added in v0.2026223.1626

type KubernetesPodDefaults = spec.KubernetesPodDefaults

type KubernetesResourceDefaults added in v0.2026223.1626

type KubernetesResourceDefaults = spec.KubernetesResourceDefaults

type KubernetesResourceValues added in v0.2026223.1626

type KubernetesResourceValues = spec.KubernetesResourceValues

type KubernetesResources added in v0.2026223.1626

type KubernetesResources = spec.KubernetesResources

type KubernetesSecretsBackend added in v0.2026223.1626

type KubernetesSecretsBackend = spec.KubernetesSecretsBackend

type KubernetesSpec added in v0.2026223.1626

type KubernetesSpec = spec.KubernetesSpec

type KubernetesStorage added in v0.2026223.1626

type KubernetesStorage = spec.KubernetesStorage

type LibvirtAudio

type LibvirtAudio = spec.LibvirtAudio

type LibvirtCPU

type LibvirtCPU = spec.LibvirtCPU

type LibvirtCPUCache

type LibvirtCPUCache = spec.LibvirtCPUCache

type LibvirtCPUFeature

type LibvirtCPUFeature = spec.LibvirtCPUFeature

type LibvirtCPUTopology

type LibvirtCPUTopology = spec.LibvirtCPUTopology

type LibvirtCPUTune

type LibvirtCPUTune = spec.LibvirtCPUTune

type LibvirtChannel

type LibvirtChannel = spec.LibvirtChannel

type LibvirtClock

type LibvirtClock = spec.LibvirtClock

type LibvirtConsole

type LibvirtConsole = spec.LibvirtConsole

type LibvirtDevices

type LibvirtDevices = spec.LibvirtDevices

type LibvirtDisk

type LibvirtDisk = spec.LibvirtDisk

type LibvirtDomain

type LibvirtDomain = spec.LibvirtDomain

type LibvirtEmulatorPin

type LibvirtEmulatorPin = spec.LibvirtEmulatorPin

type LibvirtFeatures

type LibvirtFeatures = spec.LibvirtFeatures

type LibvirtFilesystem

type LibvirtFilesystem = spec.LibvirtFilesystem

type LibvirtGraphics

type LibvirtGraphics = spec.LibvirtGraphics

type LibvirtGraphicsGL added in v0.2026240.2009

type LibvirtGraphicsGL = spec.LibvirtGraphicsGL

type LibvirtGraphicsListen

type LibvirtGraphicsListen = spec.LibvirtGraphicsListen

type LibvirtGraphicsListeners

type LibvirtGraphicsListeners = spec.LibvirtGraphicsListeners

type LibvirtHostdev

type LibvirtHostdev = spec.LibvirtHostdev

type LibvirtHub

type LibvirtHub = spec.LibvirtHub

type LibvirtHugepages

type LibvirtHugepages = spec.LibvirtHugepages

type LibvirtHyperV

type LibvirtHyperV = spec.LibvirtHyperV

type LibvirtIOMMU

type LibvirtIOMMU = spec.LibvirtIOMMU

type LibvirtIOThreadPin

type LibvirtIOThreadPin = spec.LibvirtIOThreadPin

type LibvirtInput

type LibvirtInput = spec.LibvirtInput

type LibvirtInterface

type LibvirtInterface = spec.LibvirtInterface

type LibvirtKVM

type LibvirtKVM = spec.LibvirtKVM

type LibvirtLaunchSecurity

type LibvirtLaunchSecurity = spec.LibvirtLaunchSecurity

type LibvirtMemBalloon

type LibvirtMemBalloon = spec.LibvirtMemBalloon

type LibvirtMemTune

type LibvirtMemTune = spec.LibvirtMemTune

type LibvirtMemnode

type LibvirtMemnode = spec.LibvirtMemnode

type LibvirtMemoryBacking

type LibvirtMemoryBacking = spec.LibvirtMemoryBacking

type LibvirtNUMACell

type LibvirtNUMACell = spec.LibvirtNUMACell

type LibvirtNUMAMemory

type LibvirtNUMAMemory = spec.LibvirtNUMAMemory

type LibvirtNUMATune

type LibvirtNUMATune = spec.LibvirtNUMATune

type LibvirtPanic

type LibvirtPanic = spec.LibvirtPanic

type LibvirtParallel

type LibvirtParallel = spec.LibvirtParallel

type LibvirtPortForward

type LibvirtPortForward = spec.LibvirtPortForward

type LibvirtRNG

type LibvirtRNG = spec.LibvirtRNG

type LibvirtRedirDev

type LibvirtRedirDev = spec.LibvirtRedirDev

type LibvirtResource

type LibvirtResource = spec.LibvirtResource

type LibvirtSecLabel

type LibvirtSecLabel = spec.LibvirtSecLabel

type LibvirtSerial

type LibvirtSerial = spec.LibvirtSerial

type LibvirtShmem

type LibvirtShmem = spec.LibvirtShmem

type LibvirtSmartcard

type LibvirtSmartcard = spec.LibvirtSmartcard

type LibvirtSound

type LibvirtSound = spec.LibvirtSound

type LibvirtSpinlocks

type LibvirtSpinlocks = spec.LibvirtSpinlocks

type LibvirtSysInfo

type LibvirtSysInfo = spec.LibvirtSysInfo

type LibvirtTPM

type LibvirtTPM = spec.LibvirtTPM

type LibvirtTimer

type LibvirtTimer = spec.LibvirtTimer

type LibvirtURI

type LibvirtURI = spec.LibvirtURI

LibvirtURI re-exports spec.LibvirtURI (its IsLocal method rides the alias). See spec/spec/libvirt_uri.go.

type LibvirtUSB

type LibvirtUSB = spec.LibvirtUSB

type LibvirtVCPUPin

type LibvirtVCPUPin = spec.LibvirtVCPUPin

type LibvirtVendorID

type LibvirtVendorID = spec.LibvirtVendorID

type LibvirtVideo

type LibvirtVideo = spec.LibvirtVideo

type LibvirtVideoDriver added in v0.2026240.2009

type LibvirtVideoDriver = spec.LibvirtVideoDriver

type LibvirtVideoResolution added in v0.2026240.2009

type LibvirtVideoResolution = spec.LibvirtVideoResolution

type LibvirtVsock

type LibvirtVsock = spec.LibvirtVsock

type LibvirtWatchdog

type LibvirtWatchdog = spec.LibvirtWatchdog

type LocalPkgDef

type LocalPkgDef = spec.LocalPkg

type LocalSpec

type LocalSpec = spec.LocalSpec

type MCPServerYAML

type MCPServerYAML = spec.MCPServerYAML

type Matcher

type Matcher = spec.Matcher

type MatcherList

type MatcherList = spec.MatcherList

type MergeConfig

type MergeConfig = spec.MergeConfig

type Op

type Op = spec.Op

type OvmfPaths

type OvmfPaths struct {
	// CodePath is the OVMF_CODE firmware image. Read-only.
	CodePath string

	// VarsTemplate is the OVMF_VARS template with standard UEFI CA
	// keys pre-enrolled (when secure=true). The per-VM NVRAM file is
	// copied from this template on first VM create.
	VarsTemplate string

	// Secure indicates whether this is the secure-boot-enabled variant.
	Secure bool
}

OvmfPaths is the pair of firmware image paths needed to boot a UEFI VM: OVMF_CODE (read-only, shared across all VMs) and an OVMF_VARS template (read-only, copied to a per-VM writable NVRAM file on first VM create).

func ResolveOvmfPaths

func ResolveOvmfPaths(distroID string, secure bool) (OvmfPaths, error)

ResolveOvmfPaths picks the correct OVMF_CODE + OVMF_VARS paths for the host distro + secure-boot setting. Returns an error when no candidate path exists on disk so `charly vm create` fails with a clean remediation hint instead of a cryptic QEMU pflash error.

D17 path table:

Fedora         /usr/share/OVMF/OVMF_CODE{.secboot,}.fd
               /usr/share/OVMF/OVMF_VARS{.secboot,}.fd
Arch           /usr/share/edk2/x64/OVMF_CODE{.secboot,}.4m.fd
               /usr/share/edk2/x64/OVMF_VARS.4m.fd
Debian/Ubuntu  /usr/share/OVMF/OVMF_CODE_4M{.ms,}.fd
               /usr/share/OVMF/OVMF_VARS_4M{.ms,}.fd

type PackageItem

type PackageItem = spec.PackageItem

type PacstrapDef

type PacstrapDef = spec.Pacstrap

type PacstrapRepo

type PacstrapRepo = spec.PacstrapRepo

type PhaseSet

type PhaseSet = spec.PhaseSet

type PhaseTemplates

type PhaseTemplates = spec.PhaseTemplates

type PodSpec

type PodSpec = spec.PodSpec

type PollClass

type PollClass = poll.PollClass

type PollCondition

type PollCondition = poll.PollCondition

type PollConfig

type PollConfig = poll.PollConfig

type PortScope

type PortScope = spec.PortScope

type PortSpec

type PortSpec = spec.PortSpec

type PreemptibleConfig

type PreemptibleConfig = spec.PreemptibleConfig

type QemuRuntimePaths

type QemuRuntimePaths struct {
	// MonitorSocket — unix socket for the QEMU monitor (`-monitor`).
	MonitorSocket string

	// QmpSocket — unix socket for QMP (`-qmp`).
	QmpSocket string

	// ConsoleSocket — unix socket for the serial console (`-serial`).
	ConsoleSocket string

	// PidFile — `-pidfile` target.
	PidFile string
}

QemuRuntimePaths carries backend-specific paths that QEMU needs but libvirt doesn't (socket paths, pidfile). Composed with VmRuntimeParams when the QEMU backend renders its argv.

type ReadinessConfig

type ReadinessConfig = spec.ReadinessConfig

type ResolvedReadiness

type ResolvedReadiness = poll.ResolvedReadiness

type ResourceDef

type ResourceDef = spec.ResourceDef

type RouteYAML

type RouteYAML = spec.RouteYAML

type SSHTarget

type SSHTarget = spec.SSHTarget

SSHTarget aliases spec.SSHTarget — the parsed "[user@]host[:port]" form.

type SecretYAML

type SecretYAML = spec.SecretYAML

type SecurityConfig

type SecurityConfig = spec.SecurityConfig

type ServiceEntry

type ServiceEntry = spec.ServiceEntry

type ServiceOverrides

type ServiceOverrides = spec.CandyServiceOverrides

type ServiceSchemaDef

type ServiceSchemaDef = spec.InitServiceSchema

type ShellConfig

type ShellConfig = spec.Shell

type ShellSpec

type ShellSpec = spec.ShellSpec

type SidecarConfig

type SidecarConfig = spec.PodSidecar

type SidecarDef

type SidecarDef = spec.SidecarDef

type SidecarSecret

type SidecarSecret = spec.SidecarSecret

type SidecarVolume

type SidecarVolume = spec.SidecarVolume

type SnapshotCreateOpts

type SnapshotCreateOpts struct {
	// VmName is the kind:vm entity name (without charly- prefix).
	VmName string

	// SnapName is the new snapshot's name.
	SnapName string

	// Mode is "external" or "internal" — empty defaults to external.
	Mode string

	// Description is an optional human note.
	Description string

	// Quiesce, when true, requests guest-agent fsfreeze before
	// snapshotting (with libvirt's plain freeze as fallback).
	Quiesce bool

	// LibvirtBackend, when non-nil, overrides the auto-detected backend.
	// Default: probe via the caller's own backend-resolve (candy/plugin-vm's
	// resolveVmBackendPlugin).
	LibvirtBackend string
}

SnapshotCreateOpts parameterizes the creation of a snapshot.

type SnapshotDeleteOpts

type SnapshotDeleteOpts struct {
	VmName   string
	SnapName string
	// Force allows deletion even when refcount > 0. Default false.
	// Recommended only when the consuming clones/ephemerals have
	// already been destroyed and the registry is stale.
	Force bool
}

SnapshotDeleteOpts parameterizes deletion.

type SnapshotEntry

type SnapshotEntry struct {
	// Name uniquely identifies the snapshot within this VM.
	Name string `json:"name"`

	// Mode is "external" or "internal".
	Mode string `json:"mode"`

	// LibvirtName is the snapshot's name as known to libvirt. For
	// external mode, libvirt registers the snapshot as a domain
	// snapshot and we store the libvirt-side identifier here. For
	// internal mode, this matches Name (qemu-img embeds the literal
	// name).
	LibvirtName string `json:"libvirt_name,omitempty"`

	// DiskPath is the absolute path to the external snapshot file.
	// Empty for internal-mode snapshots.
	DiskPath string `json:"disk_path,omitempty"`

	// Description carries the operator-supplied note.
	Description string `json:"description,omitempty"`

	// Created is the RFC3339 creation timestamp.
	Created string `json:"created,omitempty"`

	// Parent is the prior snapshot in the implicit chain at create
	// time (whichever was current then). Informational; helps trace
	// backing-chain ancestry.
	Parent string `json:"parent,omitempty"`

	// Refcount tracks active clones / ephemerals depending on this
	// snapshot. delete refuses while > 0.
	Refcount int `json:"refcount"`

	// Quiesced records whether the snapshot was taken with guest-agent
	// fsfreeze active. Informational; helps an operator decide
	// whether the snapshot is consistent.
	Quiesced bool `json:"quiesced,omitempty"`
}

SnapshotEntry is one snapshot record. Mirrors VmSnapshotState plus on-disk-only fields (the registry is internal; VmSnapshotState is the charly.yml-facing mirror).

func CreateSnapshot

func CreateSnapshot(opts SnapshotCreateOpts) (*SnapshotEntry, error)

CreateSnapshot is the mode-aware orchestrator for `charly vm snapshot create`. Looks up the active VM, dispatches to the matching mode- specific implementation, and records the result in registry.json + meta.json.

func ListSnapshots

func ListSnapshots(vmName string) ([]*SnapshotEntry, error)

ListSnapshots returns the snapshots for a VM as a name-sorted slice.

func LookupSnapshot

func LookupSnapshot(vmName, snapName string) (*SnapshotEntry, error)

LookupSnapshot returns a snapshot entry by name or an error.

func PromoteSnapshot

func PromoteSnapshot(vmName, snapName string) (*SnapshotEntry, error)

PromoteSnapshot converts an internal snapshot to external mode by extracting it via `qemu-img convert` to a new qcow2 file in the snapshots directory. After promotion, the snapshot is usable as a clone backing target. The internal snapshot inside the primary qcow2 is left in place — promote is non-destructive.

type SnapshotRegistry

type SnapshotRegistry struct {
	// Version is the registry schema version. V1 is the initial release.
	Version int `json:"version"`

	// Snapshots is the unified set of snapshots known to charly for this
	// VM, keyed by Name. Both modes appear here.
	Snapshots map[string]*SnapshotEntry `json:"snapshots"`
}

SnapshotRegistry is the on-disk schema for snapshots/registry.json. Versioned so future shape evolutions can migrate cleanly.

type Step

type Step = spec.Step

type StepKeyword

type StepKeyword = spec.StepKeyword

type TunnelYAML

type TunnelYAML = spec.TunnelYAML

type VmCharlyInstall

type VmCharlyInstall = spec.VmCharlyInstall

type VmChecksum

type VmChecksum = spec.VmChecksum

type VmCloudInit

type VmCloudInit = spec.VmCloudInit

type VmCloudInitFile

type VmCloudInitFile = spec.VmCloudInitFile

type VmCloudInitMirrors

type VmCloudInitMirrors = spec.VmCloudInitMirrors

type VmCloudInitNetwork

type VmCloudInitNetwork = spec.VmCloudInitNetwork

type VmCloudInitUser

type VmCloudInitUser = spec.VmCloudInitUser

type VmDeployState

type VmDeployState = spec.VmDeployState

type VmKeyInjection

type VmKeyInjection = spec.VmKeyInjection

type VmKeyInjectionResolved

type VmKeyInjectionResolved = spec.VmKeyInjectionResolved

type VmNetwork

type VmNetwork = spec.VmNetwork

type VmRuntimeParams

type VmRuntimeParams struct {
	// Name is the libvirt domain name / QEMU process handle.
	Name string

	// QCOW2Path is the absolute path to the VM's root qcow2 disk.
	QCOW2Path string

	// SeedISOPath is the absolute path to the NoCloud cidata ISO.
	// Empty → no cdrom attached (bootc source with cloud-init disabled).
	SeedISOPath string

	// InstallerISOPath is the absolute path to a distro's OFFICIAL INSTALLER ISO, for
	// source.kind: iso. Empty for every other source kind, which is why it is a separate
	// field rather than a reuse of SeedISOPath: an iso VM attaches BOTH — the installer
	// AND, on its own cdrom, the answers volume that makes the install unattended.
	//
	// Its presence also changes the BOOT ORDER to disk-then-cdrom. That is the whole
	// mechanism by which an ISO install terminates: an empty disk is not bootable, so the
	// firmware falls through to the installer on the first boot; once the installer has
	// written the disk, the disk boots and the ISO is never reached again. Nothing has to
	// detect that the install finished, and nothing has to eject or detach anything.
	InstallerISOPath string

	// NVRAMPath is the absolute path to the per-VM UEFI NVRAM file.
	// Empty → firmware: bios (no pflash drives emitted).
	NVRAMPath string

	// OVMFCodePath is the absolute path to the OVMF_CODE firmware image.
	// Required when Firmware == "uefi-*"; empty when bios.
	OVMFCodePath string

	// HostArch is the host architecture string (e.g. "x86_64", "aarch64").
	HostArch string

	// HostCPUVendor is "GenuineIntel" | "AuthenticAMD" | "". Used to
	// auto-append +vmx or +svm in resolveCPUDefaults when mode defaults
	// to host-passthrough and the user hasn't explicitly disabled nested
	// virt.
	HostCPUVendor string

	// SMBIOSCredentials are pre-formatted systemd-credential oemString
	// entries (e.g. "io.systemd.credential.binary:tmpfiles.extra=<b64>").
	SMBIOSCredentials []string

	// RamMB is the resolved RAM in MiB (VmSpec.Ram parsed).
	RamMB int

	// Cpus is the resolved vCPU count (VmSpec.Cpus with defaults applied).
	Cpus int

	// SSHPort is the host port forwarded to guest :22.
	SSHPort int

	// ExtraPortForwards are additional "host:guest" TCP forwards on
	// top of the SSH port. Used with user-mode networking.
	ExtraPortForwards []string

	// VmStateDir is the absolute path to the per-VM state directory
	// (~/.local/share/charly/vm/charly-<name>/). Used by the libvirt YAML
	// bridge to expand `{{.VmStateDir}}` template references in
	// path-bearing libvirt attributes (channel <source path=>,
	// graphics socket paths). Populated by the create-time caller
	// (vm_create_spec.go::runVmSpecCreate) so author-supplied paths
	// stay portable across users without hardcoded /home/<x>.
	VmStateDir string
}

VmRuntimeParams carries the runtime-resolved state that the libvirt-XML and QEMU-argv emitters need but isn't in the author's VmSpec: the VM name, disk paths, SSH pubkey, host architecture, host CPU vendor, etc. Both RenderDomainXML (libvirt) and RenderQEMUArgs (qemu) consume the same struct so the "rendered from a common source" invariant is preserved.

type VmSnapshotDecl

type VmSnapshotDecl = spec.VmSnapshotDecl

type VmSnapshotState

type VmSnapshotState = spec.VmSnapshotState

type VmSource

type VmSource = spec.VmSource

type VmSpec

type VmSpec = spec.ResolvedVm

type VmSsh added in v0.2026232.552

type VmSsh = spec.VmSsh

type VolumeYAML

type VolumeYAML = spec.VolumeYAML

Jump to

Keyboard shortcuts

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