vm defaults: host-aware sizing + spec line on spawn + doctor check
Replaces the static model.Default* constants that drove --vcpu / --memory / --disk-size with a three-layer resolver: 1. [vm_defaults] in ~/.config/banger/config.toml (if set) 2. host-derived heuristics (cpus/4 capped at 4; ram/8 capped at 8 GiB) 3. baked-in constants (floor) Visibility: - Every `vm run` / `vm create` prints a `spec:` line before progress begins: `spec: 4 vcpu · 8192 MiB · 8G disk`. Matches the VM that actually gets created because the CLI is now the single source of truth — it resolves, populates the flag defaults, and forwards the explicit values to the daemon. - `banger doctor` adds a "vm defaults" check showing per-field provenance (config|auto|builtin) and the config file path for overrides. - `--help` shows the resolved defaults (e.g. `--vcpu int (default 4)` on an 8-core host). No `banger config init` command, no first-run side effects, no writes to the user's filesystem behind their back. Users who want explicit control set the keys; everyone else gets sensible numbers that track their hardware.
This commit is contained in:
parent
78ff482bfa
commit
21b74639d8
10 changed files with 594 additions and 56 deletions
|
|
@ -34,6 +34,7 @@ type fileConfig struct {
|
|||
TapPoolSize int `toml:"tap_pool_size"`
|
||||
DefaultDNS string `toml:"default_dns"`
|
||||
FileSync []fileSyncEntryFile `toml:"file_sync"`
|
||||
VMDefaults *vmDefaultsFile `toml:"vm_defaults"`
|
||||
}
|
||||
|
||||
type fileSyncEntryFile struct {
|
||||
|
|
@ -42,6 +43,16 @@ type fileSyncEntryFile struct {
|
|||
Mode string `toml:"mode"`
|
||||
}
|
||||
|
||||
// vmDefaultsFile mirrors the optional `[vm_defaults]` block. All
|
||||
// fields are zero-valued when omitted; the resolver treats zero as
|
||||
// "not set, compute from host or fall back to builtin constants."
|
||||
type vmDefaultsFile struct {
|
||||
VCPUCount int `toml:"vcpu"`
|
||||
MemoryMiB int `toml:"memory_mib"`
|
||||
DiskSize string `toml:"disk_size"`
|
||||
SystemOverlaySize string `toml:"system_overlay_size"`
|
||||
}
|
||||
|
||||
func Load(layout paths.Layout) (model.DaemonConfig, error) {
|
||||
cfg := model.DaemonConfig{
|
||||
LogLevel: "info",
|
||||
|
|
@ -140,9 +151,48 @@ func Load(layout paths.Layout) (model.DaemonConfig, error) {
|
|||
}
|
||||
cfg.FileSync = append(cfg.FileSync, validated)
|
||||
}
|
||||
|
||||
if file.VMDefaults != nil {
|
||||
override, err := parseVMDefaults(*file.VMDefaults)
|
||||
if err != nil {
|
||||
return cfg, fmt.Errorf("vm_defaults: %w", err)
|
||||
}
|
||||
cfg.VMDefaults = override
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// parseVMDefaults validates and translates the TOML block into the
|
||||
// model-level override struct. Negative values are rejected outright;
|
||||
// zero means "not set."
|
||||
func parseVMDefaults(file vmDefaultsFile) (model.VMDefaultsOverride, error) {
|
||||
override := model.VMDefaultsOverride{
|
||||
VCPUCount: file.VCPUCount,
|
||||
MemoryMiB: file.MemoryMiB,
|
||||
}
|
||||
if override.VCPUCount < 0 {
|
||||
return model.VMDefaultsOverride{}, fmt.Errorf("vcpu must be >= 0 (got %d)", override.VCPUCount)
|
||||
}
|
||||
if override.MemoryMiB < 0 {
|
||||
return model.VMDefaultsOverride{}, fmt.Errorf("memory_mib must be >= 0 (got %d)", override.MemoryMiB)
|
||||
}
|
||||
if value := strings.TrimSpace(file.DiskSize); value != "" {
|
||||
bytes, err := model.ParseSize(value)
|
||||
if err != nil {
|
||||
return model.VMDefaultsOverride{}, fmt.Errorf("disk_size: %w", err)
|
||||
}
|
||||
override.WorkDiskSizeBytes = bytes
|
||||
}
|
||||
if value := strings.TrimSpace(file.SystemOverlaySize); value != "" {
|
||||
bytes, err := model.ParseSize(value)
|
||||
if err != nil {
|
||||
return model.VMDefaultsOverride{}, fmt.Errorf("system_overlay_size: %w", err)
|
||||
}
|
||||
override.SystemOverlaySizeByte = bytes
|
||||
}
|
||||
return override, nil
|
||||
}
|
||||
|
||||
// validateFileSyncEntry normalises a single `[[file_sync]]` entry
|
||||
// and rejects anything the operator would regret later: empty
|
||||
// paths, unsupported leading characters, path traversal, or
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue