mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 00:17:39 +01:00
126 lines
2.4 KiB
Go
126 lines
2.4 KiB
Go
package monitoring
|
|
|
|
import (
|
|
"context"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type containerDiskOverride struct {
|
|
Used uint64
|
|
Total uint64
|
|
}
|
|
|
|
func clampToInt64(value uint64) int64 {
|
|
if value > math.MaxInt64 {
|
|
return math.MaxInt64
|
|
}
|
|
return int64(value)
|
|
}
|
|
|
|
func storageSupportsContainerVolumes(content string) bool {
|
|
if content == "" {
|
|
return false
|
|
}
|
|
|
|
for _, part := range strings.Split(content, ",") {
|
|
switch strings.TrimSpace(strings.ToLower(part)) {
|
|
case "rootdir", "images", "subvol":
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func isRootVolumeForContainer(volid string, vmid int) bool {
|
|
if vmid <= 0 || volid == "" {
|
|
return false
|
|
}
|
|
|
|
normalized := strings.ToLower(volid)
|
|
if idx := strings.Index(normalized, "@"); idx != -1 {
|
|
normalized = normalized[:idx]
|
|
}
|
|
|
|
id := strconv.Itoa(vmid)
|
|
patterns := []string{
|
|
"subvol-" + id + "-disk-0",
|
|
"vm-" + id + "-disk-0",
|
|
}
|
|
|
|
for _, pattern := range patterns {
|
|
if strings.Contains(normalized, pattern) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (m *Monitor) collectContainerRootUsage(ctx context.Context, client PVEClientInterface, node string, vmIDs []int) map[int]containerDiskOverride {
|
|
overrides := make(map[int]containerDiskOverride)
|
|
if len(vmIDs) == 0 {
|
|
return overrides
|
|
}
|
|
|
|
vmidSet := make(map[int]struct{}, len(vmIDs))
|
|
for _, id := range vmIDs {
|
|
vmidSet[id] = struct{}{}
|
|
}
|
|
|
|
storages, err := client.GetStorage(ctx, node)
|
|
if err != nil {
|
|
log.Debug().
|
|
Err(err).
|
|
Str("node", node).
|
|
Msg("Unable to list storages for container disk overrides")
|
|
return overrides
|
|
}
|
|
|
|
for _, storage := range storages {
|
|
if !storageSupportsContainerVolumes(storage.Content) {
|
|
continue
|
|
}
|
|
if !storageContentQueryable(storage) {
|
|
continue
|
|
}
|
|
|
|
contents, err := client.GetStorageContent(ctx, node, storage.Storage)
|
|
if err != nil {
|
|
log.Debug().
|
|
Err(err).
|
|
Str("node", node).
|
|
Str("storage", storage.Storage).
|
|
Msg("Container disk usage query failed; metrics for instance omitted this cycle")
|
|
continue
|
|
}
|
|
|
|
for _, item := range contents {
|
|
vmid := item.VMID
|
|
if vmid == 0 {
|
|
continue
|
|
}
|
|
if _, ok := vmidSet[vmid]; !ok {
|
|
continue
|
|
}
|
|
if !isRootVolumeForContainer(item.Volid, vmid) {
|
|
continue
|
|
}
|
|
if item.Used == 0 {
|
|
continue
|
|
}
|
|
|
|
overrides[vmid] = containerDiskOverride{
|
|
Used: item.Used,
|
|
Total: item.Size,
|
|
}
|
|
}
|
|
}
|
|
|
|
return overrides
|
|
}
|