lotus/lotuspond/spawn.go
2019-10-09 10:10:13 +02:00

219 lines
4.7 KiB
Go

package main
import (
"fmt"
"golang.org/x/xerrors"
"io"
"io/ioutil"
"os"
"os/exec"
"sync/atomic"
"time"
)
func (api *api) Spawn() (nodeInfo, error) {
dir, err := ioutil.TempDir(os.TempDir(), "lotus-")
if err != nil {
return nodeInfo{}, err
}
genParam := "--genesis=" + api.genesis
id := atomic.AddInt32(&api.cmds, 1)
if id == 1 {
// make genesis
genf, err := ioutil.TempFile(os.TempDir(), "lotus-genesis-")
if err != nil {
return nodeInfo{}, err
}
api.genesis = genf.Name()
genParam = "--lotus-make-random-genesis=" + api.genesis
if err := genf.Close(); err != nil {
return nodeInfo{}, err
}
}
errlogfile, err := os.OpenFile(dir+".err.log", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nodeInfo{}, err
}
logfile, err := os.OpenFile(dir+".out.log", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nodeInfo{}, err
}
mux := newWsMux()
cmd := exec.Command("./lotus", "daemon", "--bootstrap=false", genParam, "--api", fmt.Sprintf("%d", 2500+id))
cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile, mux.errpw)
cmd.Stdout = io.MultiWriter(os.Stdout, logfile, mux.outpw)
cmd.Env = []string{"LOTUS_PATH=" + dir}
if err := cmd.Start(); err != nil {
return nodeInfo{}, err
}
info := nodeInfo{
Repo: dir,
ID: id,
ApiPort: 2500 + id,
State: NodeRunning,
}
api.runningLk.Lock()
api.running[id] = &runningNode{
cmd: cmd,
meta: info,
mux: mux,
stop: func() {
cmd.Process.Signal(os.Interrupt)
cmd.Process.Wait()
api.runningLk.Lock()
api.running[id].meta.State = NodeStopped
api.runningLk.Unlock()
//logfile.Close()
//errlogfile.Close()
//close(mux.stop)
},
}
api.runningLk.Unlock()
time.Sleep(time.Millisecond * 750) // TODO: Something less terrible
return info, nil
}
func (api *api) SpawnStorage(fullNodeRepo string) (nodeInfo, error) {
dir, err := ioutil.TempDir(os.TempDir(), "lotus-storage-")
if err != nil {
return nodeInfo{}, err
}
errlogfile, err := os.OpenFile(dir+".err.log", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nodeInfo{}, err
}
logfile, err := os.OpenFile(dir+".out.log", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nodeInfo{}, err
}
initArgs := []string{"init"}
if fullNodeRepo == api.running[1].meta.Repo {
initArgs = []string{"init", "--actor=t0101", "--genesis-miner"}
}
id := atomic.AddInt32(&api.cmds, 1)
cmd := exec.Command("./lotus-storage-miner", initArgs...)
cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile)
cmd.Stdout = io.MultiWriter(os.Stdout, logfile)
cmd.Env = []string{"LOTUS_STORAGE_PATH=" + dir, "LOTUS_PATH=" + fullNodeRepo}
if err := cmd.Run(); err != nil {
return nodeInfo{}, err
}
time.Sleep(time.Millisecond * 300)
mux := newWsMux()
cmd = exec.Command("./lotus-storage-miner", "run", "--api", fmt.Sprintf("%d", 2500+id))
cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile, mux.errpw)
cmd.Stdout = io.MultiWriter(os.Stdout, logfile, mux.outpw)
cmd.Env = []string{"LOTUS_STORAGE_PATH=" + dir, "LOTUS_PATH=" + fullNodeRepo}
if err := cmd.Start(); err != nil {
return nodeInfo{}, err
}
info := nodeInfo{
Repo: dir,
ID: id,
ApiPort: 2500 + id,
State: NodeRunning,
FullNode: fullNodeRepo,
Storage: true,
}
api.runningLk.Lock()
api.running[id] = &runningNode{
cmd: cmd,
meta: info,
mux: mux,
stop: func() {
cmd.Process.Signal(os.Interrupt)
cmd.Process.Wait()
api.runningLk.Lock()
api.running[id].meta.State = NodeStopped
api.runningLk.Unlock()
//logfile.Close()
//errlogfile.Close()
//close(mux.stop)
},
}
api.runningLk.Unlock()
time.Sleep(time.Millisecond * 750) // TODO: Something less terrible
return info, nil
}
func (api *api) RestartNode(id int32) (nodeInfo, error) {
api.runningLk.Lock()
defer api.runningLk.Unlock()
nd, ok := api.running[id]
if !ok {
return nodeInfo{}, xerrors.New("node not found")
}
if nd.meta.State != NodeStopped {
return nodeInfo{}, xerrors.New("node not stopped")
}
var cmd *exec.Cmd
if nd.meta.Storage {
cmd = exec.Command("./lotus-storage-miner", "run", "--api", fmt.Sprintf("%d", 2500+id))
} else {
cmd = exec.Command("./lotus", "daemon", "--api", fmt.Sprintf("%d", 2500+id))
}
cmd.Stderr = nd.cmd.Stderr // recycle old vars
cmd.Stdout = nd.cmd.Stdout
cmd.Env = nd.cmd.Env
if err := cmd.Start(); err != nil {
return nodeInfo{}, err
}
nd.cmd = cmd
nd.stop = func() {
cmd.Process.Signal(os.Interrupt)
cmd.Process.Wait()
api.runningLk.Lock()
api.running[id].meta.State = NodeStopped
api.runningLk.Unlock()
//logfile.Close()
//errlogfile.Close()
//close(mux.stop)
}
nd.meta.State = NodeRunning
time.Sleep(time.Millisecond * 750) // TODO: Something less terrible
return nd.meta, nil
}