This commit is contained in:
henrygd
2026-03-03 12:42:30 -05:00
parent d34ef1ebe9
commit 48503f9f99
5 changed files with 86 additions and 18 deletions

View File

@@ -28,8 +28,10 @@ import (
// ansiEscapePattern matches ANSI escape sequences (colors, cursor movement, etc.)
// This includes CSI sequences like \x1b[...m and simple escapes like \x1b[K
var ansiEscapePattern = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b[@-Z\\-_]`)
var dockerContainerIDPattern = regexp.MustCompile(`^[a-fA-F0-9]{12,64}$`)
var (
ansiEscapePattern = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b[@-Z\\-_]`)
dockerContainerIDPattern = regexp.MustCompile(`^[a-fA-F0-9]{12,64}$`)
)
const (
// Docker API timeout in milliseconds

View File

@@ -4,6 +4,7 @@ import (
"context"
"crypto/tls"
"errors"
"log/slog"
"net/http"
"time"
@@ -22,24 +23,29 @@ type pveManager struct {
// Returns stats for all running VMs/LXCs
func (pm *pveManager) getPVEStats() ([]*container.Stats, error) {
if pm.client == nil {
slog.Info("PVE client not configured")
return nil, errors.New("PVE client not configured")
}
cluster, err := pm.client.Cluster(context.Background())
if err != nil {
slog.Error("Error getting cluster", "err", err)
return nil, err
}
slog.Info("PVE cluster", "cluster", cluster)
resources, err := cluster.Resources(context.Background(), "vm")
if err != nil {
slog.Error("Error getting resources", "err", err, "resources", resources)
return nil, err
}
slog.Info("PVE resources", "resources", resources)
containersLength := len(resources)
slog.Info("PVE containers length", "containersLength", containersLength)
containerIds := make(map[string]struct{}, containersLength)
// only include running vms and lxcs on selected node
for _, resource := range resources {
if resource.Node == pm.nodeName && resource.Status == "running" {
slog.Info("PVE resource", "resource", resource)
containerIds[resource.ID] = struct{}{}
}
}
@@ -53,6 +59,7 @@ func (pm *pveManager) getPVEStats() ([]*container.Stats, error) {
// populate stats
stats := make([]*container.Stats, 0, len(containerIds))
for _, resource := range resources {
// slog.Info("PVE resource", "resource", resource)
if _, exists := containerIds[resource.ID]; !exists {
continue
}
@@ -71,6 +78,10 @@ func (pm *pveManager) getPVEStats() ([]*container.Stats, error) {
resourceStats.Id = resource.ID
// Store type (e.g. "qemu" or "lxc") in .Image (cbor key 8, json:"-")
resourceStats.Image = resource.Type
// PVE limits (cbor-only, for pve_vms table)
resourceStats.MaxCPU = resource.MaxCPU
resourceStats.MaxMem = resource.MaxMem
resourceStats.Uptime = resource.Uptime
// prevent first run from sending all prev sent/recv bytes
total_sent := uint64(resource.NetOut)
total_recv := uint64(resource.NetIn)
@@ -87,14 +98,18 @@ func (pm *pveManager) getPVEStats() ([]*container.Stats, error) {
resourceStats.Mem = float64(resource.Mem)
resourceStats.Bandwidth = [2]uint64{uint64(sent_delta), uint64(recv_delta)}
slog.Info("PVE resource stats", "resourceStats", resourceStats)
stats = append(stats, resourceStats)
}
slog.Info("PVE stats", "stats", stats)
return stats, nil
}
// Creates a new PVE manager
func newPVEManager(_ *Agent) *pveManager {
slog.Info("Creating new PVE manager")
url, exists := GetEnv("PROXMOX_URL")
if !exists {
url = "https://localhost:8006/api2/json"
@@ -103,6 +118,11 @@ func newPVEManager(_ *Agent) *pveManager {
tokenID, tokenIDExists := GetEnv("PROXMOX_TOKENID")
secret, secretExists := GetEnv("PROXMOX_SECRET")
slog.Info("PROXMOX_URL", "url", url)
slog.Info("PROXMOX_NODE", "nodeName", nodeName)
slog.Info("PROXMOX_TOKENID", "tokenID", tokenID)
slog.Info("PROXMOX_SECRET", "secret", secret)
// PROXMOX_INSECURE_TLS defaults to true; set to "false" to enable TLS verification
insecureTLS := true
if val, exists := GetEnv("PROXMOX_INSECURE_TLS"); exists {
@@ -123,6 +143,7 @@ func newPVEManager(_ *Agent) *pveManager {
proxmox.WithAPIToken(tokenID, secret),
)
} else {
slog.Error("Env variables not set")
client = nil
}
@@ -133,13 +154,15 @@ func newPVEManager(_ *Agent) *pveManager {
}
// Retrieve node cpu count
if client != nil {
slog.Info("Getting node CPU count", "nodeName", nodeName)
node, err := client.Node(context.Background(), nodeName)
if err != nil {
pveManager.client = nil
slog.Error("Error getting node", "err", err)
} else {
pveManager.cpuCount = node.CPUInfo.CPUs
slog.Info("Node CPU count", "cpuCount", pveManager.cpuCount)
}
}
return pveManager
}