123 lines
2.7 KiB
Go
123 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
|
|
dstore "github.com/ipfs/go-datastore"
|
|
"github.com/mitchellh/go-homedir"
|
|
"github.com/urfave/cli/v2"
|
|
"golang.org/x/xerrors"
|
|
"gopkg.in/cheggaaa/pb.v1"
|
|
|
|
"github.com/filecoin-project/go-jsonrpc"
|
|
|
|
"github.com/filecoin-project/lotus/chain/store"
|
|
lcli "github.com/filecoin-project/lotus/cli"
|
|
"github.com/filecoin-project/lotus/lib/backupds"
|
|
"github.com/filecoin-project/lotus/node/config"
|
|
"github.com/filecoin-project/lotus/node/repo"
|
|
)
|
|
|
|
var backupCmd = lcli.BackupCmd("repo", repo.FullNode, func(cctx *cli.Context) (lcli.BackupAPI, jsonrpc.ClientCloser, error) {
|
|
return lcli.GetFullNodeAPI(cctx)
|
|
})
|
|
|
|
func restore(cctx *cli.Context, r repo.Repo) error {
|
|
bf, err := homedir.Expand(cctx.Path("restore"))
|
|
if err != nil {
|
|
return xerrors.Errorf("expand backup file path: %w", err)
|
|
}
|
|
|
|
st, err := os.Stat(bf)
|
|
if err != nil {
|
|
return xerrors.Errorf("stat backup file (%s): %w", bf, err)
|
|
}
|
|
|
|
f, err := os.Open(bf)
|
|
if err != nil {
|
|
return xerrors.Errorf("opening backup file: %w", err)
|
|
}
|
|
defer f.Close() // nolint:errcheck
|
|
|
|
lr, err := r.Lock(repo.FullNode)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer lr.Close() // nolint:errcheck
|
|
|
|
if cctx.IsSet("restore-config") {
|
|
log.Info("Restoring config")
|
|
|
|
cf, err := homedir.Expand(cctx.String("restore-config"))
|
|
if err != nil {
|
|
return xerrors.Errorf("expanding config path: %w", err)
|
|
}
|
|
|
|
_, err = os.Stat(cf)
|
|
if err != nil {
|
|
return xerrors.Errorf("stat config file (%s): %w", cf, err)
|
|
}
|
|
|
|
var cerr error
|
|
err = lr.SetConfig(func(raw interface{}) {
|
|
rcfg, ok := raw.(*config.FullNode)
|
|
if !ok {
|
|
cerr = xerrors.New("expected miner config")
|
|
return
|
|
}
|
|
|
|
ff, err := config.FromFile(cf, rcfg)
|
|
if err != nil {
|
|
cerr = xerrors.Errorf("loading config: %w", err)
|
|
return
|
|
}
|
|
|
|
*rcfg = *ff.(*config.FullNode)
|
|
})
|
|
if cerr != nil {
|
|
return cerr
|
|
}
|
|
if err != nil {
|
|
return xerrors.Errorf("setting config: %w", err)
|
|
}
|
|
|
|
} else {
|
|
log.Warn("--restore-config NOT SET, WILL USE DEFAULT VALUES")
|
|
}
|
|
|
|
log.Info("Restoring metadata backup")
|
|
|
|
mds, err := lr.Datastore(context.TODO(), "/metadata")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
bar := pb.New64(st.Size())
|
|
br := bar.NewProxyReader(f)
|
|
bar.ShowTimeLeft = true
|
|
bar.ShowPercent = true
|
|
bar.ShowSpeed = true
|
|
bar.Units = pb.U_BYTES
|
|
|
|
bar.Start()
|
|
err = backupds.RestoreInto(br, mds)
|
|
bar.Finish()
|
|
|
|
if err != nil {
|
|
return xerrors.Errorf("restoring metadata: %w", err)
|
|
}
|
|
|
|
log.Info("Resetting chainstore metadata")
|
|
|
|
chainHead := dstore.NewKey("head")
|
|
if err := mds.Delete(chainHead); err != nil {
|
|
return xerrors.Errorf("clearing chain head: %w", err)
|
|
}
|
|
if err := store.FlushValidationCache(mds); err != nil {
|
|
return xerrors.Errorf("clearing chain validation cache: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|