etcd4.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package migrate
  2. import (
  3. "fmt"
  4. "log"
  5. "os"
  6. "path"
  7. pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
  8. "github.com/coreos/etcd/pkg/pbutil"
  9. "github.com/coreos/etcd/pkg/types"
  10. raftpb "github.com/coreos/etcd/raft/raftpb"
  11. "github.com/coreos/etcd/snap"
  12. "github.com/coreos/etcd/wal"
  13. "github.com/coreos/etcd/wal/walpb"
  14. )
  15. func snapDir4(dataDir string) string {
  16. return path.Join(dataDir, "snapshot")
  17. }
  18. func logFile4(dataDir string) string {
  19. return path.Join(dataDir, "log")
  20. }
  21. func cfgFile4(dataDir string) string {
  22. return path.Join(dataDir, "conf")
  23. }
  24. func snapDir2(dataDir string) string {
  25. return path.Join(dataDir, "snap")
  26. }
  27. func walDir2(dataDir string) string {
  28. return path.Join(dataDir, "wal")
  29. }
  30. func Migrate4To2(dataDir string, name string) error {
  31. // prep new directories
  32. sd2 := snapDir2(dataDir)
  33. if err := os.MkdirAll(sd2, 0700); err != nil {
  34. return fmt.Errorf("failed creating snapshot directory %s: %v", sd2, err)
  35. }
  36. // read v0.4 data
  37. snap4, err := DecodeLatestSnapshot4FromDir(snapDir4(dataDir))
  38. if err != nil {
  39. return err
  40. }
  41. cfg4, err := DecodeConfig4FromFile(cfgFile4(dataDir))
  42. if err != nil {
  43. return err
  44. }
  45. ents4, err := DecodeLog4FromFile(logFile4(dataDir))
  46. if err != nil {
  47. return err
  48. }
  49. nodeIDs := ents4.NodeIDs()
  50. nodeID := GuessNodeID(nodeIDs, snap4, cfg4, name)
  51. if nodeID == 0 {
  52. return fmt.Errorf("Couldn't figure out the node ID from the log or flags, cannot convert")
  53. }
  54. metadata := pbutil.MustMarshal(&pb.Metadata{NodeID: nodeID, ClusterID: 0x04add5})
  55. wd2 := walDir2(dataDir)
  56. w, err := wal.Create(wd2, metadata)
  57. if err != nil {
  58. return fmt.Errorf("failed initializing wal at %s: %v", wd2, err)
  59. }
  60. defer w.Close()
  61. // transform v0.4 data
  62. var snap2 *raftpb.Snapshot
  63. if snap4 == nil {
  64. log.Printf("No snapshot found")
  65. } else {
  66. log.Printf("Found snapshot: lastIndex=%d", snap4.LastIndex)
  67. snap2 = snap4.Snapshot2()
  68. }
  69. st2 := cfg4.HardState2()
  70. // If we've got the most recent snapshot, we can use it's committed index. Still likely less than the current actual index, but worth it for the replay.
  71. if snap2 != nil {
  72. st2.Commit = snap2.Metadata.Index
  73. }
  74. ents2, err := Entries4To2(ents4)
  75. if err != nil {
  76. return err
  77. }
  78. ents2Len := len(ents2)
  79. log.Printf("Found %d log entries: firstIndex=%d lastIndex=%d", ents2Len, ents2[0].Index, ents2[ents2Len-1].Index)
  80. // explicitly prepend an empty entry as the WAL code expects it
  81. ents2 = append(make([]raftpb.Entry, 1), ents2...)
  82. if err = w.Save(st2, ents2); err != nil {
  83. return err
  84. }
  85. log.Printf("Log migration successful")
  86. // migrate snapshot (if necessary) and logs
  87. var walsnap walpb.Snapshot
  88. if snap2 != nil {
  89. walsnap.Index, walsnap.Term = snap2.Metadata.Index, snap2.Metadata.Term
  90. ss := snap.New(sd2)
  91. if err := ss.SaveSnap(*snap2); err != nil {
  92. return err
  93. }
  94. log.Printf("Snapshot migration successful")
  95. }
  96. if err = w.SaveSnapshot(walsnap); err != nil {
  97. return err
  98. }
  99. return nil
  100. }
  101. func GuessNodeID(nodes map[string]uint64, snap4 *Snapshot4, cfg *Config4, name string) uint64 {
  102. var snapNodes map[string]uint64
  103. if snap4 != nil {
  104. snapNodes = snap4.GetNodesFromStore()
  105. }
  106. // First, use the flag, if set.
  107. if name != "" {
  108. log.Printf("Using suggested name %s", name)
  109. if val, ok := nodes[name]; ok {
  110. log.Printf("Assigning %s the ID %s", name, types.ID(val))
  111. return val
  112. }
  113. if snapNodes != nil {
  114. if val, ok := snapNodes[name]; ok {
  115. log.Printf("Assigning %s the ID %s", name, types.ID(val))
  116. return val
  117. }
  118. }
  119. log.Printf("Name not found, autodetecting...")
  120. }
  121. // Next, look at the snapshot peers, if that exists.
  122. if snap4 != nil {
  123. //snapNodes := make(map[string]uint64)
  124. //for _, p := range snap4.Peers {
  125. //m := generateNodeMember(p.Name, p.ConnectionString, "")
  126. //snapNodes[p.Name] = uint64(m.ID)
  127. //}
  128. for _, p := range cfg.Peers {
  129. delete(snapNodes, p.Name)
  130. }
  131. if len(snapNodes) == 1 {
  132. for name, id := range nodes {
  133. log.Printf("Autodetected from snapshot: name %s", name)
  134. return id
  135. }
  136. }
  137. }
  138. // Then, try and deduce from the log.
  139. for _, p := range cfg.Peers {
  140. delete(nodes, p.Name)
  141. }
  142. if len(nodes) == 1 {
  143. for name, id := range nodes {
  144. log.Printf("Autodetected name %s", name)
  145. return id
  146. }
  147. }
  148. return 0
  149. }