rejoin_test.go 5.1 KB

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