-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4133 from filecoin-project/feat/backup
Miner backup/restore commands
- Loading branch information
Showing
22 changed files
with
1,174 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package cli | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
|
||
logging "github.com/ipfs/go-log/v2" | ||
"github.com/mitchellh/go-homedir" | ||
"github.com/urfave/cli/v2" | ||
"golang.org/x/xerrors" | ||
|
||
"github.com/filecoin-project/go-jsonrpc" | ||
|
||
"github.com/filecoin-project/lotus/lib/backupds" | ||
"github.com/filecoin-project/lotus/node/repo" | ||
) | ||
|
||
type BackupAPI interface { | ||
CreateBackup(ctx context.Context, fpath string) error | ||
} | ||
|
||
type BackupApiFn func(ctx *cli.Context) (BackupAPI, jsonrpc.ClientCloser, error) | ||
|
||
func BackupCmd(repoFlag string, rt repo.RepoType, getApi BackupApiFn) *cli.Command { | ||
var offlineBackup = func(cctx *cli.Context) error { | ||
logging.SetLogLevel("badger", "ERROR") // nolint:errcheck | ||
|
||
repoPath := cctx.String(repoFlag) | ||
r, err := repo.NewFS(repoPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ok, err := r.Exists() | ||
if err != nil { | ||
return err | ||
} | ||
if !ok { | ||
return xerrors.Errorf("repo at '%s' is not initialized", cctx.String(repoFlag)) | ||
} | ||
|
||
lr, err := r.LockRO(rt) | ||
if err != nil { | ||
return xerrors.Errorf("locking repo: %w", err) | ||
} | ||
defer lr.Close() // nolint:errcheck | ||
|
||
mds, err := lr.Datastore("/metadata") | ||
if err != nil { | ||
return xerrors.Errorf("getting metadata datastore: %w", err) | ||
} | ||
|
||
bds := backupds.Wrap(mds) | ||
|
||
fpath, err := homedir.Expand(cctx.Args().First()) | ||
if err != nil { | ||
return xerrors.Errorf("expanding file path: %w", err) | ||
} | ||
|
||
out, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0644) | ||
if err != nil { | ||
return xerrors.Errorf("opening backup file %s: %w", fpath, err) | ||
} | ||
|
||
if err := bds.Backup(out); err != nil { | ||
if cerr := out.Close(); cerr != nil { | ||
log.Errorw("error closing backup file while handling backup error", "closeErr", cerr, "backupErr", err) | ||
} | ||
return xerrors.Errorf("backup error: %w", err) | ||
} | ||
|
||
if err := out.Close(); err != nil { | ||
return xerrors.Errorf("closing backup file: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
var onlineBackup = func(cctx *cli.Context) error { | ||
api, closer, err := getApi(cctx) | ||
if err != nil { | ||
return xerrors.Errorf("getting api: %w (if the node isn't running you can use the --offline flag)", err) | ||
} | ||
defer closer() | ||
|
||
err = api.CreateBackup(ReqContext(cctx), cctx.Args().First()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Println("Success") | ||
|
||
return nil | ||
} | ||
|
||
return &cli.Command{ | ||
Name: "backup", | ||
Usage: "Create node metadata backup", | ||
Description: `The backup command writes a copy of node metadata under the specified path | ||
Online backups: | ||
For security reasons, the daemon must be have LOTUS_BACKUP_BASE_PATH env var set | ||
to a path where backup files are supposed to be saved, and the path specified in | ||
this command must be within this base path`, | ||
Flags: []cli.Flag{ | ||
&cli.BoolFlag{ | ||
Name: "offline", | ||
Usage: "create backup without the node running", | ||
}, | ||
}, | ||
ArgsUsage: "[backup file path]", | ||
Action: func(cctx *cli.Context) error { | ||
if cctx.Args().Len() != 1 { | ||
return xerrors.Errorf("expected 1 argument") | ||
} | ||
|
||
if cctx.Bool("offline") { | ||
return offlineBackup(cctx) | ||
} | ||
|
||
return onlineBackup(cctx) | ||
}, | ||
} | ||
} |
Oops, something went wrong.