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
- Variables
- func DecrementSnapshotRefcount(vmName, snapName string) error
- func DeleteSnapshot(opts SnapshotDeleteOpts) error
- func DetectRuntimeHostVendor() string
- func EnsurePerVmNvram(templatePath, perVmDir string) (string, error)
- func IncrementSnapshotRefcount(vmName, snapName string) error
- func IsDeviceElement(snippet string) bool
- func KeyToRootTmpfilesD(pubkey string) string
- func KeyToUserTmpfilesD(user, home, pubkey string) string
- func KillQemuByPID(stateDir string)
- func LibvirtSessionSocket() string
- func LibvirtSessionSocketWithProbes() (picked string, probed []string)
- func QemuAlive(stateDir string) bool
- func QemuSystemBinary() string
- func RenderCloudInit(spec *VmSpec, rt CloudInitRuntimeParams) (userData, metaData, networkConfig string, err error)
- func RenderInstallerSeed(inst *spec.DistroInstaller, ctx spec.InstallerSeedContext) (map[string]string, error)
- func RenderQemuArgv(spec *VmSpec, rt VmRuntimeParams, paths QemuRuntimePaths) []string
- func ResolveKeyInjectionChannels(spec *VmSpec) (smbios, cloudInit bool)
- func ResolveOvmfForSpec(spec *VmSpec, vmStateDir string) (codePath, nvramPath string, err error)
- func ResolveVmCpus(spec *VmSpec) int
- func ResolveVmRam(spec *VmSpec) string
- func RevertSnapshot(vmName, snapName string) error
- func SeedFileNames(files map[string]string) []string
- func SmbiosCredForSSH(user, home, pubkey string) string
- func SnapshotBackingStalePath(entry *SnapshotEntry) (string, error)
- func VmDiskDir(vmName string) (string, error)
- func VmDiskRoot() (string, error)
- func VmStateRoot() (string, error)
- func WriteJSON(w io.Writer, v any) error
- func WriteLabeledISO(outPath, volumeID string, files map[string]string) error
- func WriteSeedISO(outPath, userData, metaData, networkConfig string) error
- type AURPackages
- type AgentConfig
- type AliasConfig
- type AliasYAML
- type AlpineBootstrapDef
- type AndroidAdbEndpoint
- type AndroidGoogleAccount
- type AndroidSpec
- type ApkPackageSpec
- type BaseUserDef
- type BootloaderDef
- type BootstrapDef
- type BoxConfig
- type BuildStageContext
- type BuilderDef
- type CacheMountDef
- type CandyArtifact
- type CandyArtifactRewrite
- type CandyCapabilities
- type CandyPluginDecl
- type CandyYAML
- type CloudInitRuntimeParams
- type CopyDef
- type CredentialMount
- type DataYAML
- type DebootstrapDef
- type DebootstrapRepo
- type DeployExpose
- type DeployNode
- type DeployProbes
- type DeployResources
- type DeploySecretConfig
- type DeployStorage
- type DeployVolumeConfig
- type DistroDef
- type DistroPackages
- type DnfConfig
- type EnvDependency
- type EphemeralLifetime
- type EphemeralRuntime
- type ExtractYAML
- type FormatDef
- type FormatRule
- type GpuSelector
- type HooksConfig
- type HostDistro
- type InitDef
- type InstallContext
- type InstallOptsConfig
- type IterateConfig
- type KubernetesDeployConfig
- type KubernetesGatewayAPI
- type KubernetesHostname
- type KubernetesImagesDefaults
- type KubernetesIngressDefaults
- type KubernetesObservability
- type KubernetesPatch
- type KubernetesPodDefaults
- type KubernetesResourceDefaults
- type KubernetesResourceValues
- type KubernetesResources
- type KubernetesSecretsBackend
- type KubernetesSpec
- type KubernetesStorage
- type LibvirtAudio
- type LibvirtCPU
- type LibvirtCPUCache
- type LibvirtCPUFeature
- type LibvirtCPUTopology
- type LibvirtCPUTune
- type LibvirtChannel
- type LibvirtClock
- type LibvirtConsole
- type LibvirtDevices
- type LibvirtDisk
- type LibvirtDomain
- type LibvirtEmulatorPin
- type LibvirtFeatures
- type LibvirtFilesystem
- type LibvirtGraphics
- type LibvirtGraphicsGL
- type LibvirtGraphicsListen
- type LibvirtGraphicsListeners
- type LibvirtHostdev
- type LibvirtHub
- type LibvirtHugepages
- type LibvirtHyperV
- type LibvirtIOMMU
- type LibvirtIOThreadPin
- type LibvirtInput
- type LibvirtInterface
- type LibvirtKVM
- type LibvirtLaunchSecurity
- type LibvirtMemBalloon
- type LibvirtMemTune
- type LibvirtMemnode
- type LibvirtMemoryBacking
- type LibvirtNUMACell
- type LibvirtNUMAMemory
- type LibvirtNUMATune
- type LibvirtPanic
- type LibvirtParallel
- type LibvirtPortForward
- type LibvirtRNG
- type LibvirtRedirDev
- type LibvirtResource
- type LibvirtSecLabel
- type LibvirtSerial
- type LibvirtShmem
- type LibvirtSmartcard
- type LibvirtSound
- type LibvirtSpinlocks
- type LibvirtSysInfo
- type LibvirtTPM
- type LibvirtTimer
- type LibvirtURI
- type LibvirtUSB
- type LibvirtVCPUPin
- type LibvirtVendorID
- type LibvirtVideo
- type LibvirtVideoDriver
- type LibvirtVideoResolution
- type LibvirtVsock
- type LibvirtWatchdog
- type LocalPkgDef
- type LocalSpec
- type MCPServerYAML
- type Matcher
- type MatcherList
- type MergeConfig
- type Op
- type OvmfPaths
- type PackageItem
- type PacstrapDef
- type PacstrapRepo
- type PhaseSet
- type PhaseTemplates
- type PodSpec
- type PollClass
- type PollCondition
- type PollConfig
- type PortScope
- type PortSpec
- type PreemptibleConfig
- type QemuRuntimePaths
- type ReadinessConfig
- type ResolvedReadiness
- type ResourceDef
- type RouteYAML
- type SSHTarget
- type SecretYAML
- type SecurityConfig
- type ServiceEntry
- type ServiceOverrides
- type ServiceSchemaDef
- type ShellConfig
- type ShellSpec
- type SidecarConfig
- type SidecarDef
- type SidecarSecret
- type SidecarVolume
- type SnapshotCreateOpts
- type SnapshotDeleteOpts
- type SnapshotEntry
- type SnapshotRegistry
- type Step
- type StepKeyword
- type TunnelYAML
- type VmCharlyInstall
- type VmChecksum
- type VmCloudInit
- type VmCloudInitFile
- type VmCloudInitMirrors
- type VmCloudInitNetwork
- type VmCloudInitUser
- type VmDeployState
- type VmKeyInjection
- type VmKeyInjectionResolved
- type VmNetwork
- type VmRuntimeParams
- type VmSnapshotDecl
- type VmSnapshotState
- type VmSource
- type VmSpec
- type VmSsh
- type VolumeYAML
Constants ¶
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 )
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.
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 ¶
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.
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).
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 )
var CompareGlibc = hostenv.CompareGlibc
CompareGlibc re-exports hostenv.CompareGlibc. See spec/hostenv/hostdistro.go.
var DetectHostDistro = hostenv.DetectHostDistro
DetectHostDistro re-exports hostenv.DetectHostDistro. See spec/hostenv/hostdistro.go.
var DetectHostGlibc = hostenv.DetectHostGlibc
DetectHostGlibc re-exports hostenv.DetectHostGlibc. See spec/hostenv/hostdistro.go.
var ParseLibvirtURI = spec.ParseLibvirtURI
ParseLibvirtURI re-exports spec.ParseLibvirtURI. See spec/spec/libvirt_uri.go.
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.
var SplitVmAddress = spec.SplitVmAddress
SplitVmAddress re-exports spec.SplitVmAddress. See spec/spec/vm_domain.go.
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.
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.
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).
var VmDomainIdentity = spec.VmDomainIdentity
var VmNameFromDeployName = spec.VmNameFromDeployName
VmNameFromDeployName re-exports spec.VmNameFromDeployName. See spec/spec/vm_domain.go.
Functions ¶
func DecrementSnapshotRefcount ¶
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 ¶
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 ¶
IncrementSnapshotRefcount increases the refcount on the named snapshot. Used by clone/ephemeral instantiation paths.
func IsDeviceElement ¶
IsDeviceElement returns true if the XML snippet's root element belongs inside <devices>.
func KeyToRootTmpfilesD ¶
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 ¶
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 QemuAlive ¶ added in v0.2026226.1201
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:
- Signal(0) — the PID exists and is signalable.
- /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):
VmSsh.User added to users: with sudo + ssh_authorized_keys (if the key-injection channel is enabled AND SSHPublicKey != "")
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.
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`.
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.
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 ¶
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 ¶
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 ¶
ResolveVmCpus picks the spec-declared CPU count or falls back to 2.
func ResolveVmRam ¶
ResolveVmRam picks the spec-declared RAM or falls back to "4G".
func RevertSnapshot ¶
RevertSnapshot is the mode-aware revert.
func SeedFileNames ¶ added in v0.2026242.940
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 ¶
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 ¶
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
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
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 ¶
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
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 ¶
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 AgentConfig ¶
type AliasConfig ¶
type AliasConfig = spec.AliasConfig
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 BootloaderDef ¶
type BootloaderDef = spec.Bootloader
type BootstrapDef ¶
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 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 CredentialMount ¶
type CredentialMount = spec.CredentialMount
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 EnvDependency ¶
type EnvDependency = spec.EnvDependency
type EphemeralLifetime ¶
type EphemeralLifetime = spec.EphemeralLifetime
type EphemeralRuntime ¶
type EphemeralRuntime = spec.EphemeralRuntime
type ExtractYAML ¶
type ExtractYAML = spec.ExtractYAML
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 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 MCPServerYAML ¶
type MCPServerYAML = spec.MCPServerYAML
type MatcherList ¶
type MatcherList = spec.MatcherList
type MergeConfig ¶
type MergeConfig = spec.MergeConfig
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 ¶
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 PacstrapRepo ¶
type PacstrapRepo = spec.PacstrapRepo
type PhaseTemplates ¶
type PhaseTemplates = spec.PhaseTemplates
type PollCondition ¶
type PollCondition = poll.PollCondition
type PollConfig ¶
type PollConfig = poll.PollConfig
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 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 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 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 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 VmSpec ¶
type VmSpec = spec.ResolvedVm
type VolumeYAML ¶
type VolumeYAML = spec.VolumeYAML
Source Files
¶
- cloud_init_iso.go
- cloud_init_render.go
- exports.go
- hooks.go
- hostdistro.go
- installer_seed_render.go
- libvirt_helpers.go
- libvirt_session.go
- libvirt_uri.go
- libvirt_yaml.go
- libvirt_yaml_listen.go
- output_path.go
- ovmf_paths.go
- poll_reexport.go
- qemu_liveness.go
- qemu_render.go
- qemu_render_gpu.go
- smbios_credentials.go
- spec_aliases.go
- ssh_target.go
- vm_deploy_addressing.go
- vm_domain_reexport.go
- vm_helpers.go
- vm_snapshot.go
- vm_state_root.go