zmgr/docs/ai/decisions.md
Till Wegmueller abdce9c927
Add zmgr: illumos zone manager with IPAM and flat-file registry
Rust CLI that creates/destroys/imports illumos zones from KDL template
configs with automatic IP allocation from named pools. Registry lives
under /etc/zmgr as flat KDL files — zone entries double as the IPAM
ledger. Includes default templates for ipkg (OI) and nlipkg (OFL)
brands, matching the existing shell scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:14:09 +01:00

1.9 KiB

Design Decisions

KDL over TOML/JSON

KDL (v2) was chosen for all config files because:

  • Node-based structure maps naturally to zone/pool/template semantics
  • More readable than TOML for nested structures
  • kdl crate v6.5 supports KDL v2 spec
  • Note: KDL v2 uses #true/#false for booleans, not bare true/false

knuffel (typed derive) was evaluated but targets KDL v1, incompatible with kdl v6. Manual extraction via kdl_util.rs helpers is sufficient for our simple schemas.

Flat Files, No Database

All state lives in /etc/zmgr/ as individual KDL files:

  • One file per zone, pool, template, publisher
  • Human-editable with any text editor
  • Works on minimal illumos installs (no SQLite, no sled)
  • Easy to back up, version control, or inspect

IPAM: Zone Files Are the Ledger

No separate allocation table. To find allocated IPs:

  1. Scan /etc/zmgr/zones/*.kdl
  2. Parse each zone's address field
  3. Check which IPs fall within a pool's network

This avoids consistency issues between a ledger and registry.

Global Pools, Template References

Pools are defined independently (not inside templates) so multiple templates can share a pool. Templates reference pools by name. This matches the user's preference for a "global pool config" pattern.

bhyve Exclusion

Import logic explicitly skips brand=bhyve zones. These are vm-manager's responsibility. This boundary is enforced at the import level, not at the config level.

Error Handling: miette Diagnostics

Every error variant includes:

  • A descriptive message
  • A diagnostic code (e.g., zmgr::pool::exhausted)
  • A help message telling the user what to do next

This follows the miette diagnostic pattern per project conventions.

No Daemon, No State Machine

zmgr is a one-shot CLI. Each invocation reads config, acts, writes results. No background process, no lock files, no PID management. Zone lifecycle is delegated to the OS (zoneadm).