2019-07-24 17:10:44 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2019-08-19 20:16:27 +00:00
|
|
|
"path"
|
2019-08-12 23:09:08 +00:00
|
|
|
"strconv"
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
"gopkg.in/urfave/cli.v2"
|
2020-05-20 17:43:22 +00:00
|
|
|
|
|
|
|
"github.com/filecoin-project/go-jsonrpc"
|
2019-07-24 17:10:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const listenAddr = "127.0.0.1:2222"
|
|
|
|
|
|
|
|
type runningNode struct {
|
2019-07-25 00:55:19 +00:00
|
|
|
cmd *exec.Cmd
|
2019-07-24 17:10:44 +00:00
|
|
|
meta nodeInfo
|
2019-07-26 00:40:06 +00:00
|
|
|
|
2019-08-19 22:38:32 +00:00
|
|
|
mux *outmux
|
2019-07-26 00:40:06 +00:00
|
|
|
stop func()
|
2019-07-24 17:10:44 +00:00
|
|
|
}
|
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
var onCmd = &cli.Command{
|
|
|
|
Name: "on",
|
|
|
|
Usage: "run a command on a given node",
|
|
|
|
Action: func(cctx *cli.Context) error {
|
|
|
|
client, err := apiClient()
|
2019-07-25 23:25:46 +00:00
|
|
|
if err != nil {
|
2019-08-12 23:09:08 +00:00
|
|
|
return err
|
2019-07-25 23:25:46 +00:00
|
|
|
}
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
nd, err := strconv.ParseInt(cctx.Args().Get(0), 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2019-07-25 23:25:46 +00:00
|
|
|
}
|
|
|
|
|
2019-08-12 23:53:59 +00:00
|
|
|
node := nodeById(client.Nodes(), int(nd))
|
2019-08-12 23:09:08 +00:00
|
|
|
var cmd *exec.Cmd
|
|
|
|
if !node.Storage {
|
|
|
|
cmd = exec.Command("./lotus", cctx.Args().Slice()[1:]...)
|
|
|
|
cmd.Env = []string{
|
|
|
|
"LOTUS_PATH=" + node.Repo,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cmd = exec.Command("./lotus-storage-miner")
|
|
|
|
cmd.Env = []string{
|
|
|
|
"LOTUS_STORAGE_PATH=" + node.Repo,
|
|
|
|
"LOTUS_PATH=" + node.FullNode,
|
|
|
|
}
|
|
|
|
}
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
cmd.Stderr = os.Stderr
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
err = cmd.Run()
|
|
|
|
return err
|
|
|
|
},
|
2019-07-24 17:10:44 +00:00
|
|
|
}
|
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
var shCmd = &cli.Command{
|
|
|
|
Name: "sh",
|
|
|
|
Usage: "spawn shell with node shell variables set",
|
|
|
|
Action: func(cctx *cli.Context) error {
|
|
|
|
client, err := apiClient()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
nd, err := strconv.ParseInt(cctx.Args().Get(0), 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:53:59 +00:00
|
|
|
node := nodeById(client.Nodes(), int(nd))
|
2019-08-12 23:09:08 +00:00
|
|
|
shcmd := exec.Command("/bin/bash")
|
|
|
|
if !node.Storage {
|
|
|
|
shcmd.Env = []string{
|
|
|
|
"LOTUS_PATH=" + node.Repo,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shcmd.Env = []string{
|
|
|
|
"LOTUS_STORAGE_PATH=" + node.Repo,
|
|
|
|
"LOTUS_PATH=" + node.FullNode,
|
|
|
|
}
|
|
|
|
}
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-12-02 16:47:09 +00:00
|
|
|
shcmd.Env = append(os.Environ(), shcmd.Env...)
|
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
shcmd.Stdin = os.Stdin
|
|
|
|
shcmd.Stdout = os.Stdout
|
|
|
|
shcmd.Stderr = os.Stderr
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
fmt.Printf("Entering shell for Node %d\n", nd)
|
|
|
|
err = shcmd.Run()
|
|
|
|
fmt.Printf("Closed pond shell\n")
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
return err
|
|
|
|
},
|
2019-07-24 17:10:44 +00:00
|
|
|
}
|
|
|
|
|
2019-08-12 23:53:59 +00:00
|
|
|
func nodeById(nodes []nodeInfo, i int) nodeInfo {
|
|
|
|
for _, n := range nodes {
|
|
|
|
if n.ID == int32(i) {
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic("no node with this id")
|
|
|
|
}
|
|
|
|
|
2019-08-19 20:16:27 +00:00
|
|
|
func logHandler(api *api) func(http.ResponseWriter, *http.Request) {
|
|
|
|
return func(w http.ResponseWriter, req *http.Request) {
|
|
|
|
id, err := strconv.ParseInt(path.Base(req.URL.Path), 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
api.runningLk.Lock()
|
|
|
|
n := api.running[int32(id)]
|
|
|
|
api.runningLk.Unlock()
|
|
|
|
|
|
|
|
n.mux.ServeHTTP(w, req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
var runCmd = &cli.Command{
|
|
|
|
Name: "run",
|
|
|
|
Usage: "run lotuspond daemon",
|
|
|
|
Action: func(cctx *cli.Context) error {
|
|
|
|
rpcServer := jsonrpc.NewServer()
|
2019-09-17 12:03:28 +00:00
|
|
|
a := &api{running: map[int32]*runningNode{}}
|
2019-08-19 20:16:27 +00:00
|
|
|
rpcServer.Register("Pond", a)
|
2019-07-30 23:18:21 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
http.Handle("/", http.FileServer(http.Dir("lotuspond/front/build")))
|
2019-09-20 06:50:10 +00:00
|
|
|
http.HandleFunc("/app/", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
http.ServeFile(w, r, "lotuspond/front/build/index.html")
|
|
|
|
})
|
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
http.Handle("/rpc/v0", rpcServer)
|
2019-08-19 20:16:27 +00:00
|
|
|
http.HandleFunc("/logs/", logHandler(a))
|
2019-07-30 23:18:21 +00:00
|
|
|
|
2019-08-12 23:09:08 +00:00
|
|
|
fmt.Printf("Listening on http://%s\n", listenAddr)
|
|
|
|
return http.ListenAndServe(listenAddr, nil)
|
|
|
|
},
|
2019-07-30 23:18:21 +00:00
|
|
|
}
|
|
|
|
|
2019-07-24 17:10:44 +00:00
|
|
|
func main() {
|
2019-08-12 23:09:08 +00:00
|
|
|
app := &cli.App{
|
|
|
|
Name: "pond",
|
|
|
|
Commands: []*cli.Command{
|
|
|
|
runCmd,
|
|
|
|
shCmd,
|
|
|
|
onCmd,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2019-07-24 17:10:44 +00:00
|
|
|
}
|