Documentation
¶
Overview ¶
Package winkit is the winkit engine: Windows guests built and booted by go-winkit (vz on macOS hosts, qemu on Linux hosts). It runs two guests, chosen by engine.Cell.Guest:
- engine.WindowsPE: a WinPE boot volume with a WSL1 nix distro (winkit stage pe-wsl). The default.
- engine.WindowsFull: a full Windows install with a WSL1 nix distro (winkit stage full-wsl).
Both import the distro as "winkit" and run the agent in it with `wsl -d winkit`. They differ in the build stage, the template directory, and the SSH channel the agent command runs over (see guest).
Index ¶
- Constants
- func CacheDir(home string) string
- func DownloadVirtioDrivers(ctx context.Context, home string, noCache bool, obs Observer) (string, error)
- func DownloadWindowsISO(ctx context.Context, home, language string, obs Observer) (string, error)
- func InstanceDir(home, cellName string) string
- func ResolveWindowsISO(envISO, configISO, home string) (string, error)
- func StopVM(ctx context.Context, home, cellName string) error
- func ValidateISO(path string) error
- func VirtioISOPath(home string) string
- type AllocatedPorts
- type DiscoveredVM
- type Engine
- type NopObserver
- type Observer
- type VMPorts
Constants ¶
const WindowsISODownloadURL = "https://www.microsoft.com/en-us/software-download/windows11arm64"
WindowsISODownloadURL is the Microsoft page for downloading Windows 11 ARM64 ISO. Kept for the manual-download fallback message in ResolveWindowsISO.
Variables ¶
This section is empty.
Functions ¶
func CacheDir ¶
CacheDir returns the QEMU media cache directory.
DEVCELL_WINKIT_CACHE_DIR points it somewhere shared. Inside a cell $HOME is itself a per-cell directory, so the default renders as ~/.devcell/<cell>/.devcell/cache/qemu and every cell re-downloads the same ~6 GB of immutable media. There is no way to reach the real host home from inside the container, so the location has to be pointable rather than inferred (CELL-386).
func DownloadVirtioDrivers ¶
func DownloadVirtioDrivers(ctx context.Context, home string, noCache bool, obs Observer) (string, error)
DownloadVirtioDrivers returns the cached VirtIO drivers ISO at VirtioISOPath, downloading it via winkit when missing or unusable. noCache discards the cached ISO first to force a fresh download.
func DownloadWindowsISO ¶
DownloadWindowsISO returns a cached Windows 11 ARM64 install ISO with complete media, downloading and assembling it when missing.
winkit's media.FetchWindowsISO serves the MCT catalog lane, which yields complete media, and its cache. Its UUP dump fallback (taken when the MCT catalog fails) builds boot-only media with no sources/install.wim, and the PE+WSL1 build extracts install.wim from the ISO, so boot-only media cannot feed it. Until winkit's fallback can assemble complete media, devcell runs UUP dump itself with BootOnly off whenever winkit returns boot-only media or fails. That ISO lives in fullMediaDir because both UUP dump lanes give their ISO the same file name and winkit's cache check cannot tell them apart.
func InstanceDir ¶
InstanceDir returns the per-cell instance directory for Windows VMs. It is also winkit's state dir for the cell's VM (StartOpts.StateDir). Layout: ~/.devcell/<cellName>/windows/
func ResolveWindowsISO ¶
ResolveWindowsISO resolves the Windows ARM64 ISO path. Priority: env DEVCELL_WINKIT_WINDOWS_ISO > config path > cached download > error.
The cached download is looked up without touching the network: `cell build` must not start the multi-gigabyte download `cell init` owns.
func StopVM ¶
StopVM gracefully shuts down a running Windows VM for the given cell. It tries SSH shutdown first, then SIGTERM, then Kill.
func ValidateISO ¶
ValidateISO checks that a file carries a recognised disc format by reading the volume descriptor at sector 16 (offset 0x8001). Both ISO 9660 (CD001) and UDF (BEA01/NSR02/NSR03) are accepted — Windows ARM64 ISOs built by UUP dump are pure UDF.
func VirtioISOPath ¶
VirtioISOPath returns the path to the cached VirtIO drivers ISO, where winkit's media.FetchVirtioISO puts it.
Types ¶
type AllocatedPorts ¶
AllocatedPorts holds the cell-ID-derived port strings for SSH, VNC, and RDP.
func AllocatePorts ¶
func AllocatePorts(portPrefix string, taken map[int]struct{}) AllocatedPorts
AllocatePorts computes SSH, VNC, and RDP ports using the same cell-ID-based scheme as the Docker runner. portPrefix is SESSION_PORT_PREFIX + cellID. The taken map (may be nil) lists ports already in use by other processes.
func (AllocatedPorts) RDPPortUint16 ¶
func (p AllocatedPorts) RDPPortUint16() uint16
RDPPortUint16 returns the RDP port as uint16.
func (AllocatedPorts) SSHPortUint16 ¶
func (p AllocatedPorts) SSHPortUint16() uint16
SSHPortUint16 returns the SSH port as uint16.
func (AllocatedPorts) VNCPortUint16 ¶
func (p AllocatedPorts) VNCPortUint16() uint16
VNCPortUint16 returns the VNC port as uint16.
type DiscoveredVM ¶
DiscoveredVM is a running Windows VM found in a cell's instance dir.
func DiscoverRunningVMs ¶
func DiscoverRunningVMs(home string) []DiscoveredVM
DiscoverRunningVMs lists the live VMs winkit has registered under each cell's instance dir (~/.devcell/<cell>/windows/, see InstanceDir), which devcell passes to winkit.Start as the state dir.
func RunningVMForImage ¶
func RunningVMForImage(home, image string) (DiscoveredVM, bool)
RunningVMForImage returns a live VM, in any cell, booted from image.
type Engine ¶
type Engine struct{}
Engine implements engine.Engine for engine.Winkit.
func (Engine) Run ¶
Run boots the cell's Windows guest via go-winkit and runs the agent in its WSL1 distro over SSH.
Lifecycle:
- Acquire the image (build it when missing)
- Boot the VM via winkit.Start, wait for the guest's SSH channel
- Run the agent inside WSL1 over that channel
Two args belong to cell and are taken out of opts.Args (takeRunArgs): --force sets opts.Force, and --stack=<name> overrides opts.Cell.Stack. opts.Force builds a missing image without asking. opts.Rebuild, opts.Update and opts.Background are not honored yet; the VM this call started is stopped when the agent exits. A non-zero agent exit is *engine.ExitError.
Off macOS with opts.Debug, every step is simulated and logged with a [MOCK] prefix; on macOS, opts.Debug logs the real steps via ux.Debugf.
type NopObserver ¶
type NopObserver struct{}
NopObserver silently discards all events.
func (NopObserver) Logf ¶
func (NopObserver) Logf(string, ...any)
func (NopObserver) Progress ¶
func (NopObserver) Progress(float64, string)