mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-21 14:46:58 +00:00
fix: canonicalize host in AllocateBlockVolumeResponse (CP13-2 follow-up)
AllocateBlockVolumeResponse used bs.ListenAddr() to derive replica addresses. When the VS binds to ":port" (no explicit IP), host resolved to empty string, producing ":dataPort" as the replica address. This ":port" propagated through master assignments to both primary and replica sides. Now canonicalizes empty/wildcard host using PreferredOutboundIP() before constructing replication addresses. Also exported PreferredOutboundIP for use by the server package. This is the source fix — all downstream paths (heartbeat, API response, assignment) inherit the canonical address. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
ae87a31d22
commit
abbc8bff2b
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/storage/blockvol"
|
||||
)
|
||||
|
||||
// AllocateBlockVolume creates a new block volume on this volume server.
|
||||
@@ -31,6 +32,10 @@ func (vs *VolumeServer) AllocateBlockVolume(_ context.Context, req *volume_serve
|
||||
if idx := strings.LastIndex(host, ":"); idx >= 0 {
|
||||
host = host[:idx]
|
||||
}
|
||||
// Canonicalize: if host is empty (VS bound to ":port"), resolve to routable IP.
|
||||
if host == "" || host == "0.0.0.0" || host == "::" || host == "[::]" {
|
||||
host = blockvol.PreferredOutboundIP()
|
||||
}
|
||||
|
||||
resp := &volume_server_pb.AllocateBlockVolumeResponse{
|
||||
Path: path,
|
||||
|
||||
@@ -370,6 +370,9 @@ func (bs *BlockService) setupPrimaryReplication(path, replicaDataAddr, replicaCt
|
||||
return
|
||||
}
|
||||
// Track replication state for heartbeat reporting (R1-4).
|
||||
// These addresses are what the primary ships to — they come from the
|
||||
// master's assignment. They should already be canonical (from
|
||||
// AllocateBlockVolumeResponse), but if not, they'll be reported as-is.
|
||||
bs.replMu.Lock()
|
||||
if bs.replStates == nil {
|
||||
bs.replStates = make(map[string]*volReplState)
|
||||
|
||||
@@ -27,7 +27,7 @@ func canonicalizeListenerAddr(addr net.Addr, advertisedHost string) string {
|
||||
// Wildcard bind — use advertised host or fallback.
|
||||
host := advertisedHost
|
||||
if host == "" {
|
||||
host = preferredOutboundIP()
|
||||
host = PreferredOutboundIP()
|
||||
}
|
||||
if host == "" {
|
||||
// Last resort: return raw address (will be ":port").
|
||||
@@ -42,7 +42,8 @@ func canonicalizeListenerAddr(addr net.Addr, advertisedHost string) string {
|
||||
//
|
||||
// This is a fallback — callers should prefer an explicitly configured
|
||||
// advertised host when available.
|
||||
func preferredOutboundIP() string {
|
||||
// PreferredOutboundIP returns the machine's preferred outbound IP as a string.
|
||||
func PreferredOutboundIP() string {
|
||||
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||
if err != nil {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user