rejoin_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. package test
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "os"
  6. "strconv"
  7. "strings"
  8. "testing"
  9. "time"
  10. "github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
  11. )
  12. func increasePeerAddressPort(args []string, delta int) []string {
  13. for i, arg := range args {
  14. if !strings.Contains(arg, "peer-addr") {
  15. continue
  16. }
  17. splitArg := strings.Split(arg, ":")
  18. port, _ := strconv.Atoi(splitArg[len(splitArg)-1])
  19. args[i] = "-peer-addr=127.0.0.1:" + strconv.Itoa(port+delta)
  20. return args
  21. }
  22. return append(args, "-peer-addr=127.0.0.1:"+strconv.Itoa(7001+delta))
  23. }
  24. func increaseAddressPort(args []string, delta int) []string {
  25. for i, arg := range args {
  26. if !strings.HasPrefix(arg, "-addr") && !strings.HasPrefix(arg, "--addr") {
  27. continue
  28. }
  29. splitArg := strings.Split(arg, ":")
  30. port, _ := strconv.Atoi(splitArg[len(splitArg)-1])
  31. args[i] = "-addr=127.0.0.1:" + strconv.Itoa(port+delta)
  32. return args
  33. }
  34. return append(args, "-addr=127.0.0.1:"+strconv.Itoa(4001+delta))
  35. }
  36. func increaseDataDir(args []string, delta int) []string {
  37. for i, arg := range args {
  38. if !strings.Contains(arg, "-data-dir") {
  39. continue
  40. }
  41. splitArg := strings.Split(arg, "node")
  42. idx, _ := strconv.Atoi(splitArg[len(splitArg)-1])
  43. args[i] = "-data-dir=/tmp/node" + strconv.Itoa(idx+delta)
  44. return args
  45. }
  46. return args
  47. }
  48. // Create a five-node cluster
  49. // Random kill one of the nodes and restart it with different peer address
  50. func TestRejoinWithDifferentPeerAddress(t *testing.T) {
  51. procAttr := new(os.ProcAttr)
  52. procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
  53. clusterSize := 5
  54. argGroup, etcds, err := CreateCluster(clusterSize, procAttr, false)
  55. if err != nil {
  56. t.Fatal("cannot create cluster")
  57. }
  58. defer DestroyCluster(etcds)
  59. time.Sleep(2 * time.Second)
  60. for i := 0; i < 10; i++ {
  61. num := rand.Int() % clusterSize
  62. fmt.Println("kill node", num+1)
  63. etcds[num].Kill()
  64. etcds[num].Release()
  65. time.Sleep(time.Second)
  66. argGroup[num] = increasePeerAddressPort(argGroup[num], clusterSize)
  67. // restart
  68. etcds[num], err = os.StartProcess(EtcdBinPath, argGroup[num], procAttr)
  69. if err != nil {
  70. panic(err)
  71. }
  72. time.Sleep(time.Second)
  73. }
  74. c := etcd.NewClient(nil)
  75. c.SyncCluster()
  76. result, err := c.Set("foo", "bar", 0)
  77. if err != nil || result.Node.Key != "/foo" || result.Node.Value != "bar" {
  78. t.Fatal("Failed to set value in etcd cluster")
  79. }
  80. }
  81. // Create a five-node cluster
  82. // Replace one of the nodes with different peer address
  83. func TestReplaceWithDifferentPeerAddress(t *testing.T) {
  84. // TODO(yichengq): find some way to avoid the error that will be
  85. // caused if some node joins the cluster with the collided name.
  86. // Possible solutions:
  87. // 1. Remove itself when executing a join command with the same name
  88. // and different peer address. However, it should find some way to
  89. // trigger that execution because the leader may update its address
  90. // and stop heartbeat.
  91. // 2. Remove the node with the same name before join each time.
  92. // But this way could be rather overkill.
  93. t.Skip("Unimplemented functionality")
  94. procAttr := new(os.ProcAttr)
  95. procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
  96. clusterSize := 5
  97. argGroup, etcds, err := CreateCluster(clusterSize, procAttr, false)
  98. if err != nil {
  99. t.Fatal("cannot create cluster")
  100. }
  101. defer DestroyCluster(etcds)
  102. time.Sleep(2 * time.Second)
  103. rand.Int()
  104. for i := 0; i < 10; i++ {
  105. num := rand.Int() % clusterSize
  106. fmt.Println("replace node", num+1)
  107. argGroup[num] = increasePeerAddressPort(argGroup[num], clusterSize)
  108. argGroup[num] = increaseAddressPort(argGroup[num], clusterSize)
  109. argGroup[num] = increaseDataDir(argGroup[num], clusterSize)
  110. // restart
  111. newEtcd, err := os.StartProcess(EtcdBinPath, append(argGroup[num], "-f"), procAttr)
  112. if err != nil {
  113. panic(err)
  114. }
  115. etcds[num].Wait()
  116. etcds[num] = newEtcd
  117. }
  118. c := etcd.NewClient(nil)
  119. c.SyncCluster()
  120. result, err := c.Set("foo", "bar", 0)
  121. if err != nil || result.Node.Key != "/foo" || result.Node.Value != "bar" {
  122. t.Fatal("Failed to set value in etcd cluster")
  123. }
  124. }
  125. // Create a five-node cluster
  126. // Let the sixth instance join with different name and existing peer address
  127. func TestRejoinWithDifferentName(t *testing.T) {
  128. procAttr := new(os.ProcAttr)
  129. procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
  130. clusterSize := 5
  131. argGroup, etcds, err := CreateCluster(clusterSize, procAttr, false)
  132. if err != nil {
  133. t.Fatal("cannot create cluster")
  134. }
  135. defer DestroyCluster(etcds)
  136. time.Sleep(2 * time.Second)
  137. num := rand.Int() % clusterSize
  138. fmt.Println("join node 6 that collides with node", num+1)
  139. // kill
  140. etcds[num].Kill()
  141. etcds[num].Release()
  142. time.Sleep(time.Second)
  143. for i := 0; i < 2; i++ {
  144. // restart
  145. if i == 0 {
  146. etcds[num], err = os.StartProcess(EtcdBinPath, append(argGroup[num], "-name=node6", "-peers=127.0.0.1:7002"), procAttr)
  147. } else {
  148. etcds[num], err = os.StartProcess(EtcdBinPath, append(argGroup[num], "-f", "-name=node6", "-peers=127.0.0.1:7002"), procAttr)
  149. }
  150. if err != nil {
  151. t.Fatal("failed to start process:", err)
  152. }
  153. timer := time.AfterFunc(10*time.Second, func() {
  154. t.Fatal("new etcd should fail immediately")
  155. })
  156. etcds[num].Wait()
  157. etcds[num] = nil
  158. timer.Stop()
  159. }
  160. }