Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66498a58c5 | ||
|
|
b790b0c31c |
+15
-7
@@ -1,12 +1,20 @@
|
||||
# Virtualization tab — plan (2026-10-09; phase 1 built the same day)
|
||||
|
||||
**Status:** phase 1 is written, tested and committed as **v0.1.0-180** (`internal/incus`,
|
||||
`internal/api/virt.go`, `Virtualization.tsx`), **not yet deployed** — `make deploy` was
|
||||
refused by the session's auto-mode classifier, so it is his to run. Nothing is installed on
|
||||
any machine yet; Install has not been exercised against a live host. First real test is
|
||||
Install on `grid` (zfs pool on a file, Docker present), then `core` (btrfs loop, Docker
|
||||
present), then the Mac mini (dnf, arm64). Not built yet from the phase-1 list: the
|
||||
`instance.*` sensors and the Alerts default — next session.
|
||||
**Status:** phase 1 is **deployed to all five machines as v0.1.0-184** (2026-10-09) and
|
||||
**Install has run for real on `grid`**: Incus 6.0.4, a zfs pool on a 197 GiB sparse file in
|
||||
`~/apps/hamlab/virt/`, `incusbr0` at `172.16.100.1/24`, the two `DOCKER-USER` rules, the
|
||||
`incus-admin` group and Ham Lab's restart — one task, 90 seconds, exit 0. Verified
|
||||
afterwards: a Debian 13 container and a Debian 13 VM created from the hub, both got a lease,
|
||||
DNS and the internet through Docker's `FORWARD DROP`, the VM's agent answered `exec`;
|
||||
snapshot create/restore/delete, limits and a snapshot schedule, a shell as a Terminal tab
|
||||
through the hub, the catalogue (98 x86_64 container images, 1.1 s then cached), and the
|
||||
refusals (bad names, wrong delete confirmation, a size that isn't one). Both test instances
|
||||
were deleted again; the two Debian images stay in the store. One bug found and fixed on the
|
||||
way: `description` is an instance field, not a config key (v0.1.0-184). Detection on the
|
||||
other four: `core`, the Mac mini and `hamtv` show **Install**; `gate` shows **unavailable**
|
||||
(OpenWrt's apk has no incus, no KVM). Not built yet from the phase-1 list: the `instance.*`
|
||||
sensors and the Alerts default — next session. The write-back for `grid` is in
|
||||
`hamlet/docs/hosts.md`, `docker.md` and `gotchas.md`.
|
||||
|
||||
A tab for creating, watching, consoling into and deleting **LXC containers and KVM virtual
|
||||
machines**, the way Proxmox does with `pct` and `qm` — **per machine, like every other
|
||||
|
||||
+14
-2
@@ -388,6 +388,12 @@ func (s *Server) virtConfig(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
var set, unset []string
|
||||
desc, hasDesc := body["description"]
|
||||
delete(body, "description")
|
||||
if hasDesc && (len(desc) > 200 || strings.ContainsAny(desc, "\n\r")) {
|
||||
jsonErr(w, 400, "bad value for description")
|
||||
return
|
||||
}
|
||||
for k, v := range body {
|
||||
v = strings.TrimSpace(v)
|
||||
ok := false
|
||||
@@ -400,8 +406,6 @@ func (s *Server) virtConfig(w http.ResponseWriter, r *http.Request) {
|
||||
ok = incus.ValidCron(v)
|
||||
case "snapshots.expiry":
|
||||
ok = incus.ValidExpiry(v)
|
||||
case "description":
|
||||
ok = len(v) <= 200 && !strings.ContainsAny(v, "\n\r")
|
||||
case "boot.autostart":
|
||||
ok = v == "" || v == "true" || v == "false"
|
||||
}
|
||||
@@ -429,6 +433,14 @@ func (s *Server) virtConfig(w http.ResponseWriter, r *http.Request) {
|
||||
for _, k := range unset {
|
||||
_, _ = s.virt.Cmd(ctx, "config", "unset", name, k).CombinedOutput() // unsetting what isn't set is fine
|
||||
}
|
||||
if hasDesc {
|
||||
// the description is a field of the instance, not a config key, so it goes in through the API
|
||||
patch, _ := json.Marshal(map[string]string{"description": strings.TrimSpace(desc)})
|
||||
if out, err := s.virt.Cmd(ctx, "query", "-X", "PATCH", "-d", string(patch), "/1.0/instances/"+name).CombinedOutput(); err != nil {
|
||||
jsonErr(w, 409, strings.TrimPrefix(strings.TrimSpace(string(out)), "Error: "))
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Printf("virt: config %s set %v unset %v (from %s)", name, set, unset, clientIP(r))
|
||||
w.WriteHeader(204)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user