diff --git a/internal/carrel/status.go b/internal/carrel/status.go index e233e6d..b73d364 100644 --- a/internal/carrel/status.go +++ b/internal/carrel/status.go @@ -14,7 +14,9 @@ import ( // share. A tenant is named only when its slug is already public: it is // active and serves at least one ready *..winlab.tw domain. Every // other tenant with machines is summed into "others" without a name. -// Machine names, addresses, keys and domains are never listed. +// Machine names, addresses, keys and domains are never listed. "quota" is +// the default budget: every member gets one, and every project group gets +// another of its own on top of its members' budgets. func (e *Execution) PublicStatus() D { c := e.Capacity(nil, true) physical := obj(c["physical"]) @@ -55,11 +57,22 @@ func (e *Execution) PublicStatus() D { "disk_gib": D{"total": disk["total"], "used": disk["used"]}, }, "allocated": c["allocatable"], + "quota": D{"member": budget(DefaultQuota), "project": budget(DefaultQuota)}, "tenants": tenants, "others": others, } } +// budget is the part of a quota the status page shows. +func budget(q D) D { + return D{ + "machines": num(q["machines"]), + "vcpu": num(q["vcpu"]), + "memory_gib": num(q["memory_mb"]) / 1024, + "disk_gib": num(q["disk_gb"]), + } +} + // publicSlug reports whether a tenant's slug is already published by one of // its domains. func publicSlug(domains []D) bool { diff --git a/internal/carrel/status_test.go b/internal/carrel/status_test.go index 78b014e..cf3a426 100644 --- a/internal/carrel/status_test.go +++ b/internal/carrel/status_test.go @@ -46,6 +46,10 @@ func TestPublicStatusNamesOnlyTenantsWithAPublicDomain(t *testing.T) { if num(others["tenants"]) != 2 || num(others["machines"]) != 2 || num(others["vcpu"]) != 4 { t.Fatalf("unexpected others: %s", raw) } + member := obj(obj(body["quota"])["member"]) + if num(member["machines"]) != 8 || num(member["vcpu"]) != 8 || num(member["memory_gib"]) != 16 || num(member["disk_gib"]) != 100 || obj(obj(body["quota"])["project"])["vcpu"] == nil { + t.Fatalf("unexpected quota: %s", raw) + } node := obj(body["node"]) if num(obj(node["cpu"])["logical_cpus"]) != 32 || num(obj(node["memory_gib"])["total"]) != 192 { t.Fatalf("unexpected node: %s", raw)