backup_command.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright 2015 CoreOS, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package command
  15. import (
  16. "log"
  17. "os"
  18. "path"
  19. "time"
  20. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/codegangsta/cli"
  21. "github.com/coreos/etcd/etcdserver/etcdserverpb"
  22. "github.com/coreos/etcd/pkg/idutil"
  23. "github.com/coreos/etcd/pkg/pbutil"
  24. "github.com/coreos/etcd/snap"
  25. "github.com/coreos/etcd/wal"
  26. "github.com/coreos/etcd/wal/walpb"
  27. )
  28. func NewBackupCommand() cli.Command {
  29. return cli.Command{
  30. Name: "backup",
  31. Usage: "backup an etcd directory",
  32. Flags: []cli.Flag{
  33. cli.StringFlag{Name: "data-dir", Value: "", Usage: "Path to the etcd data dir"},
  34. cli.StringFlag{Name: "backup-dir", Value: "", Usage: "Path to the backup dir"},
  35. },
  36. Action: handleBackup,
  37. }
  38. }
  39. // handleBackup handles a request that intends to do a backup.
  40. func handleBackup(c *cli.Context) {
  41. srcSnap := path.Join(c.String("data-dir"), "snap")
  42. destSnap := path.Join(c.String("backup-dir"), "snap")
  43. srcWAL := path.Join(c.String("data-dir"), "wal")
  44. destWAL := path.Join(c.String("backup-dir"), "wal")
  45. if err := os.MkdirAll(destSnap, 0700); err != nil {
  46. log.Fatalf("failed creating backup snapshot dir %v: %v", destSnap, err)
  47. }
  48. ss := snap.New(srcSnap)
  49. snapshot, err := ss.Load()
  50. if err != nil && err != snap.ErrNoSnapshot {
  51. log.Fatal(err)
  52. }
  53. var walsnap walpb.Snapshot
  54. if snapshot != nil {
  55. walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term
  56. newss := snap.New(destSnap)
  57. if err := newss.SaveSnap(*snapshot); err != nil {
  58. log.Fatal(err)
  59. }
  60. }
  61. w, err := wal.OpenNotInUse(srcWAL, walsnap)
  62. if err != nil {
  63. log.Fatal(err)
  64. }
  65. defer w.Close()
  66. wmetadata, state, ents, err := w.ReadAll()
  67. if err != nil {
  68. log.Fatal(err)
  69. }
  70. var metadata etcdserverpb.Metadata
  71. pbutil.MustUnmarshal(&metadata, wmetadata)
  72. idgen := idutil.NewGenerator(0, time.Now())
  73. metadata.NodeID = idgen.Next()
  74. metadata.ClusterID = idgen.Next()
  75. neww, err := wal.Create(destWAL, pbutil.MustMarshal(&metadata))
  76. if err != nil {
  77. log.Fatal(err)
  78. }
  79. defer neww.Close()
  80. if err := neww.Save(state, ents); err != nil {
  81. log.Fatal(err)
  82. }
  83. }