diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 03537d820..280123707 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -198,7 +198,7 @@ var initCmd = &cli.Command{ } if err := ioutil.WriteFile(filepath.Join(lr.Path(), "sectorstore.json"), b, 0644); err != nil { - return xerrors.Errorf("persisting storage metadata (%s): %w", filepath.Join(lr.Path(), "storage.json"), err) + return xerrors.Errorf("persisting storage metadata (%s): %w", filepath.Join(lr.Path(), "sectorstore.json"), err) } } diff --git a/cmd/lotus-storage-miner/main.go b/cmd/lotus-storage-miner/main.go index 8399268ea..4549332e0 100644 --- a/cmd/lotus-storage-miner/main.go +++ b/cmd/lotus-storage-miner/main.go @@ -29,6 +29,7 @@ func main() { rewardsCmd, runCmd, sectorsCmd, + storageCmd, setPriceCmd, } jaeger := tracing.SetupJaegerTracing("lotus") diff --git a/cmd/lotus-storage-miner/storage.go b/cmd/lotus-storage-miner/storage.go new file mode 100644 index 000000000..22ea2c214 --- /dev/null +++ b/cmd/lotus-storage-miner/storage.go @@ -0,0 +1,99 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + + "github.com/google/uuid" + "github.com/mitchellh/go-homedir" + "golang.org/x/xerrors" + "gopkg.in/urfave/cli.v2" + + lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/lotus/node/config" +) + +const metaFile = "sectorstore.json" + +var storageCmd = &cli.Command{ + Name: "storage", + Usage: "manage sector storage", + Subcommands: []*cli.Command{ + storageAttachCmd, + }, +} + +var storageAttachCmd = &cli.Command{ + Name: "attach", + Usage: "attach local storage path", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "init", + Usage: "initialize the path first", + }, + &cli.Uint64Flag{ + Name: "weight", + Usage: "(for init) path weight", + Value: 10, + }, + &cli.BoolFlag{ + Name: "seal", + Usage: "(for init) use path for sealing", + }, + &cli.BoolFlag{ + Name: "store", + Usage: "(for init) use path for long-term storage", + }, + }, + Action: func(cctx *cli.Context) error { + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := lcli.ReqContext(cctx) + + if !cctx.Args().Present() { + return xerrors.Errorf("must specify storage path to attach") + } + + p, err := homedir.Expand(cctx.Args().First()) + if err != nil { + return xerrors.Errorf("expanding path: %w", err) + } + + if cctx.Bool("init") { + _, err := os.Stat(filepath.Join(p, metaFile)) + if !os.IsNotExist(err) { + if err == nil { + return xerrors.Errorf("path is already initialized") + } + return err + } + + cfg := &config.StorageMeta{ + ID: uuid.New().String(), + Weight: cctx.Uint64("weight"), + CanSeal: cctx.Bool("seal"), + CanStore: cctx.Bool("store"), + } + + if !(cfg.CanStore || cfg.CanSeal) { + return xerrors.Errorf("must specify at least one of --store of --seal") + } + + b, err := json.MarshalIndent(cfg, "", " ") + if err != nil { + return xerrors.Errorf("marshaling storage config: %w", err) + } + + if err := ioutil.WriteFile(filepath.Join(p, metaFile), b, 0644); err != nil { + return xerrors.Errorf("persisting storage metadata (%s): %w", filepath.Join(p, metaFile), err) + } + } + + return nodeApi.StorageAddLocal(ctx, p) + }, +}