kvm2: record the review validation, enable the provider entry, changelog
Closes out the review-fix campaign. The kvm2 provider was deployed in-cluster and validated against beelink -- the first time any of this code had run against real libvirt rather than the in-memory fake. config/manager/providers_config.yaml ships the kvm2-home entry enabled, since the operator is now running it for real. review/ carries the code review the four H-commits reference, so H1..H4 resolve to something rather than dangling: scope, the seven-chunk sweep, the escalations, the ten deep dives and the final report. .claude/agents carries the two reviewer definitions that produced them. What the validation did not prove is recorded next to what it did: H2's error paths need a body that fails part way through, and a healthy 433 MB download never finishes short, so the unverified libvirtd short-stream behaviour is still open. The kvm2 integration test has also still never been run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,45 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-09-17 20:36 UTC — kvm2: the four high findings from the code review, and its first run on a real hypervisor
|
||||
|
||||
A scoped review of the kvm2 provider (`review/REPORT.md`: 52 findings, 4 high, 20 medium,
|
||||
28 low) produced four fixes, one commit each, then the provider was deployed in-cluster and
|
||||
validated against beelink — the first time any of this code had run against real libvirt.
|
||||
|
||||
- **H1 — a stalled write no longer delays a connection teardown.** `sshSocket.Close` ran the
|
||||
blocking close before the unblocking one, so a transfer stuck in a TCP write pinned the
|
||||
teardown for as long as the kernel retransmitted (~15 min). `link.markDead` compounded it by
|
||||
killing inside a `sync.Once` before signalling dead, which made even cancelling the reconcile
|
||||
useless. With `MaxConcurrentReconciles: 3`, one silent host could stall every Proxy on every
|
||||
provider. `internal/provider/kvm2/{ssh,backend}.go`.
|
||||
- **H2 — a source error no longer reaches go-libvirt's stream sender.** A failing HTTP body
|
||||
deadlocked `StorageVolUpload` outright and leaked two goroutines plus 4 MiB per occurrence,
|
||||
against a 128Mi pod limit. The defect is upstream (`requestStream` never drains an unbuffered
|
||||
`outErr`); the workaround wraps the reader so it can only ever end the stream cleanly, and
|
||||
moves the transfer deadline onto the HTTP source so a stalled mirror unwinds instead of
|
||||
leaking. A daemon-side failure mid-upload still leaks — documented in *Known gaps* with the
|
||||
two-character upstream patch. `internal/provider/kvm2/{backend,image}.go`.
|
||||
- **H3 — an unreadable address is no longer reported as a missing one.** Any error from both
|
||||
address sources read as "no address yet", so a pooled connection killed by an unrelated
|
||||
reconcile demoted a healthy proxy to Provisioning, cleared its IP and made the health engine
|
||||
drop its counters. One source failing stays "no address yet"; every source failing, or a dead
|
||||
connection, is now Transient. `internal/provider/kvm2/get.go`.
|
||||
- **H4 — the base image cache is no longer shared between provider entries.** kvm2 built
|
||||
byte-identical volume names to the `kvm` provider in the same pool, so two entries could share
|
||||
one file, a concurrent fetch could boot a guest from a half-written base, and a `sha256` edit
|
||||
deleted the base under live overlays. Names now carry the entry
|
||||
(`base-<entry>-<key>.<format>`), and a digest mismatch is refused rather than resolved by
|
||||
deleting. `internal/provider/kvm2/{volume,image}.go`, `internal/provider/config_kvm.go`.
|
||||
- **klog and `net/http` errors now join the structured log stream.** client-go's leader election
|
||||
wrote `I0917 ...` lines straight to stderr because nothing routed klog into logr, and the
|
||||
discovery server's `http.Server` had no `ErrorLog`. The deployment also gained
|
||||
`--zap-encoder=json` and `--zap-time-encoding=rfc3339`, so `kubectl logs | jq` works.
|
||||
`cmd/main.go`, `internal/discovery/server.go`, `config/manager/manager.yaml`.
|
||||
- **The `kvm2-home` provider entry is enabled** in `config/manager/providers_config.yaml`.
|
||||
Validated end to end: health check Ready, a 433 MB image cached in 8.3 s under the new name
|
||||
beside kvm's untouched one, a second Proxy reusing the cache, Squid answering a real CONNECT
|
||||
probe, and Delete leaving the base image while removing the domain and its volumes.
|
||||
|
||||
## 2026-09-16 11:46 UTC — Provider blueprint split into contract, spec template and appendix
|
||||
|
||||
- **`docs/provider-contract.md`** is the generic provider specification: MUST/SHOULD/MAY
|
||||
|
||||
Reference in New Issue
Block a user