mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 11:30:15 +00:00
116 lines
3.5 KiB
Go
116 lines
3.5 KiB
Go
package monitoring
|
|
|
|
import (
|
|
"math"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/models"
|
|
"github.com/rcourtman/pulse-go-rewrite/pkg/proxmox"
|
|
)
|
|
|
|
const (
|
|
vmMemoryCarryForwardMaxAge = 2 * time.Minute
|
|
vmMemoryHealthyGuestMaxAge = 10 * time.Minute
|
|
vmMemoryCarryForwardMinUsageDelta = 5.0
|
|
vmMemorySourceReliabilityLow = 0
|
|
vmMemorySourceReliabilityFallback = 1
|
|
vmMemorySourceReliabilityTrusted = 2
|
|
)
|
|
|
|
func vmMemorySourceReliability(source string) int {
|
|
switch strings.TrimSpace(source) {
|
|
case "meminfo-available", "meminfo-derived", "guest-agent-meminfo",
|
|
"rrd-memavailable", "rrd-memused", "host-agent":
|
|
return vmMemorySourceReliabilityTrusted
|
|
case "meminfo-total-minus-used", "previous-snapshot":
|
|
return vmMemorySourceReliabilityFallback
|
|
case "", "cluster-resources", "listing-mem", "status-mem", "status-freemem", "status-unavailable":
|
|
return vmMemorySourceReliabilityLow
|
|
default:
|
|
return vmMemorySourceReliabilityFallback
|
|
}
|
|
}
|
|
|
|
func shouldCarryForwardPreviousVMMemory(prev models.VM, currentStatus, currentSource string, currentTotal, currentUsed uint64, now time.Time) bool {
|
|
if currentStatus != "running" || prev.Type != "qemu" || prev.Status != "running" {
|
|
return false
|
|
}
|
|
if prev.Memory.Total <= 0 || prev.Memory.Used < 0 {
|
|
return false
|
|
}
|
|
if prev.LastSeen.IsZero() || now.Sub(prev.LastSeen) > vmMemoryCarryForwardMaxAge {
|
|
return false
|
|
}
|
|
|
|
prevReliability := vmMemorySourceReliability(prev.MemorySource)
|
|
currentReliability := vmMemorySourceReliability(currentSource)
|
|
if prevReliability < vmMemorySourceReliabilityTrusted || currentReliability > vmMemorySourceReliabilityFallback {
|
|
return false
|
|
}
|
|
if prevReliability <= currentReliability {
|
|
return false
|
|
}
|
|
|
|
if currentTotal > 0 && prev.Memory.Total > 0 && prev.Memory.Total != int64(currentTotal) {
|
|
return false
|
|
}
|
|
|
|
currentUsage := safePercentage(float64(currentUsed), float64(currentTotal))
|
|
if prev.Memory.Usage > 0 && math.Abs(prev.Memory.Usage-currentUsage) < vmMemoryCarryForwardMinUsageDelta {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func shouldCarryForwardHealthyGuestLowTrustVMMemory(prev models.VM, currentStatus, currentSource string, currentTotal, currentUsed uint64, now time.Time, guestAgentHealthy bool) bool {
|
|
if !guestAgentHealthy || currentStatus != "running" || prev.Type != "qemu" || prev.Status != "running" {
|
|
return false
|
|
}
|
|
if prev.Memory.Total <= 0 || prev.Memory.Used < 0 {
|
|
return false
|
|
}
|
|
if prev.LastSeen.IsZero() || now.Sub(prev.LastSeen) > vmMemoryHealthyGuestMaxAge {
|
|
return false
|
|
}
|
|
if currentTotal == 0 || prev.Memory.Total != int64(currentTotal) {
|
|
return false
|
|
}
|
|
if vmMemorySourceReliability(currentSource) != vmMemorySourceReliabilityLow {
|
|
return false
|
|
}
|
|
|
|
currentUsage := safePercentage(float64(currentUsed), float64(currentTotal))
|
|
if currentUsage < 99 {
|
|
return false
|
|
}
|
|
if prev.Memory.Usage >= 90 || math.Abs(prev.Memory.Usage-currentUsage) < vmMemoryCarryForwardMinUsageDelta {
|
|
return false
|
|
}
|
|
|
|
prevReliability := vmMemorySourceReliability(prev.MemorySource)
|
|
if prev.MemorySource != "previous-snapshot" && prevReliability < vmMemorySourceReliabilityTrusted {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func guestAgentSignalsHealthy(
|
|
detailedStatus *proxmox.VMStatus,
|
|
diskFromAgent bool,
|
|
ipAddresses []string,
|
|
networkInterfaces []models.GuestNetworkInterface,
|
|
osName, osVersion, agentVersion string,
|
|
) bool {
|
|
if detailedStatus != nil && detailedStatus.Agent.Value > 0 {
|
|
return true
|
|
}
|
|
return diskFromAgent ||
|
|
len(ipAddresses) > 0 ||
|
|
len(networkInterfaces) > 0 ||
|
|
osName != "" ||
|
|
osVersion != "" ||
|
|
agentVersion != ""
|
|
}
|