fix: ensure proxmox nodes are displayed even if cluster endpoints are missing
Fixes #727. Previously, if temperature monitoring was enabled and a node wasn't found in ClusterEndpoints, the entire node processing was skipped. This change ensures we only skip temperature collection.
This commit is contained in:
parent
f8647b53ff
commit
d5fdf2f471
1 changed files with 88 additions and 85 deletions
|
|
@ -6165,6 +6165,7 @@ func (m *Monitor) pollPVEInstance(ctx context.Context, instanceName string, clie
|
||||||
// Prefer the resolved host for this node, with cluster overrides when available.
|
// Prefer the resolved host for this node, with cluster overrides when available.
|
||||||
sshHost := modelNode.Host
|
sshHost := modelNode.Host
|
||||||
foundNodeEndpoint := false
|
foundNodeEndpoint := false
|
||||||
|
shouldCollect := true
|
||||||
|
|
||||||
if modelNode.IsClusterMember && instanceCfg.IsCluster {
|
if modelNode.IsClusterMember && instanceCfg.IsCluster {
|
||||||
// For cluster members, wait until we have validated endpoints
|
// For cluster members, wait until we have validated endpoints
|
||||||
|
|
@ -6175,107 +6176,109 @@ func (m *Monitor) pollPVEInstance(ctx context.Context, instanceName string, clie
|
||||||
Str("node", node.Node).
|
Str("node", node.Node).
|
||||||
Str("instance", instanceCfg.Name).
|
Str("instance", instanceCfg.Name).
|
||||||
Msg("Skipping temperature collection - cluster endpoints not yet validated")
|
Msg("Skipping temperature collection - cluster endpoints not yet validated")
|
||||||
continue
|
shouldCollect = false
|
||||||
}
|
} else {
|
||||||
|
hasFingerprint := instanceCfg.Fingerprint != ""
|
||||||
hasFingerprint := instanceCfg.Fingerprint != ""
|
for _, ep := range instanceCfg.ClusterEndpoints {
|
||||||
for _, ep := range instanceCfg.ClusterEndpoints {
|
if strings.EqualFold(ep.NodeName, node.Node) {
|
||||||
if strings.EqualFold(ep.NodeName, node.Node) {
|
if effective := clusterEndpointEffectiveURL(ep, instanceCfg.VerifySSL, hasFingerprint); effective != "" {
|
||||||
if effective := clusterEndpointEffectiveURL(ep, instanceCfg.VerifySSL, hasFingerprint); effective != "" {
|
sshHost = effective
|
||||||
sshHost = effective
|
foundNodeEndpoint = true
|
||||||
foundNodeEndpoint = true
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If this node is a cluster member but we didn't find its specific endpoint,
|
// If this node is a cluster member but we didn't find its specific endpoint,
|
||||||
// skip temperature collection to avoid using wrong endpoint
|
// skip temperature collection to avoid using wrong endpoint
|
||||||
if !foundNodeEndpoint {
|
if !foundNodeEndpoint {
|
||||||
tempCancel()
|
tempCancel()
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("node", node.Node).
|
Str("node", node.Node).
|
||||||
Str("instance", instanceCfg.Name).
|
Str("instance", instanceCfg.Name).
|
||||||
Int("endpointCount", len(instanceCfg.ClusterEndpoints)).
|
Int("endpointCount", len(instanceCfg.ClusterEndpoints)).
|
||||||
Msg("Skipping temperature collection - node endpoint not found in cluster metadata")
|
Msg("Skipping temperature collection - node endpoint not found in cluster metadata")
|
||||||
continue
|
shouldCollect = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.TrimSpace(sshHost) == "" {
|
if shouldCollect {
|
||||||
sshHost = node.Node
|
if strings.TrimSpace(sshHost) == "" {
|
||||||
}
|
sshHost = node.Node
|
||||||
|
|
||||||
// Use HTTP proxy if configured for this instance, otherwise fall back to socket/SSH
|
|
||||||
temp, err := m.tempCollector.CollectTemperatureWithProxy(tempCtx, sshHost, node.Node, instanceCfg.TemperatureProxyURL, instanceCfg.TemperatureProxyToken)
|
|
||||||
tempCancel()
|
|
||||||
|
|
||||||
if err == nil && temp != nil && temp.Available {
|
|
||||||
// Get the current CPU temperature (prefer package, fall back to max)
|
|
||||||
currentTemp := temp.CPUPackage
|
|
||||||
if currentTemp == 0 && temp.CPUMax > 0 {
|
|
||||||
currentTemp = temp.CPUMax
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find previous temperature data for this node to preserve min/max
|
// Use HTTP proxy if configured for this instance, otherwise fall back to socket/SSH
|
||||||
var prevTemp *models.Temperature
|
temp, err := m.tempCollector.CollectTemperatureWithProxy(tempCtx, sshHost, node.Node, instanceCfg.TemperatureProxyURL, instanceCfg.TemperatureProxyToken)
|
||||||
for _, prevNode := range prevInstanceNodes {
|
tempCancel()
|
||||||
if prevNode.ID == modelNode.ID && prevNode.Temperature != nil {
|
|
||||||
prevTemp = prevNode.Temperature
|
if err == nil && temp != nil && temp.Available {
|
||||||
break
|
// Get the current CPU temperature (prefer package, fall back to max)
|
||||||
|
currentTemp := temp.CPUPackage
|
||||||
|
if currentTemp == 0 && temp.CPUMax > 0 {
|
||||||
|
currentTemp = temp.CPUMax
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize or update min/max tracking
|
// Find previous temperature data for this node to preserve min/max
|
||||||
if prevTemp != nil && prevTemp.CPUMin > 0 {
|
var prevTemp *models.Temperature
|
||||||
// Preserve existing min/max and update if necessary
|
for _, prevNode := range prevInstanceNodes {
|
||||||
temp.CPUMin = prevTemp.CPUMin
|
if prevNode.ID == modelNode.ID && prevNode.Temperature != nil {
|
||||||
temp.CPUMaxRecord = prevTemp.CPUMaxRecord
|
prevTemp = prevNode.Temperature
|
||||||
temp.MinRecorded = prevTemp.MinRecorded
|
break
|
||||||
temp.MaxRecorded = prevTemp.MaxRecorded
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update min if current is lower
|
// Initialize or update min/max tracking
|
||||||
if currentTemp > 0 && currentTemp < temp.CPUMin {
|
if prevTemp != nil && prevTemp.CPUMin > 0 {
|
||||||
|
// Preserve existing min/max and update if necessary
|
||||||
|
temp.CPUMin = prevTemp.CPUMin
|
||||||
|
temp.CPUMaxRecord = prevTemp.CPUMaxRecord
|
||||||
|
temp.MinRecorded = prevTemp.MinRecorded
|
||||||
|
temp.MaxRecorded = prevTemp.MaxRecorded
|
||||||
|
|
||||||
|
// Update min if current is lower
|
||||||
|
if currentTemp > 0 && currentTemp < temp.CPUMin {
|
||||||
|
temp.CPUMin = currentTemp
|
||||||
|
temp.MinRecorded = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update max if current is higher
|
||||||
|
if currentTemp > temp.CPUMaxRecord {
|
||||||
|
temp.CPUMaxRecord = currentTemp
|
||||||
|
temp.MaxRecorded = time.Now()
|
||||||
|
}
|
||||||
|
} else if currentTemp > 0 {
|
||||||
|
// First reading - initialize min/max to current value
|
||||||
temp.CPUMin = currentTemp
|
temp.CPUMin = currentTemp
|
||||||
temp.MinRecorded = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update max if current is higher
|
|
||||||
if currentTemp > temp.CPUMaxRecord {
|
|
||||||
temp.CPUMaxRecord = currentTemp
|
temp.CPUMaxRecord = currentTemp
|
||||||
|
temp.MinRecorded = time.Now()
|
||||||
temp.MaxRecorded = time.Now()
|
temp.MaxRecorded = time.Now()
|
||||||
}
|
}
|
||||||
} else if currentTemp > 0 {
|
|
||||||
// First reading - initialize min/max to current value
|
|
||||||
temp.CPUMin = currentTemp
|
|
||||||
temp.CPUMaxRecord = currentTemp
|
|
||||||
temp.MinRecorded = time.Now()
|
|
||||||
temp.MaxRecorded = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
modelNode.Temperature = temp
|
modelNode.Temperature = temp
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("node", node.Node).
|
Str("node", node.Node).
|
||||||
Str("sshHost", sshHost).
|
Str("sshHost", sshHost).
|
||||||
Float64("cpuPackage", temp.CPUPackage).
|
Float64("cpuPackage", temp.CPUPackage).
|
||||||
Float64("cpuMax", temp.CPUMax).
|
Float64("cpuMax", temp.CPUMax).
|
||||||
Float64("cpuMin", temp.CPUMin).
|
Float64("cpuMin", temp.CPUMin).
|
||||||
Float64("cpuMaxRecord", temp.CPUMaxRecord).
|
Float64("cpuMaxRecord", temp.CPUMaxRecord).
|
||||||
Int("nvmeCount", len(temp.NVMe)).
|
Int("nvmeCount", len(temp.NVMe)).
|
||||||
Msg("Collected temperature data")
|
Msg("Collected temperature data")
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("node", node.Node).
|
Str("node", node.Node).
|
||||||
Str("sshHost", sshHost).
|
Str("sshHost", sshHost).
|
||||||
Bool("isCluster", modelNode.IsClusterMember).
|
Bool("isCluster", modelNode.IsClusterMember).
|
||||||
Int("endpointCount", len(instanceCfg.ClusterEndpoints)).
|
Int("endpointCount", len(instanceCfg.ClusterEndpoints)).
|
||||||
Msg("Temperature collection failed - check SSH access")
|
Msg("Temperature collection failed - check SSH access")
|
||||||
} else if temp != nil {
|
} else if temp != nil {
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("node", node.Node).
|
Str("node", node.Node).
|
||||||
Str("sshHost", sshHost).
|
Str("sshHost", sshHost).
|
||||||
Bool("available", temp.Available).
|
Bool("available", temp.Available).
|
||||||
Msg("Temperature data unavailable after collection")
|
Msg("Temperature data unavailable after collection")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue