mirror of
https://github.com/anand34577/ferrum.git
synced 2026-09-12 05:48:58 +00:00
d04b769670
- Fleet Overview's Storage KPI and per-connection totals (internal/api/ overview.go) were summing shared storage once per node that mounts it, since PVE's own Shared flag is unreliable for storage added per-node without ticking it. New dedupeSharedStorage collapses those by an exact (name, total, used) match within a connection; local-only plugin types are never touched. Mirrored on the Storage page, which also now disambiguates same-named local pools (e.g. every node's "local-lvm") by node so a bar chart's category axis never gets duplicate labels. - Sign-out: React Query keeps a query's last-successful data through a failed refetch, so the cached signed-in user survived the post-logout 401 and the app never noticed. signOut() now pins ["auth","me"] to null directly instead of invalidating-and-hoping a refetch lands in time. - SMTP: net/smtp.SendMail opportunistically attempts STARTTLS whenever the server advertises it regardless of the admin's "Use STARTTLS" toggle, so an internal relay with a bad cert failed sends the admin explicitly asked to be plaintext. A dedicated sendPlain path never attempts TLS. - OIDC: added an "Auto-create new accounts" toggle — when off, a first-time SSO login for an unrecognized identity is refused instead of silently provisioning one. Also added RP-Initiated Logout: signing out of an SSO session now also ends the session at the identity provider when it advertises support for it (end_session_endpoint), via a stored id_token on OIDC sessions (new sessions.oidc_id_token column). - ResourceAreaChart tooltips now fall back to the same yTickFormatter given to the axis when a series has no formatter of its own — fixes raw unformatted numbers in Fleet Trend and every RRD chart built on it (Node/Guest detail) that only ever set the axis formatter.
65 lines
2.9 KiB
Go
65 lines
2.9 KiB
Go
package api
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"ferrum/internal/pve"
|
|
)
|
|
|
|
func TestDedupeSharedStorageCollapsesSameVolumeAcrossNodes(t *testing.T) {
|
|
// An NFS share mounted on 4 nodes without PVE's "Shared" checkbox ticked
|
|
// (Shared: 0) — cluster/resources reports it once per node, byte-for-byte
|
|
// identical each time. Must collapse to one.
|
|
rows := []pve.ClusterResource{
|
|
{Node: "pve-01", Storage: "nas", PluginType: "nfs", Shared: 0, MaxDisk: 2_000_000_000_000, Disk: 1_000_000_000_000},
|
|
{Node: "pve-02", Storage: "nas", PluginType: "nfs", Shared: 0, MaxDisk: 2_000_000_000_000, Disk: 1_000_000_000_000},
|
|
{Node: "pve-03", Storage: "nas", PluginType: "nfs", Shared: 0, MaxDisk: 2_000_000_000_000, Disk: 1_000_000_000_000},
|
|
{Node: "pve-04", Storage: "nas", PluginType: "nfs", Shared: 0, MaxDisk: 2_000_000_000_000, Disk: 1_000_000_000_000},
|
|
}
|
|
got := dedupeSharedStorage(rows)
|
|
if len(got) != 1 {
|
|
t.Fatalf("got %d rows, want 1 (deduped)", len(got))
|
|
}
|
|
if got[0].MaxDisk != 2_000_000_000_000 {
|
|
t.Errorf("MaxDisk = %d, want the single volume's real capacity, not summed across nodes", got[0].MaxDisk)
|
|
}
|
|
}
|
|
|
|
func TestDedupeSharedStorageCollapsesProperlyFlaggedShared(t *testing.T) {
|
|
rows := []pve.ClusterResource{
|
|
{Node: "pve-01", Storage: "pbs-backup", PluginType: "pbs", Shared: 1, MaxDisk: 5_000_000_000_000, Disk: 2_000_000_000_000},
|
|
{Node: "pve-02", Storage: "pbs-backup", PluginType: "pbs", Shared: 1, MaxDisk: 5_000_000_000_000, Disk: 2_000_000_000_000},
|
|
}
|
|
got := dedupeSharedStorage(rows)
|
|
if len(got) != 1 {
|
|
t.Fatalf("got %d rows, want 1 (deduped)", len(got))
|
|
}
|
|
}
|
|
|
|
func TestDedupeSharedStorageKeepsGenuinelySeparateLocalDisks(t *testing.T) {
|
|
// Same name ("local-lvm"), different nodes, different usage — this is
|
|
// real per-node capacity that must be summed, not deduped away.
|
|
rows := []pve.ClusterResource{
|
|
{Node: "pve-01", Storage: "local-lvm", PluginType: "lvmthin", Shared: 0, MaxDisk: 1_000_000_000_000, Disk: 300_000_000_000},
|
|
{Node: "pve-02", Storage: "local-lvm", PluginType: "lvmthin", Shared: 0, MaxDisk: 1_000_000_000_000, Disk: 450_000_000_000},
|
|
}
|
|
got := dedupeSharedStorage(rows)
|
|
if len(got) != 2 {
|
|
t.Fatalf("got %d rows, want 2 (local disks are never deduped)", len(got))
|
|
}
|
|
}
|
|
|
|
func TestDedupeSharedStorageKeepsDistinctVolumesEvenWithMatchingCapacity(t *testing.T) {
|
|
// Two different NFS exports that happen to be identically sized but
|
|
// currently hold different amounts of data — a real coincidence in
|
|
// total size alone isn't enough to treat them as the same volume.
|
|
rows := []pve.ClusterResource{
|
|
{Node: "pve-01", Storage: "nas-a", PluginType: "nfs", Shared: 0, MaxDisk: 1_000_000_000_000, Disk: 100_000_000_000},
|
|
{Node: "pve-01", Storage: "nas-b", PluginType: "nfs", Shared: 0, MaxDisk: 1_000_000_000_000, Disk: 200_000_000_000},
|
|
}
|
|
got := dedupeSharedStorage(rows)
|
|
if len(got) != 2 {
|
|
t.Fatalf("got %d rows, want 2 (different names, never the same volume)", len(got))
|
|
}
|
|
}
|