From 38f276dc475c7719100db01d05d5188f65695f28 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Tue, 20 Jan 2015 16:19:29 -0800 Subject: [PATCH] consul: remove ourself from raft peer set if we are the leader --- consul/server.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/consul/server.go b/consul/server.go index 14b9bd5ad1..57bd1edc15 100644 --- a/consul/server.go +++ b/consul/server.go @@ -521,6 +521,25 @@ func (s *Server) Leave() error { s.logger.Printf("[INFO] consul: server starting leave") s.left = true + // Check the number of known peers + numPeers, err := s.numOtherPeers() + if err != nil { + s.logger.Printf("[ERR] consul: failed to check raft peers: %v", err) + return err + } + + // If we are the current leader, and we have any other peers (cluster has multiple + // servers), we should do a RemovePeer to safely reduce the quorum size. If we are + // not the leader, then we should issue our leave intention and wait to be removed + // for some sane period of time. + isLeader := s.IsLeader() + if isLeader && numPeers > 0 { + future := s.raft.RemovePeer(s.raftTransport.LocalAddr()) + if err := future.Error(); err != nil && err != raft.ErrUnknownPeer { + s.logger.Printf("[ERR] consul: failed to remove ourself as raft peer: %v", err) + } + } + // Leave the WAN pool if s.serfWAN != nil { if err := s.serfWAN.Leave(); err != nil { @@ -537,6 +556,17 @@ func (s *Server) Leave() error { return nil } +// numOtherPeers is used to check on the number of known peers +// excluding the local ndoe +func (s *Server) numOtherPeers() (int, error) { + peers, err := s.raftPeers.Peers() + if err != nil { + return 0, err + } + otherPeers := raft.ExcludePeer(peers, s.raftTransport.LocalAddr()) + return len(otherPeers), nil +} + // JoinLAN is used to have Consul join the inner-DC pool // The target address should be another node inside the DC // listening on the Serf LAN address