package hub import ( "gitea.dooplex.hu/admin/felhom-agent/internal/proxmox" ) // R-1192 follow-up (night 2026-10-21): the guest swap fix (every guest may swap as much as its RAM, // localapi/guestswap.go) moves a memory burst onto the HOST's swap. Measured on demo-hp the same day: our installer // gives an 8 GB / 256 GB machine 7.75 GB of host swap, so a 4096 MB guest's 4096 MB swap fits. A host with no swap // (a BYO install, or swap turned off) gets nothing from the fix. So the report carries both numbers, the agent says it // once in its log, and the hub raises host_swap_short. The agent never creates host swap itself: changing a host its // owner set up is a decision (felhom.eu register). // HostSwapShort reports whether the host's swap is below the guests' swap allowance. A host whose guests have no // swap allowance (0) is never short. func HostSwapShort(hostMB, guestMB int64) bool { return guestMB > 0 && hostMB < guestMB } // applySwap fills the host block's swap numbers from the node status and the guests' specs, and logs the short // state once per change. func (c *Collector) applySwap(h *HostMetrics, ns proxmox.NodeStatus, guests []Guest) { hostMB := ns.Swap.Total / (1 << 20) var guestMB int64 for _, g := range guests { if g.Spec != nil { guestMB += g.Spec.SwapBytes / (1 << 20) } } h.HostSwapMB, h.GuestSwapMB = &hostMB, &guestMB if HostSwapShort(hostMB, guestMB) { if c.swapShortWarned.CompareAndSwap(false, true) { c.logger.Warn("host-swap: the host's swap is below its guests' swap allowance — a memory burst can freeze the box (R-1192); the hub is told (host_swap_short)", "host_swap_mb", hostMB, "guest_swap_mb", guestMB) } return } if c.swapShortWarned.CompareAndSwap(true, false) { c.logger.Info("host-swap: the host's swap covers its guests' swap allowance again", "host_swap_mb", hostMB, "guest_swap_mb", guestMB) } }