storj/cmd/satellite/gracefulexit.go
Maximillian von Briesen abb567f6ae
cmd/satellite: add graceful exit reports command to satellite CLI (#3300)
* update lock file and add comment

* add created at and bytes transferred

* cleanup

* rename db func to GetGracefulExitNodesByTimeFrame

* fix flag

* split into two overlay functions

* := to =

* fix test

* add node not found error class

* fix overlay test

* suggested test changes

* review suggestions

* get exit status from overlay.Get()

* check rows.Err

* fix panic when ExitFinishedAt is nil

* fix comments in cmdGracefulExit
2019-10-22 21:06:01 -04:00

101 lines
2.4 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package main
import (
"context"
"encoding/csv"
"fmt"
"io"
"os"
"strconv"
"time"
"github.com/zeebo/errs"
"go.uber.org/zap"
"storj.io/storj/pkg/storj"
"storj.io/storj/satellite/gracefulexit"
"storj.io/storj/satellite/satellitedb"
)
// generateGracefulExitCSV creates a report with graceful exit data for exiting or exited nodes in a given period
func generateGracefulExitCSV(ctx context.Context, completed bool, start time.Time, end time.Time, output io.Writer) error {
db, err := satellitedb.New(zap.L().Named("db"), gracefulExitCfg.Database)
if err != nil {
return errs.New("error connecting to master database on satellite: %+v", err)
}
defer func() {
err = errs.Combine(err, db.Close())
}()
var nodeIDs storj.NodeIDList
if completed {
nodeIDs, err = db.OverlayCache().GetGracefulExitCompletedByTimeFrame(ctx, start, end)
if err != nil {
return err
}
} else {
nodeIDs, err = db.OverlayCache().GetGracefulExitIncompleteByTimeFrame(ctx, start, end)
if err != nil {
return err
}
}
w := csv.NewWriter(output)
headers := []string{
"nodeID",
"walletAddress",
"nodeCreationDate",
"initiatedGracefulExit",
"completedGracefulExit",
"transferredGB",
}
if err := w.Write(headers); err != nil {
return err
}
for _, id := range nodeIDs {
node, err := db.OverlayCache().Get(ctx, id)
if err != nil {
return err
}
exitProgress, err := db.GracefulExit().GetProgress(ctx, id)
if gracefulexit.ErrNodeNotFound.Has(err) {
exitProgress = &gracefulexit.Progress{}
} else if err != nil {
return err
}
exitStatus := node.ExitStatus
exitFinished := ""
if exitStatus.ExitFinishedAt != nil {
exitFinished = exitStatus.ExitFinishedAt.Format("2006-01-02")
}
nextRow := []string{
node.Id.String(),
node.Operator.Wallet,
node.CreatedAt.Format("2006-01-02"),
exitStatus.ExitInitiatedAt.Format("2006-01-02"),
exitFinished,
strconv.FormatInt(exitProgress.BytesTransferred, 10),
}
if err := w.Write(nextRow); err != nil {
return err
}
}
if err := w.Error(); err != nil {
return err
}
w.Flush()
if output != os.Stdout {
if completed {
fmt.Println("Generated report for nodes that have completed graceful exit.")
} else {
fmt.Println("Generated report for nodes that are in the process of graceful exiting.")
}
}
return err
}