Documentation
¶
Overview ¶
Package winvm provides the Windows-VM (QEMU) runner backend: a golden Server Core image is baked once, ephemeral jobs run on throwaway copy-on-write overlays, and housekeeping keeps the golden image's eval license valid and its tools fresh.
Index ¶
- Variables
- func AutounattendFiles(runnerVersion, runnerSHA256, adminPassword string, tools []string) (map[string]string, error)
- func Bake(ctx context.Context, o BakeOptions, now time.Time) error
- func BuildISO(path, label string, files map[string]string) error
- func BuildISOFiles(path, label string, files map[string]string, fileRefs map[string]string) error
- func BuildJITISO(path, jit string, env map[string]string) error
- func DetectAccel(goos, goarch string) string
- func DetectOVMF(qemuBin string) (codeFD, varsTemplate string)
- func GoldenSerialPath(golden string) string
- func GoldenVarsPath(golden string) string
- func OverlayCreateArgs(golden, overlay string) []string
- func PlanBake(o *BakeOptions) (string, error)
- func Prepare(ctx context.Context, o *BakeOptions) (autoISO string, args []string, err error)
- func QEMUArgs(o LaunchOpts) []string
- func QMPBootKeys(addr string, presses int, every time.Duration) error
- func QMPEjectOnReset(addr, deviceID string, timeout time.Duration) error
- func QMPQuitNamed(ctx context.Context, addr, expectedName string) error
- func QMPScreenshot(addr, outPath string) error
- func RearmGolden(ctx context.Context, ref GoldenRef, now time.Time) error
- func RebuildGolden(ctx context.Context, ref GoldenRef, now time.Time) error
- func SaveMeta(golden string, m GoldenMeta) error
- func ToolsHash(o BakeOptions) (string, error)
- func ValidateToolSelectors(tools []string) error
- type Action
- type ActionFuncs
- type Backend
- func (b *Backend) CleanupOrphans()
- func (b *Backend) Close() error
- func (b *Backend) EnsureImage(ctx context.Context, _ string) error
- func (b *Backend) Launch(ctx context.Context, req backend.LaunchRequest) (backend.RunnerHandle, error)
- func (b *Backend) ListOwnedRunners(_ context.Context, ownership backend.RunnerOwnership) ([]backend.OwnedRunner, error)
- func (b *Backend) Name() string
- func (b *Backend) OSType(ctx context.Context) (string, error)
- func (b *Backend) Ping(ctx context.Context) error
- func (b *Backend) RemoveOwnedRunner(ctx context.Context, resourceID string) error
- type BakeOptions
- type Firmware
- type GoldenMeta
- type GoldenRef
- type Housekeeper
- type LaunchOpts
- type Options
- type Policy
Constants ¶
This section is empty.
Variables ¶
var DefaultRunnerSHA256 = imageVersionManifest.Minimal.Runner.WindowsX64SHA256
var DefaultRunnerVersion = imageVersionManifest.Minimal.Runner.Version
Functions ¶
func AutounattendFiles ¶
func AutounattendFiles(runnerVersion, runnerSHA256, adminPassword string, tools []string) (map[string]string, error)
AutounattendFiles returns the answer file + provisioning scripts with bake substitutions applied (for the autounattend ISO).
func Bake ¶
Bake builds the golden image: create base disk, boot the unattended installer, wait for it to finish (guest powers off), and write the metadata sidecar.
func BuildISO ¶
BuildISO writes an ISO containing the given files (name -> content). Used for the JIT config disk and the bake-time autounattend disk.
func BuildISOFiles ¶
BuildISOFiles writes an ISO with inline string files (name -> content) plus optional on-disk files (name -> host path) streamed from disk instead of held in memory — used to stage large binaries (runner/MinGit) onto the bake ISO so the guest reads them off the virtual CD instead of over the (slow) VM network.
func BuildJITISO ¶
BuildJITISO writes a tiny ISO carrying the JIT config blob and the runner env, attached to the VM as a CD-ROM. Pure Go (no mkisofs/oscdimg), so it works on Linux and Windows.
func DetectAccel ¶
DetectAccel picks the QEMU accelerator for this backend's x86-64 Windows guest. Hardware virtualization requires the host and guest CPU architectures to match, so ARM hosts use QEMU's cross-architecture TCG emulation, and an amd64 host only gets a hardware accelerator when that accelerator is actually usable. WHPX and HVF have no equivalent cheap probe, so they stay optimistic.
func DetectOVMF ¶
DetectOVMF locates UEFI firmware: the code blob and a vars template to copy. Searches the QEMU install's share dir and common Linux locations.
func GoldenSerialPath ¶
GoldenSerialPath is the bake's COM1 capture file. install-golden.ps1 writes progress markers here (MR:...), ending with MR:GOLDEN_OK on success, so the host can verify the bake finished without mounting the guest disk.
func GoldenVarsPath ¶
GoldenVarsPath is the UEFI NVRAM file paired with a golden image.
func OverlayCreateArgs ¶
OverlayCreateArgs builds the qemu-img args to create a clean copy-on-write overlay backed by the golden image (so each job starts from a pristine disk).
func PlanBake ¶
func PlanBake(o *BakeOptions) (string, error)
PlanBake validates bake inputs and describes its writes without creating disks, images, listeners, downloads, or processes.
func Prepare ¶
Prepare creates the base disk + autounattend ISO for a bake and returns the autounattend ISO path and the QEMU install args (without running QEMU).
func QEMUArgs ¶
func QEMUArgs(o LaunchOpts) []string
QEMUArgs builds the qemu-system-x86_64 args for a headless ephemeral runner VM. The guest auto-runs the runner and powers off after its one job; -no-reboot makes that power-off terminate QEMU so the backend's Wait returns.
func QMPBootKeys ¶
QMPBootKeys resets the VM and sends Enter repeatedly to satisfy Windows media's "Press any key to boot from CD or DVD" prompt (which otherwise times out and falls through to PXE/no-boot). Used during bake.
func QMPEjectOnReset ¶
QMPEjectOnReset connects to QMP and waits for the guest's first RESET event (Windows Setup rebooting after it applies the image to disk), then ejects the install CD with block-backend id deviceID. This stops later reboots from re-entering the DVD UEFI loader — which triple-faults under WHPX ("Unexpected VP exit code 4") — sending them to the now-bootable HDD instead. Returns after the eject, or when timeout elapses with no reset.
func QMPQuitNamed ¶
QMPQuitNamed stops only the QEMU process that reports the expected VM name. The QMP endpoint disappears with the process, avoiding unsafe PID-only kills during restart reconciliation.
func QMPScreenshot ¶
QMPScreenshot connects to a QEMU QMP endpoint and writes a PNG screenshot of the guest display to outPath. Used to observe headless VM installs.
func RearmGolden ¶
RearmGolden boots the golden image in place (writable, not an overlay) with a rearm marker ISO; the guest runs slmgr /rearm and powers off, resetting the eval clock. Must run while no jobs use the golden (drain first).
func RebuildGolden ¶
RebuildGolden re-bakes the golden from scratch (resets eval + tool fingerprint).
func SaveMeta ¶
func SaveMeta(golden string, m GoldenMeta) error
SaveMeta writes the golden image's metadata sidecar.
func ToolsHash ¶
func ToolsHash(o BakeOptions) (string, error)
ToolsHash fingerprints every input that changes the provisioned golden image. It is non-empty even without optional tools so template and runner updates rebuild existing minimal goldens.
func ValidateToolSelectors ¶
ValidateToolSelectors reports whether every golden tool selector resolves, so a typo in a pool's qemu.tools fails at config load instead of at bake time (or never, when the pool has no bake_iso).
Types ¶
type ActionFuncs ¶
type ActionFuncs struct {
Rearm func(ctx context.Context, ref GoldenRef, now time.Time) error
Rebuild func(ctx context.Context, ref GoldenRef, now time.Time) error
}
ActionFuncs are the housekeeping side effects (injectable for testing).
func DefaultActions ¶
func DefaultActions() ActionFuncs
DefaultActions wires the real rearm/rebuild operations.
type Backend ¶
type Backend struct {
// contains filtered or unexported fields
}
Backend runs ephemeral Windows runners as QEMU VMs (golden image + per-job copy-on-write overlay + JIT config ISO). It implements backend.Backend, so it plugs into the pool / autoscaler unchanged.
func NewBackend ¶
NewBackend builds the QEMU backend.
func (*Backend) CleanupOrphans ¶
func (b *Backend) CleanupOrphans()
CleanupOrphans clears leftover per-VM artifacts in the work dir at startup. A clean shutdown removes its overlay, JIT ISO, and NVRAM; its serial log stays for diagnosis until this next startup. Safe to delete at startup: no VM from this process is running yet.
func (*Backend) EnsureImage ¶
EnsureImage is a no-op for VMs (the golden image is produced by `bake`); it only checks the golden exists.
func (*Backend) Launch ¶
func (b *Backend) Launch(ctx context.Context, req backend.LaunchRequest) (backend.RunnerHandle, error)
Launch creates a clean overlay + JIT ISO and boots the VM. The guest runs its one job then powers off, which terminates QEMU (see -no-reboot).
func (*Backend) ListOwnedRunners ¶
func (b *Backend) ListOwnedRunners(_ context.Context, ownership backend.RunnerOwnership) ([]backend.OwnedRunner, error)
type BakeOptions ¶
type BakeOptions struct {
WindowsISO string // path to a Windows Server ISO (Server Core selected by the answer file)
WindowsISOSHA256 string // optional expected SHA256; the computed digest always enters the golden fingerprint
Golden string // output golden qcow2
DiskGB int
MemMB int
CPUs int
Accel string // "" = auto
RunnerVersion string
RunnerSHA256 string // required when RunnerVersion is not DefaultRunnerVersion
Tools []string // golden selectors: dotnet[:major] | node[:major] | go | buildtools[:line]
AdminPassword string
EvalDays int // 180 (server) / 90 (client)
MaxRearms int // ~5
Licensed bool // a real key/KMS is configured -> skip eval housekeeping
WorkflowsHash string
QEMUBin string
ImgBin string
OVMFCode string // UEFI firmware code (auto-detected if empty)
OVMFVarsTemplate string // UEFI vars template to copy
VNC string // raw VNC host:port; port 0 selects a free port
VNCWeb string // if set (host:port), serve a noVNC viewer to watch the install
VNCWebSocket string // resolved QEMU WebSocket host:port (set by Prepare)
Timeout time.Duration // max install wall-clock before the bake kills a hung guest (default: derived from Tools)
}
BakeOptions configures building (or rebuilding) a golden Windows image.
type Firmware ¶
type Firmware struct {
CodeFD string // read-only firmware code (edk2-x86_64-code.fd / OVMF_CODE.fd)
VarsFD string // writable per-VM NVRAM vars copy
}
Firmware holds UEFI (OVMF/edk2) firmware paths. CodeFD empty => legacy BIOS. UEFI is used for Windows because it skips the "Press any key to boot from CD" prompt that hangs unattended BIOS installs.
type GoldenMeta ¶
type GoldenMeta struct {
// CreatedAt is when the eval clock last reset (initial build or last rearm).
CreatedAt time.Time `json:"created_at"`
// EvalDays is the eval window length (180 for Server, 90 for client).
EvalDays int `json:"eval_days"`
// RearmsUsed / MaxRearms track remaining slmgr rearms.
RearmsUsed int `json:"rearms_used"`
MaxRearms int `json:"max_rearms"`
// Licensed is true when a real key/KMS is configured (eval housekeeping off).
Licensed bool `json:"licensed"`
// WorkflowsHash fingerprints the baked toolset so changes trigger a rebuild.
WorkflowsHash string `json:"workflows_hash"`
}
GoldenMeta is the sidecar metadata stored next to the golden image.
func LoadMeta ¶
func LoadMeta(golden string) (GoldenMeta, error)
LoadMeta reads the golden image's metadata sidecar (or a zero value if absent).
func (GoldenMeta) ApplyRearm ¶
func (m GoldenMeta) ApplyRearm(now time.Time) GoldenMeta
ApplyRearm records a rearm: reset the clock and consume one rearm.
func (GoldenMeta) ApplyRebuild ¶
func (m GoldenMeta) ApplyRebuild(now time.Time, wantHash string) GoldenMeta
ApplyRebuild records a fresh build: reset clock, rearms, and tool fingerprint.
type GoldenRef ¶
type GoldenRef struct {
Bake BakeOptions
}
GoldenRef ties a golden image to the bake options needed to rebuild it.
type Housekeeper ¶
type Housekeeper struct {
// contains filtered or unexported fields
}
Housekeeper periodically keeps golden images' eval licenses valid and tools fresh.
func NewHousekeeper ¶
func NewHousekeeper(refs []GoldenRef, policy Policy, every time.Duration, logger *slog.Logger) *Housekeeper
NewHousekeeper builds a Housekeeper (every<=0 disables periodic checks).
func (*Housekeeper) CheckOnce ¶
func (h *Housekeeper) CheckOnce(ctx context.Context)
CheckOnce evaluates every golden once and applies the chosen action.
func (*Housekeeper) Run ¶
func (h *Housekeeper) Run(ctx context.Context)
Run checks once immediately, then on each interval until ctx is cancelled.
type LaunchOpts ¶
type LaunchOpts struct {
Golden string // base (golden) qcow2, read-only backing file
Overlay string // per-job copy-on-write overlay qcow2
JITISOPath string // config ISO carrying the JIT blob
Name string // process identity returned by QMP
QMPAddr string // loopback QMP endpoint used for restart cleanup
PIDFile string // QEMU-owned process ID record
MemMB int
CPUs int
Accel string // "" = tcg; callers normally resolve host-compatible auto mode
Firmware Firmware
}
LaunchOpts describes one ephemeral Windows VM launch.
type Options ¶
type Options struct {
Golden string // path to the golden qcow2 (built by `multirunner bake`)
WorkDir string // where per-job overlays/ISOs are written
MemMB int
CPUs int
Accel string // "" = auto-detect (kvm/whpx/hvf on x86-64, tcg on ARM)
QEMUBin string // qemu-system-x86_64 (default looked up on PATH)
ImgBin string // qemu-img (default looked up on PATH)
}
Options configures the QEMU Windows-VM backend.