diff --git a/etcdserver/server.go b/etcdserver/server.go index 677285767..97b125fcf 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -27,6 +27,7 @@ import ( "os" "path" "regexp" + "sort" "sync/atomic" "time" @@ -193,7 +194,8 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) { haveWAL := wal.Exist(cfg.WALDir()) switch { case !haveWAL && !cfg.NewCluster: - cl, err := GetClusterFromPeers(cfg.Cluster.PeerURLs()) + us := getOtherPeerURLs(cfg.Cluster, cfg.Name) + cl, err := GetClusterFromPeers(us) if err != nil { return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %v", err) } @@ -748,6 +750,20 @@ func startNode(cfg *ServerConfig, ids []types.ID) (id types.ID, n raft.Node, w * return } +// getOtherPeerURLs returns peer urls of other members in the cluster. The +// returned list is sorted in ascending lexicographical order. +func getOtherPeerURLs(cl ClusterInfo, self string) []string { + us := make([]string, 0) + for _, m := range cl.Members() { + if m.Name == self { + continue + } + us = append(us, m.PeerURLs...) + } + sort.Strings(us) + return us +} + func restartNode(cfg *ServerConfig, index uint64, snapshot *raftpb.Snapshot) (id types.ID, n raft.Node, w *wal.WAL) { var err error // restart a node from previous wal diff --git a/etcdserver/server_test.go b/etcdserver/server_test.go index 8caa1ad7f..25fa25bc9 100644 --- a/etcdserver/server_test.go +++ b/etcdserver/server_test.go @@ -1093,6 +1093,47 @@ func TestPublishRetry(t *testing.T) { } } +func TestGetOtherPeerURLs(t *testing.T) { + tests := []struct { + membs []*Member + self string + wurls []string + }{ + { + []*Member{ + newTestMemberp(1, []string{"http://10.0.0.1"}, "a", nil), + }, + "a", + []string{}, + }, + { + []*Member{ + newTestMemberp(1, []string{"http://10.0.0.1"}, "a", nil), + newTestMemberp(2, []string{"http://10.0.0.2"}, "b", nil), + newTestMemberp(3, []string{"http://10.0.0.3"}, "c", nil), + }, + "a", + []string{"http://10.0.0.2", "http://10.0.0.3"}, + }, + { + []*Member{ + newTestMemberp(1, []string{"http://10.0.0.1"}, "a", nil), + newTestMemberp(3, []string{"http://10.0.0.3"}, "c", nil), + newTestMemberp(2, []string{"http://10.0.0.2"}, "b", nil), + }, + "a", + []string{"http://10.0.0.2", "http://10.0.0.3"}, + }, + } + for i, tt := range tests { + cl := NewClusterFromMembers("", types.ID(0), tt.membs) + urls := getOtherPeerURLs(cl, tt.self) + if !reflect.DeepEqual(urls, tt.wurls) { + t.Errorf("#%d: urls = %+v, want %+v", i, urls, tt.wurls) + } + } +} + func TestGetBool(t *testing.T) { tests := []struct { b *bool