functional/rpcpb: implement FetchSnapshot
@@ -18,12 +18,16 @@ import (
"context"
"fmt"
"net/url"
+ "os"
"time"
"github.com/coreos/etcd/clientv3"
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
"github.com/coreos/etcd/pkg/transport"
+ "github.com/coreos/etcd/snapshot"
+ "github.com/dustin/go-humanize"
+ "go.uber.org/zap"
grpc "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
@@ -229,7 +233,47 @@ func (m *Member) WriteHealthKey() error {
}
// FetchSnapshot downloads a snapshot file from this member.
-func (m *Member) FetchSnapshot() error {
+func (m *Member) FetchSnapshot(lg *zap.Logger) (err error) {
+ // remove existing snapshot first
+ if err = os.Remove(m.SnapshotPath); err != nil {
+ return err
+ }
+
+ var cli *clientv3.Client
+ cli, err = m.CreateEtcdClient()
+ if err != nil {
+ return fmt.Errorf("%v (%q)", err, m.EtcdClientEndpoint)
+ }
+ defer cli.Close()
+
+ now := time.Now()
+ mgr := snapshot.NewV3(cli, lg)
+ if err = mgr.Save(context.Background(), m.SnapshotPath); err != nil {
+ return err
+ }
+ took := time.Since(now)
+ var fi os.FileInfo
+ fi, err = os.Stat(m.SnapshotPath)
+ if err != nil {
+ return err
+ }
+
+ var st snapshot.Status
+ st, err = mgr.Status(m.SnapshotPath)
+ if err != nil {
+ return err
+ }
+
+ lg.Info(
+ "snapshot saved",
+ zap.String("snapshot-path", m.SnapshotPath),
+ zap.String("snapshot-file-size", humanize.Bytes(uint64(fi.Size()))),
+ zap.String("snapshot-total-size", humanize.Bytes(uint64(st.TotalSize))),
+ zap.Int("snapshot-total-key", st.TotalKey),
+ zap.Uint32("snapshot-hash", st.Hash),
+ zap.Int64("snapshot-revision", st.Revision),
+ zap.Duration("took", took),
+ )
return nil
}
