install page: say when the host has too little swap behind the guest (R-1192 follow-up); restore record log says when a cut restore was put back; unreleased
gates / gates (push) Successful in 1m36s

This commit is contained in:
2026-10-21 22:11:16 +02:00
parent d582feb245
commit 37b79caad9
11 changed files with 78 additions and 6 deletions
+5
View File
@@ -720,6 +720,11 @@ func (s *Server) deployPageData(w http.ResponseWriter, r *http.Request, name str
memInfo["UsedPercent"] = usedPercent
memInfo["Blocked"] = newReqMB > 0 && afterMB > usableMB
memInfo["OvercommitWarn"] = newLimitMB > 0 && afterLimitMB > totalMB
// R-1192 follow-up: when memory is tight, say so if the HOST has too little swap behind the guest — the
// guest swap fix then has nothing to give, and a big upload can freeze the box.
if memInfo["OvercommitWarn"] == true {
memInfo["SwapShort"] = s.hostSwapShort()
}
}
data["MemoryInfo"] = memInfo
}
+1 -1
View File
@@ -400,7 +400,7 @@ func i18nDeployData(deployed bool, st stacks.ContainerState, variant int) map[st
d["GeoAppOverride"] = true
d["AppEmailGlobalOn"] = false
d["AppEmailAppOn"] = true
d["MemoryInfo"] = map[string]interface{}{"Available": true, "Blocked": false, "OvercommitWarn": true, "AfterMB": 3000, "UsableMB": 4000,
d["MemoryInfo"] = map[string]interface{}{"Available": true, "Blocked": false, "OvercommitWarn": true, "SwapShort": true, "AfterMB": 3000, "UsableMB": 4000,
"Percent": 75, "UsedPercent": 70, "UsedMB": 2800, "NewRequestMB": 128}
d["StorageInfo"] = map[string]interface{}{"Label": "HDD egy", "Path": "/mnt/hdd1", "DataSizeHuman": "2 GB", "FreeHuman": "500 GB", "FreePercent": 50.0}
d["OtherStoragePaths"] = []string{"/mnt/hdd2"}
@@ -0,0 +1,28 @@
package web
import (
"testing"
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
)
// R-1192 follow-up (night 2026-10-21): the install page adds „A gépen nincs elég cserehely (swap)…" when memory is
// tight AND the agent reports the host's swap below the guest's RAM. An older agent (no number) is not judged.
// RED-PROOF: swapShort returning false always → the first case fails.
func TestR1192_SwapShortJudgesTheHostSwapAgainstTheGuestRAM(t *testing.T) {
mb := func(v int64) *int64 { return &v }
for _, c := range []struct {
name string
info agentapi.GuestMemoryInfo
want bool
}{
{"a host with no swap", agentapi.GuestMemoryInfo{AllocatedMB: 4096, HostSwapMB: mb(0)}, true},
{"a host with 2 GB swap behind a 4 GB guest", agentapi.GuestMemoryInfo{AllocatedMB: 4096, HostSwapMB: mb(2048)}, true},
{"the installer's 8 GB host (7.75 GB swap)", agentapi.GuestMemoryInfo{AllocatedMB: 4096, HostSwapMB: mb(7935)}, false},
{"an older agent (no number)", agentapi.GuestMemoryInfo{AllocatedMB: 4096}, false},
} {
if got := swapShort(c.info); got != c.want {
t.Errorf("%s: swapShort = %v, want %v", c.name, got, c.want)
}
}
}
@@ -192,3 +192,26 @@ func procMemTotalMB() int64 {
}
return 0
}
// hostSwapShort (R-1192 follow-up, night 2026-10-21) asks the agent whether the HOST's swap is below this guest's RAM
// — the guest swap fix (swap = RAM) puts a memory burst there, and a host with none gets nothing from it. False when
// it cannot tell (an older agent, an agent that does not answer within 2 s): the install page then shows only the
// overcommit sentence, as before.
func (s *Server) hostSwapShort() bool {
agent, err := s.memAgentForResize()
if err != nil || agent == nil {
return false
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
info, err := agent.GuestMemory(ctx)
if err != nil {
return false
}
return swapShort(info)
}
// swapShort: the host's swap is known and below the guest's RAM.
func swapShort(info agentapi.GuestMemoryInfo) bool {
return info.HostSwapMB != nil && info.AllocatedMB > 0 && *info.HostSwapMB < info.AllocatedMB
}
@@ -55,7 +55,7 @@
</div>
{{if .OvercommitWarn}}
<div class="alert alert-warning" style="margin-top:0.5rem;margin-bottom:0">
{{T "deploy.memory_overcommit_slow"}}
{{T "deploy.memory_overcommit_slow"}}{{if .SwapShort}} {{T "deploy.memory_swap_short"}}{{end}}
</div>
{{end}}
{{end}}
@@ -214,7 +214,7 @@
</div>
<div class="alert alert-warning" style="margin-top:0.5rem;margin-bottom:0">
Az alkalmazások csúcsterhelése meghaladhatja a rendelkezésre álló memóriát. Ilyenkor a doboz nagy feltöltések alatt lelassulhat, és akár percekig sem válaszol. Ha ez gyakran előfordul, távolíts el egy alkalmazást.
Az alkalmazások csúcsterhelése meghaladhatja a rendelkezésre álló memóriát. Ilyenkor a doboz nagy feltöltések alatt lelassulhat, és akár percekig sem válaszol. Ha ez gyakran előfordul, távolíts el egy alkalmazást. A gépen nincs elég cserehely (swap), ezért nagy feltöltéskor a doboz lelassulhat, és percekig sem válaszolhat. Szólj a Felhomnak, mi rendbe tesszük.
</div>