Fix storage/disk/backup disappearing for clusters with VerifySSL enabled
Related to #670, #657
The fix in v4.26.5 (commit 59a97f2e3) attempted to resolve storage disappearing
by preferring hostnames over IPs when TLS hostname verification is required
(VerifySSL=true and no fingerprint). However, that fix was ineffective because
the cluster discovery code was populating BOTH the Host and IP fields with the
IP address.
**Root Cause:**
In internal/api/config_handlers.go, the detectPVECluster function was setting:
- endpoint.Host = schemePrefix + clusterNode.IP (when IP was available)
- endpoint.IP = clusterNode.IP
This meant both fields contained the same IP address. When the monitoring code
tried to prefer endpoint.Host for TLS validation (internal/monitoring/monitor.go:
361-368), it was still getting an IP, causing certificate validation to fail
with "certificate is valid for pve01.example.com, not 10.0.0.44".
**Solution:**
Separate the Host and IP fields properly during cluster discovery:
- endpoint.Host = hostname (e.g., "https://pve01:8006") for TLS validation
- endpoint.IP = IP address (e.g., "10.0.0.44") for DNS-free connections
The existing logic in clusterEndpointEffectiveURL() can now correctly choose
between them based on TLS requirements.
**Impact:**
Users with VerifySSL=true who upgraded to v4.26.1-v4.26.5 and lost storage
visibility should now see storage, VM disks, and backups again after this fix.
This commit is contained in:
parent
a39beca464
commit
6bf32f98d6
1 changed files with 16 additions and 15 deletions
|
|
@ -666,22 +666,22 @@ func detectPVECluster(clientConfig proxmox.ClientConfig, nodeName string, existi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the host URL with proper port
|
// Build the host URL with proper port
|
||||||
// Prefer IP if available, otherwise use node name
|
// Store hostname in Host field (for TLS validation), IP separately
|
||||||
nodeHost := clusterNode.IP
|
|
||||||
if nodeHost == "" {
|
|
||||||
nodeHost = clusterNode.Name
|
|
||||||
}
|
|
||||||
nodeHost = ensureHostHasPort(nodeHost, defaultPort)
|
|
||||||
|
|
||||||
endpoint := config.ClusterEndpoint{
|
endpoint := config.ClusterEndpoint{
|
||||||
NodeID: clusterNode.ID,
|
NodeID: clusterNode.ID,
|
||||||
NodeName: clusterNode.Name,
|
NodeName: clusterNode.Name,
|
||||||
Host: schemePrefix + nodeHost,
|
|
||||||
GuestURL: findExistingGuestURL(clusterNode.Name, existingEndpoints),
|
GuestURL: findExistingGuestURL(clusterNode.Name, existingEndpoints),
|
||||||
Online: clusterNode.Online == 1,
|
Online: clusterNode.Online == 1,
|
||||||
LastSeen: time.Now(),
|
LastSeen: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate Host field with hostname (if available) for TLS certificate validation
|
||||||
|
if clusterNode.Name != "" {
|
||||||
|
nodeHost := ensureHostHasPort(clusterNode.Name, defaultPort)
|
||||||
|
endpoint.Host = schemePrefix + nodeHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate IP field separately for DNS-free connections
|
||||||
if clusterNode.IP != "" {
|
if clusterNode.IP != "" {
|
||||||
endpoint.IP = clusterNode.IP
|
endpoint.IP = clusterNode.IP
|
||||||
}
|
}
|
||||||
|
|
@ -696,24 +696,25 @@ func detectPVECluster(clientConfig proxmox.ClientConfig, nodeName string, existi
|
||||||
Msg("All detected cluster nodes failed validation; falling back to cluster metadata")
|
Msg("All detected cluster nodes failed validation; falling back to cluster metadata")
|
||||||
|
|
||||||
for _, clusterNode := range unvalidatedNodes {
|
for _, clusterNode := range unvalidatedNodes {
|
||||||
nodeHost := clusterNode.IP
|
if clusterNode.Name == "" && clusterNode.IP == "" {
|
||||||
if nodeHost == "" {
|
|
||||||
nodeHost = clusterNode.Name
|
|
||||||
}
|
|
||||||
if nodeHost == "" {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nodeHost = ensureHostHasPort(nodeHost, defaultPort)
|
|
||||||
|
|
||||||
endpoint := config.ClusterEndpoint{
|
endpoint := config.ClusterEndpoint{
|
||||||
NodeID: clusterNode.ID,
|
NodeID: clusterNode.ID,
|
||||||
NodeName: clusterNode.Name,
|
NodeName: clusterNode.Name,
|
||||||
Host: schemePrefix + nodeHost,
|
|
||||||
GuestURL: findExistingGuestURL(clusterNode.Name, existingEndpoints),
|
GuestURL: findExistingGuestURL(clusterNode.Name, existingEndpoints),
|
||||||
Online: clusterNode.Online == 1,
|
Online: clusterNode.Online == 1,
|
||||||
LastSeen: time.Now(),
|
LastSeen: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate Host field with hostname (if available) for TLS certificate validation
|
||||||
|
if clusterNode.Name != "" {
|
||||||
|
nodeHost := ensureHostHasPort(clusterNode.Name, defaultPort)
|
||||||
|
endpoint.Host = schemePrefix + nodeHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate IP field separately for DNS-free connections
|
||||||
if clusterNode.IP != "" {
|
if clusterNode.IP != "" {
|
||||||
endpoint.IP = clusterNode.IP
|
endpoint.IP = clusterNode.IP
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue