Files
ProxmoxDash/guests.go

67 lines
1.5 KiB
Go

package main
import (
"context"
"encoding/json"
"os/exec"
"sort"
"sync"
"time"
)
type GuestMetrics struct {
VMID int `json:"vmid"`
Name string `json:"name"`
Type string `json:"type"`
Node string `json:"node"`
Status string `json:"status"`
CPU float64 `json:"cpu"`
MaxCPU float64 `json:"maxcpu"`
MemoryBytes uint64 `json:"mem"`
MaxMemory uint64 `json:"maxmem"`
Uptime uint64 `json:"uptime"`
Template int `json:"template"`
}
type GuestsMetrics struct {
Available bool `json:"available"`
Guests []GuestMetrics `json:"guests"`
}
type guestCollector struct {
mu sync.Mutex
cached GuestsMetrics
updatedAt time.Time
}
func (c *guestCollector) collect() GuestsMetrics {
c.mu.Lock()
defer c.mu.Unlock()
if time.Since(c.updatedAt) < 3*time.Second {
return c.cached
}
c.cached = readGuests()
c.updatedAt = time.Now()
return c.cached
}
func readGuests() GuestsMetrics {
if _, err := exec.LookPath("pvesh"); err != nil {
return GuestsMetrics{}
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
output, err := exec.CommandContext(ctx, "pvesh", "get", "/cluster/resources", "--type", "vm", "--output-format", "json").Output()
result := GuestsMetrics{Available: true}
if err != nil {
return result
}
if json.Unmarshal(output, &result.Guests) != nil {
return result
}
sort.Slice(result.Guests, func(i, j int) bool {
return result.Guests[i].VMID < result.Guests[j].VMID
})
return result
}