Merge pull request #1899 from filecoin-project/feat/1827-lotus-daemon-stop-cmd
add (sub)commands which shut down lotus daemon and storage miner
This commit is contained in:
commit
35740895ed
@ -34,6 +34,9 @@ type Common interface {
|
|||||||
|
|
||||||
LogList(context.Context) ([]string, error)
|
LogList(context.Context) ([]string, error)
|
||||||
LogSetLevel(context.Context, string, string) error
|
LogSetLevel(context.Context, string, string) error
|
||||||
|
|
||||||
|
// trigger graceful shutdown
|
||||||
|
Shutdown(context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version provides various build-time information
|
// Version provides various build-time information
|
||||||
|
@ -47,6 +47,8 @@ type CommonStruct struct {
|
|||||||
|
|
||||||
LogList func(context.Context) ([]string, error) `perm:"write"`
|
LogList func(context.Context) ([]string, error) `perm:"write"`
|
||||||
LogSetLevel func(context.Context, string, string) error `perm:"write"`
|
LogSetLevel func(context.Context, string, string) error `perm:"write"`
|
||||||
|
|
||||||
|
Shutdown func(context.Context) error `perm:"admin"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,6 +295,10 @@ func (c *CommonStruct) LogSetLevel(ctx context.Context, group, level string) err
|
|||||||
return c.Internal.LogSetLevel(ctx, group, level)
|
return c.Internal.LogSetLevel(ctx, group, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CommonStruct) Shutdown(ctx context.Context) error {
|
||||||
|
return c.Internal.Shutdown(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// FullNodeStruct
|
// FullNodeStruct
|
||||||
|
|
||||||
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
|
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
|
||||||
|
@ -290,7 +290,7 @@ var runCmd = &cli.Command{
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
log.Warn("Shutting down..")
|
log.Warn("Shutting down...")
|
||||||
if err := srv.Shutdown(context.TODO()); err != nil {
|
if err := srv.Shutdown(context.TODO()); err != nil {
|
||||||
log.Errorf("shutting down RPC server failed: %s", err)
|
log.Errorf("shutting down RPC server failed: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ func main() {
|
|||||||
initCmd,
|
initCmd,
|
||||||
rewardsCmd,
|
rewardsCmd,
|
||||||
runCmd,
|
runCmd,
|
||||||
|
stopCmd,
|
||||||
sectorsCmd,
|
sectorsCmd,
|
||||||
storageCmd,
|
storageCmd,
|
||||||
setPriceCmd,
|
setPriceCmd,
|
||||||
|
@ -100,9 +100,12 @@ var runCmd = &cli.Command{
|
|||||||
return xerrors.Errorf("repo at '%s' is not initialized, run 'lotus-storage-miner init' to set it up", storageRepoPath)
|
return xerrors.Errorf("repo at '%s' is not initialized, run 'lotus-storage-miner init' to set it up", storageRepoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shutdownChan := make(chan struct{})
|
||||||
|
|
||||||
var minerapi api.StorageMiner
|
var minerapi api.StorageMiner
|
||||||
stop, err := node.New(ctx,
|
stop, err := node.New(ctx,
|
||||||
node.StorageMiner(&minerapi),
|
node.StorageMiner(&minerapi),
|
||||||
|
node.Override(new(dtypes.ShutdownChan), shutdownChan),
|
||||||
node.Online(),
|
node.Online(),
|
||||||
node.Repo(r),
|
node.Repo(r),
|
||||||
|
|
||||||
@ -156,8 +159,12 @@ var runCmd = &cli.Command{
|
|||||||
|
|
||||||
sigChan := make(chan os.Signal, 2)
|
sigChan := make(chan os.Signal, 2)
|
||||||
go func() {
|
go func() {
|
||||||
<-sigChan
|
select {
|
||||||
log.Warn("Shutting down..")
|
case <-sigChan:
|
||||||
|
case <-shutdownChan:
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warn("Shutting down...")
|
||||||
if err := stop(context.TODO()); err != nil {
|
if err := stop(context.TODO()); err != nil {
|
||||||
log.Errorf("graceful shutting down failed: %s", err)
|
log.Errorf("graceful shutting down failed: %s", err)
|
||||||
}
|
}
|
||||||
|
29
cmd/lotus-storage-miner/stop.go
Normal file
29
cmd/lotus-storage-miner/stop.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "net/http/pprof"
|
||||||
|
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var stopCmd = &cli.Command{
|
||||||
|
Name: "stop",
|
||||||
|
Usage: "Stop a running lotus storage miner",
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, closer, err := lcli.GetAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
err = api.Shutdown(lcli.ReqContext(cctx))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
"github.com/filecoin-project/lotus/lib/peermgr"
|
"github.com/filecoin-project/lotus/lib/peermgr"
|
||||||
"github.com/filecoin-project/lotus/metrics"
|
"github.com/filecoin-project/lotus/metrics"
|
||||||
"github.com/filecoin-project/lotus/node"
|
"github.com/filecoin-project/lotus/node"
|
||||||
@ -44,6 +45,26 @@ const (
|
|||||||
preTemplateFlag = "genesis-template"
|
preTemplateFlag = "genesis-template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var daemonStopCmd = &cli.Command{
|
||||||
|
Name: "stop",
|
||||||
|
Usage: "Stop a running lotus daemon",
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, closer, err := lcli.GetAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
err = api.Shutdown(lcli.ReqContext(cctx))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// DaemonCmd is the `go-lotus daemon` command
|
// DaemonCmd is the `go-lotus daemon` command
|
||||||
var DaemonCmd = &cli.Command{
|
var DaemonCmd = &cli.Command{
|
||||||
Name: "daemon",
|
Name: "daemon",
|
||||||
@ -170,12 +191,15 @@ var DaemonCmd = &cli.Command{
|
|||||||
genesis = node.Override(new(modules.Genesis), testing.MakeGenesis(cctx.String(makeGenFlag), cctx.String(preTemplateFlag)))
|
genesis = node.Override(new(modules.Genesis), testing.MakeGenesis(cctx.String(makeGenFlag), cctx.String(preTemplateFlag)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shutdownChan := make(chan struct{})
|
||||||
|
|
||||||
var api api.FullNode
|
var api api.FullNode
|
||||||
|
|
||||||
stop, err := node.New(ctx,
|
stop, err := node.New(ctx,
|
||||||
node.FullAPI(&api),
|
node.FullAPI(&api),
|
||||||
|
|
||||||
node.Override(new(dtypes.Bootstrapper), isBootstrapper),
|
node.Override(new(dtypes.Bootstrapper), isBootstrapper),
|
||||||
|
node.Override(new(dtypes.ShutdownChan), shutdownChan),
|
||||||
node.Online(),
|
node.Online(),
|
||||||
node.Repo(r),
|
node.Repo(r),
|
||||||
|
|
||||||
@ -221,7 +245,10 @@ var DaemonCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: properly parse api endpoint (or make it a URL)
|
// TODO: properly parse api endpoint (or make it a URL)
|
||||||
return serveRPC(api, stop, endpoint)
|
return serveRPC(api, stop, endpoint, shutdownChan)
|
||||||
|
},
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
daemonStopCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
|
|
||||||
var log = logging.Logger("main")
|
var log = logging.Logger("main")
|
||||||
|
|
||||||
func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr) error {
|
func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shutdownCh <-chan struct{}) error {
|
||||||
rpcServer := jsonrpc.NewServer()
|
rpcServer := jsonrpc.NewServer()
|
||||||
rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(a))
|
rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(a))
|
||||||
|
|
||||||
@ -62,17 +62,23 @@ func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr) erro
|
|||||||
|
|
||||||
srv := &http.Server{Handler: http.DefaultServeMux}
|
srv := &http.Server{Handler: http.DefaultServeMux}
|
||||||
|
|
||||||
sigChan := make(chan os.Signal, 2)
|
sigCh := make(chan os.Signal, 2)
|
||||||
go func() {
|
go func() {
|
||||||
<-sigChan
|
select {
|
||||||
|
case <-sigCh:
|
||||||
|
case <-shutdownCh:
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warn("Shutting down...")
|
||||||
if err := srv.Shutdown(context.TODO()); err != nil {
|
if err := srv.Shutdown(context.TODO()); err != nil {
|
||||||
log.Errorf("shutting down RPC server failed: %s", err)
|
log.Errorf("shutting down RPC server failed: %s", err)
|
||||||
}
|
}
|
||||||
if err := stop(context.TODO()); err != nil {
|
if err := stop(context.TODO()); err != nil {
|
||||||
log.Errorf("graceful shutting down failed: %s", err)
|
log.Errorf("graceful shutting down failed: %s", err)
|
||||||
}
|
}
|
||||||
|
log.Warn("Graceful shutdown successful")
|
||||||
}()
|
}()
|
||||||
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
|
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)
|
||||||
|
|
||||||
return srv.Serve(manet.NetListener(lst))
|
return srv.Serve(manet.NetListener(lst))
|
||||||
}
|
}
|
||||||
|
@ -150,6 +150,7 @@ func defaults() []Option {
|
|||||||
Override(new(helpers.MetricsCtx), context.Background),
|
Override(new(helpers.MetricsCtx), context.Background),
|
||||||
Override(new(record.Validator), modules.RecordValidator),
|
Override(new(record.Validator), modules.RecordValidator),
|
||||||
Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)),
|
Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(false)),
|
||||||
|
Override(new(dtypes.ShutdownChan), make(chan struct{})),
|
||||||
|
|
||||||
// Filecoin modules
|
// Filecoin modules
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ type CommonAPI struct {
|
|||||||
APISecret *dtypes.APIAlg
|
APISecret *dtypes.APIAlg
|
||||||
Host host.Host
|
Host host.Host
|
||||||
Router lp2p.BaseIpfsRouting
|
Router lp2p.BaseIpfsRouting
|
||||||
|
ShutdownChan dtypes.ShutdownChan
|
||||||
}
|
}
|
||||||
|
|
||||||
type jwtPayload struct {
|
type jwtPayload struct {
|
||||||
@ -115,4 +116,9 @@ func (a *CommonAPI) LogSetLevel(ctx context.Context, subsystem, level string) er
|
|||||||
return logging.SetLogLevel(subsystem, level)
|
return logging.SetLogLevel(subsystem, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *CommonAPI) Shutdown(ctx context.Context) error {
|
||||||
|
a.ShutdownChan <- struct{}{}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var _ api.Common = &CommonAPI{}
|
var _ api.Common = &CommonAPI{}
|
||||||
|
5
node/modules/dtypes/shutdown.go
Normal file
5
node/modules/dtypes/shutdown.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package dtypes
|
||||||
|
|
||||||
|
// ShutdownChan is a channel to which you send a value if you intend to shut
|
||||||
|
// down the daemon (or storage miner), including the node and RPC server.
|
||||||
|
type ShutdownChan chan struct{}
|
Loading…
Reference in New Issue
Block a user