Fix cluster proxy token collision - store per-node control tokens
When multiple cluster nodes register sensor-proxy, each registration was overwriting the previous node's control token on the shared PVEInstance. This caused "Proxy token not recognized" errors on all but the last-registered node. Changes: - Add TemperatureProxyControlToken field to ClusterEndpoint struct - Store control tokens per-endpoint for cluster registrations - Check both instance-level and endpoint-level tokens when validating Related to #738
This commit is contained in:
parent
db56cb7d0d
commit
f8c7a30d28
2 changed files with 36 additions and 2 deletions
|
|
@ -230,6 +230,7 @@ func (h *TemperatureProxyHandlers) HandleRegister(w http.ResponseWriter, r *http
|
||||||
// Find matching PVE instance by hostname
|
// Find matching PVE instance by hostname
|
||||||
var matchedInstance *config.PVEInstance
|
var matchedInstance *config.PVEInstance
|
||||||
var matchedIndex int
|
var matchedIndex int
|
||||||
|
var matchedEndpointIndex = -1 // For cluster nodes, track which endpoint matched
|
||||||
|
|
||||||
for i := range nodesConfig.PVEInstances {
|
for i := range nodesConfig.PVEInstances {
|
||||||
instance := &nodesConfig.PVEInstances[i]
|
instance := &nodesConfig.PVEInstances[i]
|
||||||
|
|
@ -250,10 +251,11 @@ func (h *TemperatureProxyHandlers) HandleRegister(w http.ResponseWriter, r *http
|
||||||
|
|
||||||
// Check cluster endpoints
|
// Check cluster endpoints
|
||||||
if instance.IsCluster {
|
if instance.IsCluster {
|
||||||
for _, ep := range instance.ClusterEndpoints {
|
for j, ep := range instance.ClusterEndpoints {
|
||||||
if strings.EqualFold(ep.NodeName, hostname) || strings.Contains(strings.ToLower(ep.Host), strings.ToLower(hostname)) {
|
if strings.EqualFold(ep.NodeName, hostname) || strings.Contains(strings.ToLower(ep.Host), strings.ToLower(hostname)) {
|
||||||
matchedInstance = instance
|
matchedInstance = instance
|
||||||
matchedIndex = i
|
matchedIndex = i
|
||||||
|
matchedEndpointIndex = j
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -282,15 +284,28 @@ func (h *TemperatureProxyHandlers) HandleRegister(w http.ResponseWriter, r *http
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the instance with proxy configuration
|
// Update the instance with proxy configuration
|
||||||
|
// For clusters, store per-node tokens on the ClusterEndpoint; instance-level token is for non-cluster or fallback
|
||||||
nodesConfig.PVEInstances[matchedIndex].TemperatureProxyURL = proxyURL
|
nodesConfig.PVEInstances[matchedIndex].TemperatureProxyURL = proxyURL
|
||||||
if isHTTPMode {
|
if isHTTPMode {
|
||||||
nodesConfig.PVEInstances[matchedIndex].TemperatureProxyToken = authToken
|
nodesConfig.PVEInstances[matchedIndex].TemperatureProxyToken = authToken
|
||||||
}
|
}
|
||||||
nodesConfig.PVEInstances[matchedIndex].TemperatureProxyControlToken = ctrlToken
|
|
||||||
|
// For cluster nodes, store token on the specific endpoint so each node has its own token
|
||||||
|
if matchedEndpointIndex >= 0 && matchedInstance.IsCluster {
|
||||||
|
nodesConfig.PVEInstances[matchedIndex].ClusterEndpoints[matchedEndpointIndex].TemperatureProxyControlToken = ctrlToken
|
||||||
|
log.Debug().
|
||||||
|
Str("hostname", hostname).
|
||||||
|
Int("endpoint_index", matchedEndpointIndex).
|
||||||
|
Msg("Storing control token on cluster endpoint")
|
||||||
|
} else {
|
||||||
|
// Non-cluster instance or matched by instance name directly
|
||||||
|
nodesConfig.PVEInstances[matchedIndex].TemperatureProxyControlToken = ctrlToken
|
||||||
|
}
|
||||||
|
|
||||||
// Save updated configuration
|
// Save updated configuration
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Int("matchedIndex", matchedIndex).
|
Int("matchedIndex", matchedIndex).
|
||||||
|
Int("matchedEndpointIndex", matchedEndpointIndex).
|
||||||
Str("saving_url", nodesConfig.PVEInstances[matchedIndex].TemperatureProxyURL).
|
Str("saving_url", nodesConfig.PVEInstances[matchedIndex].TemperatureProxyURL).
|
||||||
Bool("saving_has_token", nodesConfig.PVEInstances[matchedIndex].TemperatureProxyToken != "").
|
Bool("saving_has_token", nodesConfig.PVEInstances[matchedIndex].TemperatureProxyToken != "").
|
||||||
Str("instance_name", nodesConfig.PVEInstances[matchedIndex].Name).
|
Str("instance_name", nodesConfig.PVEInstances[matchedIndex].Name).
|
||||||
|
|
@ -368,6 +383,8 @@ func (h *TemperatureProxyHandlers) HandleAuthorizedNodes(w http.ResponseWriter,
|
||||||
var matched *config.PVEInstance
|
var matched *config.PVEInstance
|
||||||
for i := range nodesConfig.PVEInstances {
|
for i := range nodesConfig.PVEInstances {
|
||||||
inst := &nodesConfig.PVEInstances[i]
|
inst := &nodesConfig.PVEInstances[i]
|
||||||
|
|
||||||
|
// Check instance-level token first
|
||||||
switch {
|
switch {
|
||||||
case strings.TrimSpace(inst.TemperatureProxyControlToken) == token:
|
case strings.TrimSpace(inst.TemperatureProxyControlToken) == token:
|
||||||
matched = inst
|
matched = inst
|
||||||
|
|
@ -378,6 +395,20 @@ func (h *TemperatureProxyHandlers) HandleAuthorizedNodes(w http.ResponseWriter,
|
||||||
if matched != nil {
|
if matched != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For clusters, also check per-node tokens on ClusterEndpoints
|
||||||
|
if inst.IsCluster {
|
||||||
|
for j := range inst.ClusterEndpoints {
|
||||||
|
ep := &inst.ClusterEndpoints[j]
|
||||||
|
if strings.TrimSpace(ep.TemperatureProxyControlToken) == token {
|
||||||
|
matched = inst
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matched != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshFromProxy := 0
|
refreshFromProxy := 0
|
||||||
|
|
|
||||||
|
|
@ -438,6 +438,9 @@ type ClusterEndpoint struct {
|
||||||
PulseReachable *bool // Pulse's view: can Pulse reach this endpoint? nil = not yet checked
|
PulseReachable *bool // Pulse's view: can Pulse reach this endpoint? nil = not yet checked
|
||||||
LastPulseCheck *time.Time // Last time Pulse checked connectivity
|
LastPulseCheck *time.Time // Last time Pulse checked connectivity
|
||||||
PulseError string // Last error Pulse encountered connecting to this endpoint
|
PulseError string // Last error Pulse encountered connecting to this endpoint
|
||||||
|
|
||||||
|
// Per-node temperature proxy tokens (for clusters with sensor-proxy on each node)
|
||||||
|
TemperatureProxyControlToken string // Control-plane token for this specific node
|
||||||
}
|
}
|
||||||
|
|
||||||
// PBSInstance represents a Proxmox Backup Server connection
|
// PBSInstance represents a Proxmox Backup Server connection
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue