first take at "daemon stop" command

Fixes #1827

TODO: plumb the daemon-stopping into lotus-storage-miner, too
This commit is contained in:
laser 2020-06-02 11:54:24 -07:00
parent 5e727819ad
commit 38d714a28a
8 changed files with 49 additions and 9 deletions

View File

@ -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

View File

@ -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) {

View File

View File

@ -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"
@ -49,7 +50,18 @@ var daemonStopCmd = &cli.Command{
Usage: "Stop a running lotus daemon", Usage: "Stop a running lotus daemon",
Flags: []cli.Flag{}, Flags: []cli.Flag{},
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
panic("wombat attack") 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
}, },
} }
@ -179,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)))
} }
shutdownCh := 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.ShutdownCh), shutdownCh),
node.Online(), node.Online(),
node.Repo(r), node.Repo(r),
@ -230,7 +245,7 @@ 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, shutdownCh)
}, },
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
daemonStopCmd, daemonStopCmd,

View File

@ -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))
} }

View File

@ -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.ShutdownCh), make(chan struct{})),
// Filecoin modules // Filecoin modules

View File

@ -25,9 +25,10 @@ import (
type CommonAPI struct { type CommonAPI struct {
fx.In fx.In
APISecret *dtypes.APIAlg APISecret *dtypes.APIAlg
Host host.Host Host host.Host
Router lp2p.BaseIpfsRouting Router lp2p.BaseIpfsRouting
ShutdownCh dtypes.ShutdownCh
} }
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.ShutdownCh <- struct{}{}
return nil
}
var _ api.Common = &CommonAPI{} var _ api.Common = &CommonAPI{}

View File

@ -0,0 +1,3 @@
package dtypes
type ShutdownCh chan struct{}