diff --git a/docs/ai/architecture.md b/docs/ai/architecture.md index 2281f87..0371734 100644 --- a/docs/ai/architecture.md +++ b/docs/ai/architecture.md @@ -8,14 +8,15 @@ zmgr is a single Rust binary that manages illumos zones via flat KDL config file ``` src/ - main.rs CLI entry point (clap), command dispatch + main.rs CLI entry point (clap), command dispatch, table formatting config.rs Global config (/etc/zmgr/config.kdl) - template.rs Zone templates (/etc/zmgr/templates/*.kdl) - pool.rs IPAM pools (/etc/zmgr/pools/*.kdl) - zone.rs Zone registry (/etc/zmgr/zones/*.kdl) + template.rs Zone templates (/etc/zmgr/templates/*.kdl) — multi-net + pool.rs IPAM pools (/etc/zmgr/pools/*.kdl) — range + list modes + zone.rs Zone registry (/etc/zmgr/zones/*.kdl) — multi-net publisher.rs IPS publishers (/etc/zmgr/publishers/*.kdl) exec.rs System command wrappers (zonecfg, zoneadm, dladm) import.rs Import existing zones into registry + validate.rs Config validation (syntax, integrity, pool sanity) kdl_util.rs KDL document parsing helpers error.rs Error types (miette diagnostics) ``` @@ -24,36 +25,63 @@ src/ ### Zone Creation (`zmgr create `) -1. Load global config → get default template name -2. Load template → get brand, autoboot, pool reference -3. Load pool → get network, gateway, stub, IP range -4. Scan zone registry → find allocated IPs -5. Allocate next free IP from pool range -6. `dladm create-vnic` → create VNIC on stub -7. `zonecfg -z ` → pipe zone configuration -8. `zoneadm -z install` → install zone -9. Write zone registry entry (KDL file) -10. If autoboot, `zoneadm boot` +1. Load global config -> get default template name +2. Load template -> get brand, autoboot, net blocks (each references a pool) +3. For each net: load pool -> allocate next free IP from pool +4. Build zonecfg commands with one `add net` block per network +5. Step-by-step execution with progress: + - Create VNICs via `dladm create-vnic` + - Configure zone via `zonecfg -z ` + - Install zone via `zoneadm -z install` + - Write zone registry entry (KDL file) + - If autoboot, `zoneadm boot` +6. On partial failure: print what succeeded + cleanup commands + +### Zone Destruction (`zmgr destroy `) + +1. Load zone from registry +2. Require confirmation (type zone name, or `--yes`) +3. Step-by-step teardown with progress: + - Halt zone + - Uninstall zone + - Delete zone configuration + - Delete VNICs (one per net) + - Remove registry entry ### Zone Import (`zmgr import`) -1. `zoneadm list -cp` → get system zones +1. `zoneadm list -cp` -> get system zones 2. Filter out already-registered and bhyve zones -3. `zonecfg -z info` → extract config -4. Match brand → template, IP → pool -5. Write zone registry entry +3. `zonecfg -z info` -> extract config (multiple nets) +4. Match brand -> template, IP -> pool, net names -> template net names +5. Write zone registry entry with current date + +### Validation (`zmgr validate`) + +1. Parse all KDL files (config, templates, pools, zones) +2. Check referential integrity (template -> pool, config -> template) +3. Check pool sanity (gateway in network, range in network) +4. Check for duplicate IPs across zones +5. Warn on high pool utilization (>90%) + +## Output Modes + +- **Human** (default): auto-sized tables, key-value detail views +- **JSON** (`--json`): structured output for scripting +- **Dry-run** (`-n`): shows commands without executing ## Dependency Graph ``` main.rs - ├── config.rs ← kdl_util.rs, error.rs - ├── template.rs ← kdl_util.rs, error.rs - ├── pool.rs ← kdl_util.rs, error.rs, zone.rs - ├── zone.rs ← kdl_util.rs, error.rs - ├── publisher.rs ← kdl_util.rs, error.rs - ├── exec.rs ← error.rs - └── import.rs ← exec.rs, pool.rs, template.rs, zone.rs + ├── config.rs <- kdl_util.rs, error.rs + ├── template.rs <- kdl_util.rs, error.rs + ├── pool.rs <- kdl_util.rs, error.rs + ├── zone.rs <- kdl_util.rs, error.rs + ├── publisher.rs <- kdl_util.rs, error.rs + ├── exec.rs <- error.rs + ├── import.rs <- exec.rs, pool.rs, template.rs, zone.rs + └── validate.rs <- config.rs, pool.rs, template.rs, zone.rs ``` ## Boundary with vm-manager diff --git a/docs/ai/gap-analysis.md b/docs/ai/gap-analysis.md index d2d9c22..7ca4962 100644 --- a/docs/ai/gap-analysis.md +++ b/docs/ai/gap-analysis.md @@ -5,9 +5,6 @@ ### Publishers Not Applied During Install Publishers are stored and listed but not yet passed to `zonecfg`/`zoneadm` during zone creation. Future: configure IPS publishers inside the zone after install via `zlogin` or `sysding`. -### No Zone Boot/Halt Commands -`zmgr` doesn't expose boot/halt/reboot as subcommands. Users must use `zoneadm -z boot` directly. Could add `zmgr boot ` / `zmgr halt ` as thin wrappers. - ### No Template Create/Edit via CLI Templates must be edited as KDL files directly. Could add `zmgr template create` / `zmgr template edit` commands. @@ -29,11 +26,28 @@ Import matches zones to templates by brand and IPs to pools by network containme ### No IPv6 Support IPAM only handles IPv4 pools. Could extend to dual-stack. +### No Automatic Rollback on Create Failure +On partial failure, zmgr prints cleanup guidance but does not automatically undo. Could add `--rollback-on-failure` flag. + +### No Colored Output +Could add colored state indicators (green=running, red=halted) using `owo-colors`. Should respect `NO_COLOR` env var. + ## Resolved -- ~~No Dry-Run Mode~~ — Implemented: `--dry-run` / `-n` flag on create and destroy -- ~~Single network per zone~~ — Implemented: templates define multiple `net` blocks, each referencing a pool -- ~~No public/hoster IP support~~ — Implemented: pools support explicit address lists in addition to contiguous ranges +- ~~No Dry-Run Mode~~ — `--dry-run` / `-n` flag on create and destroy +- ~~Single network per zone~~ — Templates define multiple `net` blocks +- ~~No public/hoster IP support~~ — Pools support explicit address lists +- ~~No destructive operation confirmation~~ — Destroy requires typing zone name (or `--yes`) +- ~~No progress output~~ — Create/destroy show numbered step-by-step progress +- ~~No partial failure guidance~~ — Prints cleanup commands on failure +- ~~No config validation~~ — `zmgr validate` checks syntax, integrity, pool sanity +- ~~No machine-readable output~~ — `--json` flag on all list/show/status commands +- ~~No shell completions~~ — `zmgr completions bash|zsh|fish` +- ~~No version flag~~ — `zmgr --version` +- ~~No boot/halt commands~~ — `zmgr boot` and `zmgr halt` +- ~~Publisher naming confusion~~ — Remove accepts both publisher name and filename stem +- ~~Hardcoded column widths~~ — Tables auto-size based on content +- ~~Import empty created date~~ — Uses current date, matches template net names ## Future Considerations @@ -41,3 +55,4 @@ IPAM only handles IPv4 pools. Could extend to dual-stack. - **Snapshots**: ZFS snapshot management for zone rollback - **Migration**: Move zones between hosts - **Monitoring**: Health checks, resource usage +- **Drift detection**: Dedicated command to compare registry vs system state diff --git a/docs/ai/implementation-state.md b/docs/ai/implementation-state.md index 4ae5d52..5b3d2df 100644 --- a/docs/ai/implementation-state.md +++ b/docs/ai/implementation-state.md @@ -2,8 +2,9 @@ ## Completed +### Core - [x] Project scaffold (Cargo.toml, module structure) -- [x] KDL parsing helpers (`kdl_util.rs`) +- [x] KDL v2 parsing helpers (`kdl_util.rs`) - [x] Error types with miette diagnostics (`error.rs`) - [x] Global config loading (`config.rs`) - [x] Template loading + defaults — multi-net support (`template.rs`) @@ -12,31 +13,54 @@ - [x] Publisher management (`publisher.rs`) - [x] Exec layer for system commands (`exec.rs`) - [x] Import logic from existing zones — multi-net parsing (`import.rs`) -- [x] CLI commands: init, create, destroy, list, status, import -- [x] CLI commands: template list/show, pool list/show -- [x] CLI commands: publisher list/add/remove +- [x] Validation engine (`validate.rs`) + +### CLI Commands +- [x] `init`, `create`, `destroy`, `list`, `status`, `import` +- [x] `boot`, `halt` — thin wrappers around zoneadm +- [x] `validate` — checks KDL syntax, referential integrity, pool sanity, duplicate IPs +- [x] `template list|show`, `pool list|show` +- [x] `publisher list|add|remove` +- [x] `completions ` — bash/zsh/fish shell completions + +### DX Features - [x] `--dry-run` / `-n` flag for create and destroy -- [x] Multi-network zones (multiple net blocks per template/zone) +- [x] `--yes` / `-y` flag to skip confirmation (scripting) +- [x] `--json` flag for machine-readable output +- [x] `--version` flag +- [x] Destroy confirmation: type zone name to confirm (TTY detection) +- [x] Step-by-step numbered progress during create/destroy +- [x] Partial failure guidance: prints cleanup commands on create failure +- [x] Auto-sizing table columns (measures content before printing) +- [x] Dry-run notes that IP allocation is tentative +- [x] Publisher remove accepts publisher name or filename stem +- [x] Import uses current date + matches template net names +- [x] RFC 5737 comment on default public pool + +### Multi-Network +- [x] Templates define multiple `net` blocks, each referencing a pool - [x] List-based IPAM pools (explicit addresses from hoster) - [x] Default router template with internal + public nets -- [x] Backward compat: legacy flat `pool` field in templates, flat address fields in zones -- [x] Clean build (zero warnings) -- [x] Tested: init, template list/show, pool list/show, publisher list, list, dry-run single+multi-net +- [x] Backward compat: legacy flat `pool` field in templates ## Not Yet Tested on illumos -- [ ] `zmgr create` (requires illumos with zonecfg/zoneadm/dladm) +- [ ] `zmgr create` (requires zonecfg/zoneadm/dladm) - [ ] `zmgr destroy` - [ ] `zmgr import` - [ ] `zmgr status` (requires zoneadm) +- [ ] `zmgr boot` / `zmgr halt` ## Dependencies | Crate | Version | Purpose | |---|---|---| | clap | 4.6.0 | CLI parsing (derive) | +| clap_complete | 4.6.0 | Shell completion generation | | kdl | 6.5.0 | KDL v2 document parsing | | miette | 7.6.0 | Diagnostic error reporting | | thiserror | 2.0.18 | Error type derives | | ipnet | 2.12.0 | IP network arithmetic | | chrono | 0.4.44 | Date formatting | +| serde | 1.0.228 | Serialization framework | +| serde_json | 1.0.149 | JSON output |