storageminer: Improve CLI UX
This commit is contained in:
parent
b535a801bc
commit
d9acd484c0
@ -98,6 +98,16 @@ func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address
|
|||||||
return api.MinerSectors{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
return api.MinerSectors{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notProving, err := abi.BitFieldUnion(mas.Faults, mas.Recoveries)
|
||||||
|
if err != nil {
|
||||||
|
return api.MinerSectors{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
npc, err := notProving.Count()
|
||||||
|
if err != nil {
|
||||||
|
return api.MinerSectors{}, err
|
||||||
|
}
|
||||||
|
|
||||||
blks := cbor.NewCborStore(sm.ChainStore().Blockstore())
|
blks := cbor.NewCborStore(sm.ChainStore().Blockstore())
|
||||||
ss, err := amt.LoadAMT(ctx, blks, mas.Sectors)
|
ss, err := amt.LoadAMT(ctx, blks, mas.Sectors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -106,6 +116,7 @@ func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address
|
|||||||
|
|
||||||
return api.MinerSectors{
|
return api.MinerSectors{
|
||||||
Sset: ss.Count,
|
Sset: ss.Count,
|
||||||
|
Pset: ss.Count - npc,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,18 +79,18 @@ func SizeStr(bi BigInt) string {
|
|||||||
return fmt.Sprintf("%.3g %s", f, byteSizeUnits[i])
|
return fmt.Sprintf("%.3g %s", f, byteSizeUnits[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
var decUnits = []string{"", "K", "M", "G", "T", "P", "E", "Z"}
|
var deciUnits = []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"}
|
||||||
|
|
||||||
func DecStr(bi BigInt) string {
|
func DeciStr(bi BigInt) string {
|
||||||
r := new(big.Rat).SetInt(bi.Int)
|
r := new(big.Rat).SetInt(bi.Int)
|
||||||
den := big.NewRat(1, 1000)
|
den := big.NewRat(1, 1024)
|
||||||
|
|
||||||
var i int
|
var i int
|
||||||
for f, _ := r.Float64(); f >= 1000 && i+1 < len(decUnits); f, _ = r.Float64() {
|
for f, _ := r.Float64(); f >= 1024 && i+1 < len(deciUnits); f, _ = r.Float64() {
|
||||||
i++
|
i++
|
||||||
r = r.Mul(r, den)
|
r = r.Mul(r, den)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, _ := r.Float64()
|
f, _ := r.Float64()
|
||||||
return fmt.Sprintf("%.3g %s", f, decUnits[i])
|
return fmt.Sprintf("%.3g %s", f, deciUnits[i])
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/xerrors"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
"gopkg.in/urfave/cli.v2"
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||||
@ -19,7 +21,12 @@ import (
|
|||||||
var infoCmd = &cli.Command{
|
var infoCmd = &cli.Command{
|
||||||
Name: "info",
|
Name: "info",
|
||||||
Usage: "Print storage miner info",
|
Usage: "Print storage miner info",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{Name: "color"},
|
||||||
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
|
color.NoColor = !cctx.Bool("color")
|
||||||
|
|
||||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -54,7 +61,7 @@ var infoCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Miner: %s\n", maddr)
|
fmt.Printf("Miner: %s\n", color.BlueString("%s", maddr))
|
||||||
|
|
||||||
// Sector size
|
// Sector size
|
||||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||||
@ -71,8 +78,17 @@ var infoCmd = &cli.Command{
|
|||||||
|
|
||||||
rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower)
|
rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower)
|
||||||
qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower)
|
qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower)
|
||||||
fmt.Printf("Byte Power: %s / %s (%0.4f%%)\n", types.SizeStr(pow.MinerPower.RawBytePower), types.SizeStr(pow.TotalPower.RawBytePower), float64(rpercI.Int64())/10000)
|
|
||||||
fmt.Printf("Actual Power: %s / %s (%0.4f%%)\n", types.DecStr(pow.MinerPower.QualityAdjPower), types.DecStr(pow.TotalPower.QualityAdjPower), float64(qpercI.Int64())/10000)
|
fmt.Printf("Byte Power: %s / %s (%0.4f%%)\n",
|
||||||
|
color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)),
|
||||||
|
types.SizeStr(pow.TotalPower.RawBytePower),
|
||||||
|
float64(rpercI.Int64())/10000)
|
||||||
|
|
||||||
|
fmt.Printf("Actual Power: %s / %s (%0.4f%%)\n",
|
||||||
|
color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)),
|
||||||
|
types.DeciStr(pow.TotalPower.QualityAdjPower),
|
||||||
|
float64(qpercI.Int64())/10000)
|
||||||
|
|
||||||
secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
|
secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -92,15 +108,17 @@ var infoCmd = &cli.Command{
|
|||||||
float64(10000*uint64(len(faults))/secCounts.Pset)/100.)
|
float64(10000*uint64(len(faults))/secCounts.Pset)/100.)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Miner Balance: %s\n", types.FIL(mact.Balance))
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance)))
|
||||||
fmt.Printf("\tPreCommit: %s\n", types.FIL(mas.PreCommitDeposits))
|
fmt.Printf("\tPreCommit: %s\n", types.FIL(mas.PreCommitDeposits))
|
||||||
fmt.Printf("\tLocked: %s\n", types.FIL(mas.LockedFunds))
|
fmt.Printf("\tLocked: %s\n", types.FIL(mas.LockedFunds))
|
||||||
fmt.Printf("\tAvailable: %s\n", types.FIL(types.BigSub(mact.Balance, types.BigAdd(mas.LockedFunds, mas.PreCommitDeposits))))
|
color.Green("\tAvailable: %s", types.FIL(types.BigSub(mact.Balance, types.BigAdd(mas.LockedFunds, mas.PreCommitDeposits))))
|
||||||
wb, err := api.WalletBalance(ctx, mi.Worker)
|
wb, err := api.WalletBalance(ctx, mi.Worker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("getting worker balance: %w", err)
|
return xerrors.Errorf("getting worker balance: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Worker Balance: %s\n", types.FIL(wb))
|
color.Cyan("Worker Balance: %s", types.FIL(wb))
|
||||||
|
|
||||||
mb, err := api.StateMarketBalance(ctx, maddr, types.EmptyTSK)
|
mb, err := api.StateMarketBalance(ctx, maddr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -109,53 +127,14 @@ var infoCmd = &cli.Command{
|
|||||||
fmt.Printf("Market (Escrow): %s\n", types.FIL(mb.Escrow))
|
fmt.Printf("Market (Escrow): %s\n", types.FIL(mb.Escrow))
|
||||||
fmt.Printf("Market (Locked): %s\n", types.FIL(mb.Locked))
|
fmt.Printf("Market (Locked): %s\n", types.FIL(mb.Locked))
|
||||||
|
|
||||||
/*// TODO: indicate whether the post worker is in use
|
fmt.Println()
|
||||||
wstat, err := nodeApi.WorkerStats(ctx)
|
|
||||||
|
fmt.Println("Sectors:")
|
||||||
|
err = sectorsInfo(ctx, nodeApi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Worker use:\n")
|
|
||||||
fmt.Printf("\tLocal: %d / %d (+%d reserved)\n", wstat.LocalTotal-wstat.LocalReserved-wstat.LocalFree, wstat.LocalTotal-wstat.LocalReserved, wstat.LocalReserved)
|
|
||||||
fmt.Printf("\tRemote: %d / %d\n", wstat.RemotesTotal-wstat.RemotesFree, wstat.RemotesTotal)
|
|
||||||
|
|
||||||
fmt.Printf("Queues:\n")
|
|
||||||
fmt.Printf("\tAddPiece: %d\n", wstat.AddPieceWait)
|
|
||||||
fmt.Printf("\tPreCommit: %d\n", wstat.PreCommitWait)
|
|
||||||
fmt.Printf("\tCommit: %d\n", wstat.CommitWait)
|
|
||||||
fmt.Printf("\tUnseal: %d\n", wstat.UnsealWait)*/
|
|
||||||
|
|
||||||
/*ps, err := api.StateMinerPostState(ctx, maddr, types.EmptyTSK)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if ps.ProvingPeriodStart != 0 {
|
|
||||||
head, err := api.ChainHead(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fallback := ps.ProvingPeriodStart - head.Height()
|
|
||||||
fallbackS := fallback * build.BlockDelay
|
|
||||||
|
|
||||||
next := fallback + power.WindowedPostChallengeDuration
|
|
||||||
nextS := next * build.BlockDelay
|
|
||||||
|
|
||||||
fmt.Printf("PoSt Submissions:\n")
|
|
||||||
fmt.Printf("\tFallback: Epoch %d (in %d blocks, ~%dm %ds)\n", ps.ProvingPeriodStart, fallback, fallbackS/60, fallbackS%60)
|
|
||||||
fmt.Printf("\tDeadline: Epoch %d (in %d blocks, ~%dm %ds)\n", ps.ProvingPeriodStart+build.SlashablePowerDelay, next, nextS/60, nextS%60)
|
|
||||||
fmt.Printf("\tConsecutive Failures: %d\n", ps.NumConsecutiveFailures)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Proving Period: Not Proving\n")
|
|
||||||
}*/
|
|
||||||
|
|
||||||
sinfo, err := sectorsInfo(ctx, nodeApi)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Sectors: ", sinfo)
|
|
||||||
|
|
||||||
// TODO: grab actr state / info
|
// TODO: grab actr state / info
|
||||||
// * Sealed sectors (count / bytes)
|
// * Sealed sectors (count / bytes)
|
||||||
// * Power
|
// * Power
|
||||||
@ -163,23 +142,78 @@ var infoCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func sectorsInfo(ctx context.Context, napi api.StorageMiner) (map[sealing.SectorState]int, error) {
|
type stateMeta struct{
|
||||||
|
i int
|
||||||
|
col color.Attribute
|
||||||
|
state sealing.SectorState
|
||||||
|
}
|
||||||
|
|
||||||
|
var stateOrder = map[sealing.SectorState]stateMeta{}
|
||||||
|
var stateList = []stateMeta{
|
||||||
|
{col: 39, state: "Total"},
|
||||||
|
{col: color.FgGreen, state: sealing.Proving},
|
||||||
|
|
||||||
|
{col: color.FgRed, state: sealing.UndefinedSectorState},
|
||||||
|
{col: color.FgYellow, state: sealing.Empty},
|
||||||
|
{col: color.FgYellow, state: sealing.Packing},
|
||||||
|
{col: color.FgYellow, state: sealing.PreCommit1},
|
||||||
|
{col: color.FgYellow, state: sealing.PreCommit2},
|
||||||
|
{col: color.FgYellow, state: sealing.PreCommitting},
|
||||||
|
{col: color.FgYellow, state: sealing.WaitSeed},
|
||||||
|
{col: color.FgYellow, state: sealing.Committing},
|
||||||
|
{col: color.FgYellow, state: sealing.CommitWait},
|
||||||
|
{col: color.FgYellow, state: sealing.FinalizeSector},
|
||||||
|
|
||||||
|
{col: color.FgRed, state: sealing.FailedUnrecoverable},
|
||||||
|
{col: color.FgRed, state: sealing.SealFailed},
|
||||||
|
{col: color.FgRed, state: sealing.PreCommitFailed},
|
||||||
|
{col: color.FgRed, state: sealing.ComputeProofFailed},
|
||||||
|
{col: color.FgRed, state: sealing.CommitFailed},
|
||||||
|
{col: color.FgRed, state: sealing.PackingFailed},
|
||||||
|
{col: color.FgRed, state: sealing.Faulty},
|
||||||
|
{col: color.FgRed, state: sealing.FaultReported},
|
||||||
|
{col: color.FgRed, state: sealing.FaultedFinal},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for i, state := range stateList {
|
||||||
|
stateOrder[state.state] = stateMeta{
|
||||||
|
i: i,
|
||||||
|
col: state.col,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sectorsInfo(ctx context.Context, napi api.StorageMiner) error {
|
||||||
sectors, err := napi.SectorsList(ctx)
|
sectors, err := napi.SectorsList(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
out := map[sealing.SectorState]int{
|
buckets := map[sealing.SectorState]int{
|
||||||
"Total": len(sectors),
|
"Total": len(sectors),
|
||||||
}
|
}
|
||||||
for _, s := range sectors {
|
for _, s := range sectors {
|
||||||
st, err := napi.SectorsStatus(ctx, s)
|
st, err := napi.SectorsStatus(ctx, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
out[sealing.SectorState(st.State)]++
|
buckets[sealing.SectorState(st.State)]++
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
var sorted []stateMeta
|
||||||
|
for state, i := range buckets {
|
||||||
|
sorted = append(sorted, stateMeta{i: i, state: state})
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(sorted, func(i, j int) bool {
|
||||||
|
return stateOrder[sorted[i].state].i < stateOrder[sorted[j].state].i
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, s := range sorted {
|
||||||
|
_, _ = color.New(stateOrder[s.state].col).Printf("\t%s: %d\n", s.state, s.i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
@ -117,7 +119,12 @@ var storageAttachCmd = &cli.Command{
|
|||||||
var storageListCmd = &cli.Command{
|
var storageListCmd = &cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "list local storage paths",
|
Usage: "list local storage paths",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{Name: "color"},
|
||||||
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
|
color.NoColor = !cctx.Bool("color")
|
||||||
|
|
||||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -138,15 +145,25 @@ var storageListCmd = &cli.Command{
|
|||||||
sorted := make([]struct {
|
sorted := make([]struct {
|
||||||
stores.ID
|
stores.ID
|
||||||
sectors []stores.Decl
|
sectors []stores.Decl
|
||||||
|
stat stores.FsStat
|
||||||
}, 0, len(st))
|
}, 0, len(st))
|
||||||
for id, decls := range st {
|
for id, decls := range st {
|
||||||
|
st, err := nodeApi.StorageStat(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
sorted = append(sorted, struct {
|
sorted = append(sorted, struct {
|
||||||
stores.ID
|
stores.ID
|
||||||
sectors []stores.Decl
|
sectors []stores.Decl
|
||||||
}{id, decls})
|
stat stores.FsStat
|
||||||
|
}{id, decls, st})
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(sorted, func(i, j int) bool {
|
sort.Slice(sorted, func(i, j int) bool {
|
||||||
|
if sorted[i].stat.Capacity != sorted[j].stat.Capacity {
|
||||||
|
return sorted[i].stat.Capacity > sorted[j].stat.Capacity
|
||||||
|
}
|
||||||
return sorted[i].ID < sorted[j].ID
|
return sorted[i].ID < sorted[j].ID
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -168,13 +185,29 @@ var storageListCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
ping := time.Now().Sub(pingStart)
|
ping := time.Now().Sub(pingStart)
|
||||||
|
|
||||||
|
usedPercent := (st.Capacity-st.Available)*100/st.Capacity
|
||||||
|
|
||||||
|
percCol := color.FgGreen
|
||||||
|
switch {
|
||||||
|
case usedPercent > 98:
|
||||||
|
percCol = color.FgRed
|
||||||
|
case usedPercent > 90:
|
||||||
|
percCol = color.FgYellow
|
||||||
|
}
|
||||||
|
|
||||||
|
var barCols = uint64(50)
|
||||||
|
set := (st.Capacity-st.Available)*barCols/st.Capacity
|
||||||
|
bar := strings.Repeat("|", int(set)) + strings.Repeat(" ", int(barCols-set))
|
||||||
|
|
||||||
fmt.Printf("%s:\n", s.ID)
|
fmt.Printf("%s:\n", s.ID)
|
||||||
fmt.Printf("\tUnsealed: %d; Sealed: %d; Caches: %d\n", cnt[0], cnt[1], cnt[2])
|
fmt.Printf("\t[%s] %s/%s %s\n", color.New(percCol).Sprint(bar),
|
||||||
fmt.Printf("\tSpace Used: %s/%s %d%% (%s avail)\n",
|
|
||||||
types.SizeStr(types.NewInt(st.Capacity-st.Available)),
|
types.SizeStr(types.NewInt(st.Capacity-st.Available)),
|
||||||
types.SizeStr(types.NewInt(st.Capacity)),
|
types.SizeStr(types.NewInt(st.Capacity)),
|
||||||
(st.Capacity-st.Available)*100/st.Capacity,
|
color.New(percCol).Sprintf("%d%%", usedPercent))
|
||||||
types.SizeStr(types.NewInt(st.Available)))
|
fmt.Printf("\t%s; %s; %s\n",
|
||||||
|
color.YellowString("Unsealed: %d", cnt[0]),
|
||||||
|
color.GreenString("Sealed: %d", cnt[1]),
|
||||||
|
color.BlueString("Caches: %d", cnt[2]))
|
||||||
|
|
||||||
si, err := nodeApi.StorageInfo(ctx, s.ID)
|
si, err := nodeApi.StorageInfo(ctx, s.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -185,18 +218,18 @@ var storageListCmd = &cli.Command{
|
|||||||
if si.CanSeal || si.CanStore {
|
if si.CanSeal || si.CanStore {
|
||||||
fmt.Printf("Weight: %d; Use: ", si.Weight)
|
fmt.Printf("Weight: %d; Use: ", si.Weight)
|
||||||
if si.CanSeal {
|
if si.CanSeal {
|
||||||
fmt.Print("Seal ")
|
fmt.Print(color.MagentaString("Seal "))
|
||||||
}
|
}
|
||||||
if si.CanStore {
|
if si.CanStore {
|
||||||
fmt.Print("Store")
|
fmt.Print(color.CyanString("Store"))
|
||||||
}
|
}
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Use: ReadOnly")
|
fmt.Print(color.HiYellowString("Use: ReadOnly"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if localPath, ok := local[s.ID]; ok {
|
if localPath, ok := local[s.ID]; ok {
|
||||||
fmt.Printf("\tLocal: %s\n", localPath)
|
fmt.Printf("\tLocal: %s\n", color.GreenString(localPath))
|
||||||
}
|
}
|
||||||
for i, l := range si.URLs {
|
for i, l := range si.URLs {
|
||||||
var rtt string
|
var rtt string
|
||||||
@ -206,6 +239,7 @@ var storageListCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Printf("\tURL: %s%s\n", l, rtt) // TODO; try pinging maybe?? print latency?
|
fmt.Printf("\tURL: %s%s\n", l, rtt) // TODO; try pinging maybe?? print latency?
|
||||||
}
|
}
|
||||||
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -2,11 +2,15 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/sector-storage/storiface"
|
|
||||||
"gopkg.in/urfave/cli.v2"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/sector-storage/storiface"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
lcli "github.com/filecoin-project/lotus/cli"
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,7 +25,12 @@ var workersCmd = &cli.Command{
|
|||||||
var workersListCmd = &cli.Command{
|
var workersListCmd = &cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "list workers",
|
Usage: "list workers",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{Name: "color"},
|
||||||
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
|
color.NoColor = !cctx.Bool("color")
|
||||||
|
|
||||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -51,30 +60,48 @@ var workersListCmd = &cli.Command{
|
|||||||
|
|
||||||
for _, stat := range st {
|
for _, stat := range st {
|
||||||
gpuUse := "not "
|
gpuUse := "not "
|
||||||
|
gpuCol := color.FgBlue
|
||||||
if stat.GpuUsed {
|
if stat.GpuUsed {
|
||||||
|
gpuCol = color.FgGreen
|
||||||
gpuUse = ""
|
gpuUse = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Worker %d, host %s\n", stat.id, stat.Info.Hostname)
|
|
||||||
|
|
||||||
fmt.Printf("\tCPU: %d core(s) in use\n", stat.CpuUse)
|
fmt.Printf("Worker %d, host %s\n", stat.id, color.MagentaString(stat.Info.Hostname))
|
||||||
|
|
||||||
|
var barCols = uint64(64)
|
||||||
|
cpuBars := int(stat.CpuUse * barCols / stat.Info.Resources.CPUs)
|
||||||
|
cpuBar := strings.Repeat("|", cpuBars) + strings.Repeat(" ", int(barCols) - cpuBars)
|
||||||
|
|
||||||
|
fmt.Printf("\tCPU: [%s] %d core(s) in use\n", color.GreenString(cpuBar), stat.CpuUse)
|
||||||
|
|
||||||
|
ramBarsRes := int(stat.Info.Resources.MemReserved*barCols/stat.Info.Resources.MemPhysical)
|
||||||
|
ramBarsUsed := int(stat.MemUsedMin*barCols/stat.Info.Resources.MemPhysical)
|
||||||
|
ramBar := color.YellowString(strings.Repeat("|", ramBarsRes)) +
|
||||||
|
color.GreenString(strings.Repeat("|", ramBarsUsed)) +
|
||||||
|
strings.Repeat(" ", int(barCols) - ramBarsUsed - ramBarsRes)
|
||||||
|
|
||||||
|
vmem := stat.Info.Resources.MemPhysical+stat.Info.Resources.MemSwap
|
||||||
|
|
||||||
|
vmemBarsRes := int(stat.Info.Resources.MemReserved*barCols/vmem)
|
||||||
|
vmemBarsUsed := int(stat.MemUsedMax*barCols/vmem)
|
||||||
|
vmemBar := color.YellowString(strings.Repeat("|", vmemBarsRes)) +
|
||||||
|
color.GreenString(strings.Repeat("|", vmemBarsUsed)) +
|
||||||
|
strings.Repeat(" ", int(barCols) - vmemBarsUsed - vmemBarsRes)
|
||||||
|
|
||||||
|
fmt.Printf("\tRAM: [%s] %d%% %s/%s\n", ramBar,
|
||||||
|
(stat.Info.Resources.MemReserved + stat.MemUsedMin)*100/stat.Info.Resources.MemPhysical,
|
||||||
|
types.SizeStr(types.NewInt(stat.Info.Resources.MemReserved + stat.MemUsedMin)),
|
||||||
|
types.SizeStr(types.NewInt(stat.Info.Resources.MemPhysical)))
|
||||||
|
|
||||||
|
fmt.Printf("\tVMEM: [%s] %d%% %s/%s\n", vmemBar,
|
||||||
|
(stat.Info.Resources.MemReserved + stat.MemUsedMax)*100/vmem,
|
||||||
|
types.SizeStr(types.NewInt(stat.Info.Resources.MemReserved + stat.MemUsedMax)),
|
||||||
|
types.SizeStr(types.NewInt(vmem)))
|
||||||
|
|
||||||
for _, gpu := range stat.Info.Resources.GPUs {
|
for _, gpu := range stat.Info.Resources.GPUs {
|
||||||
fmt.Printf("\tGPU: %s, %sused\n", gpu, gpuUse)
|
fmt.Printf("\tGPU: %s\n", color.New(gpuCol).Sprintf("%s, %sused", gpu, gpuUse))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\tMemory: System: Physical %s, Swap %s, Reserved %s (%d%% phys)\n",
|
|
||||||
types.SizeStr(types.NewInt(stat.Info.Resources.MemPhysical)),
|
|
||||||
types.SizeStr(types.NewInt(stat.Info.Resources.MemSwap)),
|
|
||||||
types.SizeStr(types.NewInt(stat.Info.Resources.MemReserved)),
|
|
||||||
stat.Info.Resources.MemReserved*100/stat.Info.Resources.MemPhysical)
|
|
||||||
|
|
||||||
fmt.Printf("\t\tUsed: Physical %s (%d%% phys), Virtual %s (%d%% phys, %d%% virt)\n",
|
|
||||||
types.SizeStr(types.NewInt(stat.MemUsedMin)),
|
|
||||||
stat.MemUsedMin*100/stat.Info.Resources.MemPhysical,
|
|
||||||
types.SizeStr(types.NewInt(stat.MemUsedMax)),
|
|
||||||
stat.MemUsedMax*100/stat.Info.Resources.MemPhysical,
|
|
||||||
stat.MemUsedMax*100/(stat.Info.Resources.MemPhysical+stat.Info.Resources.MemSwap))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
1
go.mod
1
go.mod
@ -12,6 +12,7 @@ require (
|
|||||||
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f // indirect
|
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f // indirect
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/drand/drand v0.8.1
|
github.com/drand/drand v0.8.1
|
||||||
|
github.com/fatih/color v1.8.0
|
||||||
github.com/filecoin-project/chain-validation v0.0.6-0.20200430201010-ce84f6e96519
|
github.com/filecoin-project/chain-validation v0.0.6-0.20200430201010-ce84f6e96519
|
||||||
github.com/filecoin-project/filecoin-ffi v0.0.0-20200427223233-a0014b17f124
|
github.com/filecoin-project/filecoin-ffi v0.0.0-20200427223233-a0014b17f124
|
||||||
github.com/filecoin-project/go-address v0.0.2-0.20200218010043-eb9bb40ed5be
|
github.com/filecoin-project/go-address v0.0.2-0.20200218010043-eb9bb40ed5be
|
||||||
|
Loading…
Reference in New Issue
Block a user