Merge remote-tracking branch 'origin/master' into feat/partret-ux
This commit is contained in:
commit
135796d4fa
Binary file not shown.
@ -95,6 +95,14 @@ over time
|
|||||||
Name: "max-storage",
|
Name: "max-storage",
|
||||||
Usage: "(for init) limit storage space for sectors (expensive for very large paths!)",
|
Usage: "(for init) limit storage space for sectors (expensive for very large paths!)",
|
||||||
},
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "groups",
|
||||||
|
Usage: "path group names",
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "allow-to",
|
||||||
|
Usage: "path groups allowed to pull data from this path (allow all if not specified)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||||
@ -142,6 +150,8 @@ over time
|
|||||||
CanSeal: cctx.Bool("seal"),
|
CanSeal: cctx.Bool("seal"),
|
||||||
CanStore: cctx.Bool("store"),
|
CanStore: cctx.Bool("store"),
|
||||||
MaxStorage: uint64(maxStor),
|
MaxStorage: uint64(maxStor),
|
||||||
|
Groups: cctx.StringSlice("groups"),
|
||||||
|
AllowTo: cctx.StringSlice("allow-to"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(cfg.CanStore || cfg.CanSeal) {
|
if !(cfg.CanStore || cfg.CanSeal) {
|
||||||
@ -322,10 +332,17 @@ var storageListCmd = &cli.Command{
|
|||||||
if si.CanStore {
|
if si.CanStore {
|
||||||
fmt.Print(color.CyanString("Store"))
|
fmt.Print(color.CyanString("Store"))
|
||||||
}
|
}
|
||||||
fmt.Println("")
|
|
||||||
} else {
|
} else {
|
||||||
fmt.Print(color.HiYellowString("Use: ReadOnly"))
|
fmt.Print(color.HiYellowString("Use: ReadOnly"))
|
||||||
}
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
if len(si.Groups) > 0 {
|
||||||
|
fmt.Printf("\tGroups: %s\n", strings.Join(si.Groups, ", "))
|
||||||
|
}
|
||||||
|
if len(si.AllowTo) > 0 {
|
||||||
|
fmt.Printf("\tAllowTo: %s\n", strings.Join(si.AllowTo, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
if localPath, ok := local[s.ID]; ok {
|
if localPath, ok := local[s.ID]; ok {
|
||||||
fmt.Printf("\tLocal: %s\n", color.GreenString(localPath))
|
fmt.Printf("\tLocal: %s\n", color.GreenString(localPath))
|
||||||
|
@ -51,6 +51,14 @@ var storageAttachCmd = &cli.Command{
|
|||||||
Name: "max-storage",
|
Name: "max-storage",
|
||||||
Usage: "(for init) limit storage space for sectors (expensive for very large paths!)",
|
Usage: "(for init) limit storage space for sectors (expensive for very large paths!)",
|
||||||
},
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "groups",
|
||||||
|
Usage: "path group names",
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "allow-to",
|
||||||
|
Usage: "path groups allowed to pull data from this path (allow all if not specified)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
nodeApi, closer, err := lcli.GetWorkerAPI(cctx)
|
nodeApi, closer, err := lcli.GetWorkerAPI(cctx)
|
||||||
@ -98,6 +106,8 @@ var storageAttachCmd = &cli.Command{
|
|||||||
CanSeal: cctx.Bool("seal"),
|
CanSeal: cctx.Bool("seal"),
|
||||||
CanStore: cctx.Bool("store"),
|
CanStore: cctx.Bool("store"),
|
||||||
MaxStorage: uint64(maxStor),
|
MaxStorage: uint64(maxStor),
|
||||||
|
Groups: cctx.StringSlice("groups"),
|
||||||
|
AllowTo: cctx.StringSlice("allow-to"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(cfg.CanStore || cfg.CanSeal) {
|
if !(cfg.CanStore || cfg.CanSeal) {
|
||||||
|
222
cmd/lotus-shed/balancer.go
Normal file
222
cmd/lotus-shed/balancer.go
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
|
"github.com/filecoin-project/go-state-types/exitcode"
|
||||||
|
|
||||||
|
lapi "github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var balancerCmd = &cli.Command{
|
||||||
|
Name: "balancer",
|
||||||
|
Usage: "Utility for balancing tokens between multiple wallets",
|
||||||
|
Description: `Tokens are balanced based on the specification provided in arguments
|
||||||
|
|
||||||
|
Each argument specifies an address, role, and role parameters separated by ';'
|
||||||
|
|
||||||
|
Supported roles:
|
||||||
|
- request;[addr];[low];[high] - request tokens when balance drops to [low], topping up to [high]
|
||||||
|
- provide;[addr];[min] - provide tokens to other addresses as long as the balance is above [min]
|
||||||
|
`,
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, closer, err := lcli.GetFullNodeAPIV1(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer closer()
|
||||||
|
ctx := lcli.ReqContext(cctx)
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
addr address.Address
|
||||||
|
low, high abi.TokenAmount
|
||||||
|
}
|
||||||
|
type provide struct {
|
||||||
|
addr address.Address
|
||||||
|
min abi.TokenAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
var requests []request
|
||||||
|
var provides []provide
|
||||||
|
|
||||||
|
for i, s := range cctx.Args().Slice() {
|
||||||
|
ss := strings.Split(s, ";")
|
||||||
|
switch ss[0] {
|
||||||
|
case "request":
|
||||||
|
if len(ss) != 4 {
|
||||||
|
return xerrors.Errorf("request role needs 4 parameters (arg %d)", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := address.NewFromString(ss[1])
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("parsing address in arg %d: %w", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
low, err := types.ParseFIL(ss[2])
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("parsing low in arg %d: %w", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
high, err := types.ParseFIL(ss[3])
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("parsing high in arg %d: %w", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if abi.TokenAmount(low).GreaterThanEqual(abi.TokenAmount(high)) {
|
||||||
|
return xerrors.Errorf("low must be less than high in arg %d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
requests = append(requests, request{
|
||||||
|
addr: addr,
|
||||||
|
low: abi.TokenAmount(low),
|
||||||
|
high: abi.TokenAmount(high),
|
||||||
|
})
|
||||||
|
case "provide":
|
||||||
|
if len(ss) != 3 {
|
||||||
|
return xerrors.Errorf("provide role needs 3 parameters (arg %d)", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := address.NewFromString(ss[1])
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("parsing address in arg %d: %w", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
min, err := types.ParseFIL(ss[2])
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("parsing min in arg %d: %w", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
provides = append(provides, provide{
|
||||||
|
addr: addr,
|
||||||
|
min: abi.TokenAmount(min),
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return xerrors.Errorf("unknown role '%s' in arg %d", ss[0], i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(provides) == 0 {
|
||||||
|
return xerrors.Errorf("no provides specified")
|
||||||
|
}
|
||||||
|
if len(requests) == 0 {
|
||||||
|
return xerrors.Errorf("no requests specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
const confidence = 16
|
||||||
|
|
||||||
|
var notifs <-chan []*lapi.HeadChange
|
||||||
|
for {
|
||||||
|
if notifs == nil {
|
||||||
|
notifs, err = api.ChainNotify(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("chain notify error: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ts *types.TipSet
|
||||||
|
loop:
|
||||||
|
for {
|
||||||
|
time.Sleep(150 * time.Millisecond)
|
||||||
|
select {
|
||||||
|
case n := <-notifs:
|
||||||
|
for _, change := range n {
|
||||||
|
if change.Type != store.HCApply {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ts = change.Val
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type send struct {
|
||||||
|
to address.Address
|
||||||
|
amt abi.TokenAmount
|
||||||
|
filled bool
|
||||||
|
}
|
||||||
|
var toSend []*send
|
||||||
|
|
||||||
|
for _, req := range requests {
|
||||||
|
bal, err := api.StateGetActor(ctx, req.addr, ts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bal.Balance.LessThan(req.low) {
|
||||||
|
toSend = append(toSend, &send{
|
||||||
|
to: req.addr,
|
||||||
|
amt: big.Sub(req.high, bal.Balance),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range toSend {
|
||||||
|
fmt.Printf("REQUEST %s for %s\n", types.FIL(s.amt), s.to)
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgs []cid.Cid
|
||||||
|
|
||||||
|
for _, prov := range provides {
|
||||||
|
bal, err := api.StateGetActor(ctx, prov.addr, ts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
avail := big.Sub(bal.Balance, prov.min)
|
||||||
|
for _, s := range toSend {
|
||||||
|
if s.filled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if avail.LessThan(s.amt) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||||
|
From: prov.addr,
|
||||||
|
To: s.to,
|
||||||
|
Value: s.amt,
|
||||||
|
}, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("SEND ERROR %s\n", err.Error())
|
||||||
|
}
|
||||||
|
fmt.Printf("SEND %s; %s from %s TO %s\n", m.Cid(), types.FIL(s.amt), s.to, prov.addr)
|
||||||
|
|
||||||
|
msgs = append(msgs, m.Cid())
|
||||||
|
s.filled = true
|
||||||
|
avail = big.Sub(avail, s.amt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(msgs) > 0 {
|
||||||
|
fmt.Printf("WAITING FOR %d MESSAGES\n", len(msgs))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, msg := range msgs {
|
||||||
|
ml, err := api.StateWaitMsg(ctx, msg, confidence, lapi.LookbackNoLimit, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ml.Receipt.ExitCode != exitcode.Ok {
|
||||||
|
fmt.Printf("MSG %s NON-ZERO EXITCODE: %s\n", msg, ml.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
@ -64,6 +64,7 @@ func main() {
|
|||||||
splitstoreCmd,
|
splitstoreCmd,
|
||||||
fr32Cmd,
|
fr32Cmd,
|
||||||
chainCmd,
|
chainCmd,
|
||||||
|
balancerCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
app := &cli.App{
|
app := &cli.App{
|
||||||
|
@ -2148,7 +2148,9 @@ Inputs:
|
|||||||
"Weight": 42,
|
"Weight": 42,
|
||||||
"MaxStorage": 42,
|
"MaxStorage": 42,
|
||||||
"CanSeal": true,
|
"CanSeal": true,
|
||||||
"CanStore": true
|
"CanStore": true,
|
||||||
|
"Groups": null,
|
||||||
|
"AllowTo": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Capacity": 9,
|
"Capacity": 9,
|
||||||
@ -2258,7 +2260,9 @@ Response:
|
|||||||
"Weight": 42,
|
"Weight": 42,
|
||||||
"MaxStorage": 42,
|
"MaxStorage": 42,
|
||||||
"CanSeal": true,
|
"CanSeal": true,
|
||||||
"CanStore": true
|
"CanStore": true,
|
||||||
|
"Groups": null,
|
||||||
|
"AllowTo": null
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1983,6 +1983,8 @@ OPTIONS:
|
|||||||
--seal (for init) use path for sealing (default: false)
|
--seal (for init) use path for sealing (default: false)
|
||||||
--store (for init) use path for long-term storage (default: false)
|
--store (for init) use path for long-term storage (default: false)
|
||||||
--max-storage value (for init) limit storage space for sectors (expensive for very large paths!)
|
--max-storage value (for init) limit storage space for sectors (expensive for very large paths!)
|
||||||
|
--groups value path group names
|
||||||
|
--allow-to value path groups allowed to pull data from this path (allow all if not specified)
|
||||||
--help, -h show help (default: false)
|
--help, -h show help (default: false)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -94,6 +94,8 @@ OPTIONS:
|
|||||||
--seal (for init) use path for sealing (default: false)
|
--seal (for init) use path for sealing (default: false)
|
||||||
--store (for init) use path for long-term storage (default: false)
|
--store (for init) use path for long-term storage (default: false)
|
||||||
--max-storage value (for init) limit storage space for sectors (expensive for very large paths!)
|
--max-storage value (for init) limit storage space for sectors (expensive for very large paths!)
|
||||||
|
--groups value path group names
|
||||||
|
--allow-to value path groups allowed to pull data from this path (allow all if not specified)
|
||||||
--help, -h show help (default: false)
|
--help, -h show help (default: false)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1644,8 +1644,18 @@ OPTIONS:
|
|||||||
--help, -h show help (default: false)
|
--help, -h show help (default: false)
|
||||||
|
|
||||||
```
|
```
|
||||||
# nage
|
|
||||||
|
### lotus mpool manage
|
||||||
```
|
```
|
||||||
|
NAME:
|
||||||
|
lotus mpool manage -
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
lotus mpool manage [command options] [arguments...]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--help, -h show help (default: false)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## lotus state
|
## lotus state
|
||||||
|
33
extern/sector-storage/stores/index.go
vendored
33
extern/sector-storage/stores/index.go
vendored
@ -29,6 +29,8 @@ var SkippedHeartbeatThresh = HeartbeatInterval * 5
|
|||||||
// filesystem, local or networked / shared by multiple machines
|
// filesystem, local or networked / shared by multiple machines
|
||||||
type ID string
|
type ID string
|
||||||
|
|
||||||
|
type Group = string
|
||||||
|
|
||||||
type StorageInfo struct {
|
type StorageInfo struct {
|
||||||
ID ID
|
ID ID
|
||||||
URLs []string // TODO: Support non-http transports
|
URLs []string // TODO: Support non-http transports
|
||||||
@ -37,6 +39,9 @@ type StorageInfo struct {
|
|||||||
|
|
||||||
CanSeal bool
|
CanSeal bool
|
||||||
CanStore bool
|
CanStore bool
|
||||||
|
|
||||||
|
Groups []Group
|
||||||
|
AllowTo []Group
|
||||||
}
|
}
|
||||||
|
|
||||||
type HealthReport struct {
|
type HealthReport struct {
|
||||||
@ -168,6 +173,8 @@ func (i *Index) StorageAttach(ctx context.Context, si StorageInfo, st fsutil.FsS
|
|||||||
i.stores[si.ID].info.MaxStorage = si.MaxStorage
|
i.stores[si.ID].info.MaxStorage = si.MaxStorage
|
||||||
i.stores[si.ID].info.CanSeal = si.CanSeal
|
i.stores[si.ID].info.CanSeal = si.CanSeal
|
||||||
i.stores[si.ID].info.CanStore = si.CanStore
|
i.stores[si.ID].info.CanStore = si.CanStore
|
||||||
|
i.stores[si.ID].info.Groups = si.Groups
|
||||||
|
i.stores[si.ID].info.AllowTo = si.AllowTo
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -292,6 +299,8 @@ func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft storif
|
|||||||
storageIDs := map[ID]uint64{}
|
storageIDs := map[ID]uint64{}
|
||||||
isprimary := map[ID]bool{}
|
isprimary := map[ID]bool{}
|
||||||
|
|
||||||
|
allowTo := map[Group]struct{}{}
|
||||||
|
|
||||||
for _, pathType := range storiface.PathTypes {
|
for _, pathType := range storiface.PathTypes {
|
||||||
if ft&pathType == 0 {
|
if ft&pathType == 0 {
|
||||||
continue
|
continue
|
||||||
@ -323,6 +332,14 @@ func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft storif
|
|||||||
urls[k] = rl.String()
|
urls[k] = rl.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if allowTo != nil && len(st.info.AllowTo) > 0 {
|
||||||
|
for _, group := range st.info.AllowTo {
|
||||||
|
allowTo[group] = struct{}{}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allowTo = nil // allow to any
|
||||||
|
}
|
||||||
|
|
||||||
out = append(out, SectorStorageInfo{
|
out = append(out, SectorStorageInfo{
|
||||||
ID: id,
|
ID: id,
|
||||||
URLs: urls,
|
URLs: urls,
|
||||||
@ -365,6 +382,22 @@ func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft storif
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if allowTo != nil {
|
||||||
|
allow := false
|
||||||
|
for _, group := range st.info.Groups {
|
||||||
|
if _, found := allowTo[group]; found {
|
||||||
|
log.Debugf("path %s in allowed group %s", st.info.ID, group)
|
||||||
|
allow = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !allow {
|
||||||
|
log.Debugf("not selecting on %s, not in allowed group, allow %+v; path has %+v", st.info.ID, allowTo, st.info.Groups)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
urls := make([]string, len(st.info.URLs))
|
urls := make([]string, len(st.info.URLs))
|
||||||
for k, u := range st.info.URLs {
|
for k, u := range st.info.URLs {
|
||||||
rl, err := url.Parse(u)
|
rl, err := url.Parse(u)
|
||||||
|
154
extern/sector-storage/stores/index_test.go
vendored
Normal file
154
extern/sector-storage/stores/index_test.go
vendored
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package stores
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
logging "github.com/ipfs/go-log/v2"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||||
|
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logging.SetLogLevel("stores", "DEBUG")
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestStorage() StorageInfo {
|
||||||
|
return StorageInfo{
|
||||||
|
ID: ID(uuid.New().String()),
|
||||||
|
CanSeal: true,
|
||||||
|
CanStore: true,
|
||||||
|
Groups: nil,
|
||||||
|
AllowTo: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bigFsStat = fsutil.FsStat{
|
||||||
|
Capacity: 1 << 40,
|
||||||
|
Available: 1 << 40,
|
||||||
|
FSAvailable: 1 << 40,
|
||||||
|
Reserved: 0,
|
||||||
|
Max: 0,
|
||||||
|
Used: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
const s32g = 32 << 30
|
||||||
|
|
||||||
|
func TestFindSimple(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
i := NewIndex()
|
||||||
|
stor1 := newTestStorage()
|
||||||
|
stor2 := newTestStorage()
|
||||||
|
|
||||||
|
require.NoError(t, i.StorageAttach(ctx, stor1, bigFsStat))
|
||||||
|
require.NoError(t, i.StorageAttach(ctx, stor2, bigFsStat))
|
||||||
|
|
||||||
|
s1 := abi.SectorID{
|
||||||
|
Miner: 12,
|
||||||
|
Number: 34,
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
si, err := i.StorageFindSector(ctx, s1, storiface.FTSealed, s32g, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, si, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(t, i.StorageDeclareSector(ctx, stor1.ID, s1, storiface.FTSealed, true))
|
||||||
|
|
||||||
|
{
|
||||||
|
si, err := i.StorageFindSector(ctx, s1, storiface.FTSealed, s32g, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, si, 1)
|
||||||
|
require.Equal(t, stor1.ID, si[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
si, err := i.StorageFindSector(ctx, s1, storiface.FTSealed, s32g, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, si, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindNoAllow(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
i := NewIndex()
|
||||||
|
stor1 := newTestStorage()
|
||||||
|
stor1.AllowTo = []Group{"grp1"}
|
||||||
|
stor2 := newTestStorage()
|
||||||
|
|
||||||
|
require.NoError(t, i.StorageAttach(ctx, stor1, bigFsStat))
|
||||||
|
require.NoError(t, i.StorageAttach(ctx, stor2, bigFsStat))
|
||||||
|
|
||||||
|
s1 := abi.SectorID{
|
||||||
|
Miner: 12,
|
||||||
|
Number: 34,
|
||||||
|
}
|
||||||
|
require.NoError(t, i.StorageDeclareSector(ctx, stor1.ID, s1, storiface.FTSealed, true))
|
||||||
|
|
||||||
|
{
|
||||||
|
si, err := i.StorageFindSector(ctx, s1, storiface.FTSealed, s32g, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, si, 1)
|
||||||
|
require.Equal(t, stor1.ID, si[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
si, err := i.StorageFindSector(ctx, s1, storiface.FTSealed, s32g, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, si, 1)
|
||||||
|
require.Equal(t, stor1.ID, si[0].ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAllow(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
i := NewIndex()
|
||||||
|
|
||||||
|
stor1 := newTestStorage()
|
||||||
|
stor1.AllowTo = []Group{"grp1"}
|
||||||
|
|
||||||
|
stor2 := newTestStorage()
|
||||||
|
stor2.Groups = []Group{"grp1"}
|
||||||
|
|
||||||
|
stor3 := newTestStorage()
|
||||||
|
stor3.Groups = []Group{"grp2"}
|
||||||
|
|
||||||
|
require.NoError(t, i.StorageAttach(ctx, stor1, bigFsStat))
|
||||||
|
require.NoError(t, i.StorageAttach(ctx, stor2, bigFsStat))
|
||||||
|
require.NoError(t, i.StorageAttach(ctx, stor3, bigFsStat))
|
||||||
|
|
||||||
|
s1 := abi.SectorID{
|
||||||
|
Miner: 12,
|
||||||
|
Number: 34,
|
||||||
|
}
|
||||||
|
require.NoError(t, i.StorageDeclareSector(ctx, stor1.ID, s1, storiface.FTSealed, true))
|
||||||
|
|
||||||
|
{
|
||||||
|
si, err := i.StorageFindSector(ctx, s1, storiface.FTSealed, s32g, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, si, 1)
|
||||||
|
require.Equal(t, stor1.ID, si[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
si, err := i.StorageFindSector(ctx, s1, storiface.FTSealed, s32g, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, si, 2)
|
||||||
|
if si[0].ID == stor1.ID {
|
||||||
|
require.Equal(t, stor1.ID, si[0].ID)
|
||||||
|
require.Equal(t, stor2.ID, si[1].ID)
|
||||||
|
} else {
|
||||||
|
require.Equal(t, stor1.ID, si[1].ID)
|
||||||
|
require.Equal(t, stor2.ID, si[0].ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
extern/sector-storage/stores/local.go
vendored
11
extern/sector-storage/stores/local.go
vendored
@ -46,6 +46,13 @@ type LocalStorageMeta struct {
|
|||||||
// MaxStorage specifies the maximum number of bytes to use for sector storage
|
// MaxStorage specifies the maximum number of bytes to use for sector storage
|
||||||
// (0 = unlimited)
|
// (0 = unlimited)
|
||||||
MaxStorage uint64
|
MaxStorage uint64
|
||||||
|
|
||||||
|
// List of storage groups this path belongs to
|
||||||
|
Groups []string
|
||||||
|
|
||||||
|
// List of storage groups to which data from this path can be moved. If none
|
||||||
|
// are specified, allow to all
|
||||||
|
AllowTo []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorageConfig .lotusstorage/storage.json
|
// StorageConfig .lotusstorage/storage.json
|
||||||
@ -212,6 +219,8 @@ func (st *Local) OpenPath(ctx context.Context, p string) error {
|
|||||||
MaxStorage: meta.MaxStorage,
|
MaxStorage: meta.MaxStorage,
|
||||||
CanSeal: meta.CanSeal,
|
CanSeal: meta.CanSeal,
|
||||||
CanStore: meta.CanStore,
|
CanStore: meta.CanStore,
|
||||||
|
Groups: meta.Groups,
|
||||||
|
AllowTo: meta.AllowTo,
|
||||||
}, fst)
|
}, fst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("declaring storage in index: %w", err)
|
return xerrors.Errorf("declaring storage in index: %w", err)
|
||||||
@ -276,6 +285,8 @@ func (st *Local) Redeclare(ctx context.Context) error {
|
|||||||
MaxStorage: meta.MaxStorage,
|
MaxStorage: meta.MaxStorage,
|
||||||
CanSeal: meta.CanSeal,
|
CanSeal: meta.CanSeal,
|
||||||
CanStore: meta.CanStore,
|
CanStore: meta.CanStore,
|
||||||
|
Groups: meta.Groups,
|
||||||
|
AllowTo: meta.AllowTo,
|
||||||
}, fst)
|
}, fst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("redeclaring storage in index: %w", err)
|
return xerrors.Errorf("redeclaring storage in index: %w", err)
|
||||||
|
1
extern/sector-storage/stores/remote.go
vendored
1
extern/sector-storage/stores/remote.go
vendored
@ -305,7 +305,6 @@ func (r *Remote) checkAllocated(ctx context.Context, url string, spt abi.Registe
|
|||||||
return false, xerrors.Errorf("request: %w", err)
|
return false, xerrors.Errorf("request: %w", err)
|
||||||
}
|
}
|
||||||
req.Header = r.auth.Clone()
|
req.Header = r.auth.Clone()
|
||||||
fmt.Printf("req using header: %#v \n", r.auth)
|
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
66
lotuspond/front/package-lock.json
generated
66
lotuspond/front/package-lock.json
generated
@ -3569,9 +3569,9 @@
|
|||||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||||
},
|
},
|
||||||
"color-string": {
|
"color-string": {
|
||||||
"version": "1.5.3",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz",
|
||||||
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
|
"integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"color-name": "^1.0.0",
|
"color-name": "^1.0.0",
|
||||||
"simple-swizzle": "^0.2.2"
|
"simple-swizzle": "^0.2.2"
|
||||||
@ -7814,9 +7814,9 @@
|
|||||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
|
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
|
||||||
},
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz",
|
||||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
"integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
@ -9194,9 +9194,9 @@
|
|||||||
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
|
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
|
||||||
},
|
},
|
||||||
"path-parse": {
|
"path-parse": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||||
},
|
},
|
||||||
"path-to-regexp": {
|
"path-to-regexp": {
|
||||||
"version": "0.1.7",
|
"version": "0.1.7",
|
||||||
@ -9228,6 +9228,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||||
},
|
},
|
||||||
|
"picocolors": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
|
||||||
|
},
|
||||||
"pify": {
|
"pify": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
@ -9354,27 +9359,18 @@
|
|||||||
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
|
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.17",
|
"version": "7.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
|
||||||
"integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
|
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"picocolors": "^0.2.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1"
|
||||||
"supports-color": "^6.1.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -11057,9 +11053,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz",
|
||||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
"integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
@ -12203,9 +12199,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tmpl": {
|
"tmpl": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE="
|
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="
|
||||||
},
|
},
|
||||||
"to-arraybuffer": {
|
"to-arraybuffer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -12523,9 +12519,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"url-parse": {
|
"url-parse": {
|
||||||
"version": "1.4.7",
|
"version": "1.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
|
||||||
"integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
|
"integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"querystringify": "^2.1.1",
|
"querystringify": "^2.1.1",
|
||||||
"requires-port": "^1.0.0"
|
"requires-port": "^1.0.0"
|
||||||
@ -13164,9 +13160,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
||||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,10 @@ def generate_lotus_cli(prog):
|
|||||||
if cmd_flag is True and line == '':
|
if cmd_flag is True and line == '':
|
||||||
cmd_flag = False
|
cmd_flag = False
|
||||||
if cmd_flag is True and line[-1] != ':' and 'help, h' not in line:
|
if cmd_flag is True and line[-1] != ':' and 'help, h' not in line:
|
||||||
gap_pos = 0
|
gap_pos = None
|
||||||
sub_cmd = line
|
sub_cmd = line
|
||||||
if ' ' in line:
|
if ' ' in line:
|
||||||
gap_pos = sub_cmd.index(' ')
|
gap_pos = sub_cmd.index(' ')
|
||||||
if gap_pos:
|
|
||||||
sub_cmd = cur_cmd + ' ' + sub_cmd[:gap_pos]
|
sub_cmd = cur_cmd + ' ' + sub_cmd[:gap_pos]
|
||||||
get_cmd_recursively(sub_cmd)
|
get_cmd_recursively(sub_cmd)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
Loading…
Reference in New Issue
Block a user