70 lines
2.5 KiB
Go
70 lines
2.5 KiB
Go
package web
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-hub/internal/monitor"
|
|
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
|
)
|
|
|
|
// heldAppRow is one line of the „Held apps" list (D53, `08` §10) on the host page and the Hosts page.
|
|
type heldAppRow struct {
|
|
CustomerID string
|
|
HostID string // the customer's host, for the link on the Hosts page; "" when unknown
|
|
Stack string
|
|
Reason string
|
|
Since time.Time
|
|
Why string // the box's own sentence
|
|
WhoClears string
|
|
Reminded bool
|
|
Stale bool // the box has not repeated it for heldAppStale — it may be down
|
|
// ProtectsData (D64 = B): a restore or put-back hold — the confirm step warns before „Clear hold" (`07` §8).
|
|
ProtectsData bool
|
|
}
|
|
|
|
// holdProtectsData: the reasons whose hold keeps an app off half-restored data (`07` §8): a failed restore (the
|
|
// reason is "" or restore_failed on older rows), a mixed restore, a put-back waiting for its drive.
|
|
func holdProtectsData(reason string) bool {
|
|
switch reason {
|
|
case "", "restore_failed", "restore_mixed", "putback_pending":
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// heldAppStaleAfter mirrors monitor's heldAppStale: a box repeats app_held daily.
|
|
const heldAppStaleAfter = 50 * time.Hour
|
|
|
|
// heldAppRows reads the held-app mirror, one customer's or every one's ("" = all). A read failure is logged and
|
|
// shown as an empty list — the page must still render.
|
|
func (s *Server) heldAppRows(customerID string, hostOf map[string]string, now time.Time) []heldAppRow {
|
|
held, err := s.store.ListHeldApps(customerID)
|
|
if err != nil {
|
|
s.logger.Printf("[WARN] held apps: list for %q: %v", customerID, err)
|
|
return nil
|
|
}
|
|
return toHeldAppRows(held, hostOf, now)
|
|
}
|
|
|
|
// hostHeldAppRows is one host's list. A host with no customer has none — never the fleet's („" lists every one).
|
|
func (s *Server) hostHeldAppRows(customerID string, now time.Time) []heldAppRow {
|
|
if customerID == "" {
|
|
return nil
|
|
}
|
|
return s.heldAppRows(customerID, nil, now)
|
|
}
|
|
|
|
func toHeldAppRows(held []store.HeldApp, hostOf map[string]string, now time.Time) []heldAppRow {
|
|
out := make([]heldAppRow, 0, len(held))
|
|
for _, h := range held {
|
|
since := h.Since
|
|
if since.IsZero() {
|
|
since = h.FirstSeen
|
|
}
|
|
out = append(out, heldAppRow{CustomerID: h.CustomerID, HostID: hostOf[h.CustomerID], Stack: h.Stack, Reason: h.Reason,
|
|
Since: since, Why: h.Why, WhoClears: monitor.HeldAppWhoClears(h.Reason), Reminded: !h.RemindedAt.IsZero(),
|
|
Stale: now.Sub(h.LastSeen) > heldAppStaleAfter, ProtectsData: holdProtectsData(h.Reason)})
|
|
}
|
|
return out
|
|
}
|