Skip to content

Commit 58f9a5d

Browse files
committed
Handle Serf Reap event
This PR adds handling of the Serf member reap event to remove the peer from Raft.
1 parent f4a08a1 commit 58f9a5d

File tree

2 files changed

+93
-2
lines changed

2 files changed

+93
-2
lines changed

nomad/serf.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ func (s *Server) serfEventHandler() {
3434
case serf.EventMemberLeave, serf.EventMemberFailed:
3535
s.nodeFailed(e.(serf.MemberEvent))
3636
s.localMemberEvent(e.(serf.MemberEvent))
37-
case serf.EventMemberUpdate, serf.EventMemberReap,
38-
serf.EventUser, serf.EventQuery: // Ignore
37+
case serf.EventMemberReap:
38+
s.localMemberEvent(e.(serf.MemberEvent))
39+
case serf.EventMemberUpdate, serf.EventUser, serf.EventQuery: // Ignore
3940
default:
4041
s.logger.Printf("[WARN] nomad: unhandled serf event: %#v", e)
4142
}

nomad/serf_test.go

+90
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import (
55
"fmt"
66
"os"
77
"path"
8+
"strings"
89
"testing"
910

1011
"github.com/hashicorp/nomad/testutil"
12+
"github.com/hashicorp/serf/serf"
1113
)
1214

1315
func TestNomad_JoinPeer(t *testing.T) {
@@ -88,6 +90,94 @@ func TestNomad_RemovePeer(t *testing.T) {
8890
})
8991
}
9092

93+
func TestNomad_ReapPeer(t *testing.T) {
94+
dir := tmpDir(t)
95+
defer os.RemoveAll(dir)
96+
s1 := testServer(t, func(c *Config) {
97+
c.BootstrapExpect = 3
98+
c.DevMode = false
99+
c.DevDisableBootstrap = true
100+
c.DataDir = path.Join(dir, "node1")
101+
})
102+
defer s1.Shutdown()
103+
s2 := testServer(t, func(c *Config) {
104+
c.BootstrapExpect = 3
105+
c.DevMode = false
106+
c.DevDisableBootstrap = true
107+
c.DataDir = path.Join(dir, "node2")
108+
})
109+
defer s2.Shutdown()
110+
s3 := testServer(t, func(c *Config) {
111+
c.BootstrapExpect = 3
112+
c.DevMode = false
113+
c.DevDisableBootstrap = true
114+
c.DataDir = path.Join(dir, "node3")
115+
})
116+
defer s3.Shutdown()
117+
testJoin(t, s1, s2, s3)
118+
119+
testutil.WaitForResult(func() (bool, error) {
120+
if members := s1.Members(); len(members) != 3 {
121+
return false, fmt.Errorf("bad: %#v", members)
122+
}
123+
if members := s2.Members(); len(members) != 3 {
124+
return false, fmt.Errorf("bad: %#v", members)
125+
}
126+
if members := s3.Members(); len(members) != 3 {
127+
return false, fmt.Errorf("bad: %#v", members)
128+
}
129+
return true, nil
130+
}, func(err error) {
131+
t.Fatalf("err: %v", err)
132+
})
133+
134+
testutil.WaitForLeader(t, s1.RPC)
135+
136+
// Simulate a reap
137+
mems := s1.Members()
138+
var s2mem serf.Member
139+
for _, m := range mems {
140+
if strings.Contains(m.Name, s2.config.NodeName) {
141+
s2mem = m
142+
s2mem.Status = StatusReap
143+
break
144+
}
145+
}
146+
147+
// Shutdown and then send the reap
148+
s2.Shutdown()
149+
s1.reconcileCh <- s2mem
150+
s2.reconcileCh <- s2mem
151+
s3.reconcileCh <- s2mem
152+
153+
testutil.WaitForResult(func() (bool, error) {
154+
if len(s1.peers["global"]) != 2 {
155+
return false, fmt.Errorf("bad: %#v", s1.peers["global"])
156+
}
157+
peers, err := s1.numPeers()
158+
if err != nil {
159+
return false, fmt.Errorf("numPeers() failed: %v", err)
160+
}
161+
if peers != 2 {
162+
return false, fmt.Errorf("bad: %#v", peers)
163+
}
164+
165+
if len(s3.peers["global"]) != 2 {
166+
return false, fmt.Errorf("bad: %#v", s1.peers["global"])
167+
}
168+
peers, err = s3.numPeers()
169+
if err != nil {
170+
return false, fmt.Errorf("numPeers() failed: %v", err)
171+
}
172+
if peers != 2 {
173+
return false, fmt.Errorf("bad: %#v", peers)
174+
}
175+
return true, nil
176+
}, func(err error) {
177+
t.Fatalf("err: %v", err)
178+
})
179+
}
180+
91181
func TestNomad_BootstrapExpect(t *testing.T) {
92182
dir := tmpDir(t)
93183
defer os.RemoveAll(dir)

0 commit comments

Comments
 (0)