lotus/lotuspond/spawn.go

288 lines
7.1 KiB
Go
Raw Normal View History

2019-09-17 12:36:17 +00:00
package main
import (
2020-02-23 23:39:45 +00:00
"encoding/json"
2019-09-17 12:36:17 +00:00
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
2019-09-17 12:36:17 +00:00
"sync/atomic"
"time"
"github.com/filecoin-project/lotus/chain/types"
"golang.org/x/xerrors"
2019-11-27 14:18:51 +00:00
"github.com/filecoin-project/go-address"
2020-09-07 03:49:10 +00:00
"github.com/filecoin-project/go-state-types/abi"
2020-05-12 17:58:12 +00:00
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
2020-08-07 13:19:12 +00:00
"github.com/filecoin-project/lotus/chain/gen"
2019-11-27 14:18:51 +00:00
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
2020-05-12 17:58:12 +00:00
"github.com/filecoin-project/lotus/genesis"
2019-09-17 12:36:17 +00:00
)
func init() {
2020-06-15 16:30:49 +00:00
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
2020-05-12 17:58:12 +00:00
}
}
2019-09-17 12:36:17 +00:00
func (api *api) Spawn() (nodeInfo, error) {
dir, err := ioutil.TempDir(os.TempDir(), "lotus-")
if err != nil {
return nodeInfo{}, err
}
2019-11-27 14:18:51 +00:00
params := []string{"daemon", "--bootstrap=false"}
2019-09-17 12:36:17 +00:00
genParam := "--genesis=" + api.genesis
2019-11-27 14:18:51 +00:00
2019-09-17 12:36:17 +00:00
id := atomic.AddInt32(&api.cmds, 1)
if id == 1 {
2019-11-27 14:18:51 +00:00
// preseal
2020-02-23 23:39:45 +00:00
genMiner, err := address.NewIDAddress(genesis2.MinerStart)
2019-11-27 14:18:51 +00:00
if err != nil {
return nodeInfo{}, err
}
2019-11-29 03:38:18 +00:00
sbroot := filepath.Join(dir, "preseal")
2020-07-03 01:29:06 +00:00
genm, ki, err := seed.PreSeal(genMiner, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, 2, sbroot, []byte("8"), nil, false)
2019-11-27 14:18:51 +00:00
if err != nil {
return nodeInfo{}, xerrors.Errorf("preseal failed: %w", err)
}
2019-11-29 03:38:18 +00:00
2020-02-23 07:49:15 +00:00
if err := seed.WriteGenesisMiner(genMiner, sbroot, genm, ki); err != nil {
2019-11-29 03:38:18 +00:00
return nodeInfo{}, xerrors.Errorf("failed to write genminer info: %w", err)
}
2020-02-23 23:39:45 +00:00
params = append(params, "--import-key="+filepath.Join(dir, "preseal", "pre-seal-t01000.key"))
params = append(params, "--genesis-template="+filepath.Join(dir, "preseal", "genesis-template.json"))
// Create template
var template genesis.Template
template.Miners = append(template.Miners, *genm)
template.Accounts = append(template.Accounts, genesis.Actor{
Type: genesis.TAccount,
2020-05-29 12:36:56 +00:00
Balance: types.FromFil(5000000),
2020-02-23 23:39:45 +00:00
Meta: (&genesis.AccountMeta{Owner: genm.Owner}).ActorMeta(),
})
2020-08-07 13:19:12 +00:00
template.VerifregRootKey = gen.DefaultVerifregRootkeyActor
2020-02-23 23:39:45 +00:00
tb, err := json.Marshal(&template)
if err != nil {
return nodeInfo{}, xerrors.Errorf("marshal genesis template: %w", err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "preseal", "genesis-template.json"), tb, 0664); err != nil {
return nodeInfo{}, xerrors.Errorf("write genesis template: %w", err)
}
2019-11-27 14:18:51 +00:00
2019-09-17 12:36:17 +00:00
// make genesis
genf, err := ioutil.TempFile(os.TempDir(), "lotus-genesis-")
if err != nil {
return nodeInfo{}, err
}
api.genesis = genf.Name()
2020-02-23 23:39:45 +00:00
genParam = "--lotus-make-genesis=" + api.genesis
2019-09-17 12:36:17 +00:00
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()
confStr := fmt.Sprintf("[API]\nListenAddress = \"/ip4/127.0.0.1/tcp/%d/http\"\n", 2500+id)
err = ioutil.WriteFile(filepath.Join(dir, "config.toml"), []byte(confStr), 0700)
if err != nil {
return nodeInfo{}, err
}
2019-11-27 14:18:51 +00:00
cmd := exec.Command("./lotus", append(params, genParam)...)
2019-09-17 12:36:17 +00:00
cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile, mux.errpw)
cmd.Stdout = io.MultiWriter(os.Stdout, logfile, mux.outpw)
cmd.Env = append(os.Environ(), "LOTUS_PATH="+dir)
2019-09-17 12:36:17 +00:00
if err := cmd.Start(); err != nil {
return nodeInfo{}, err
}
info := nodeInfo{
Repo: dir,
ID: id,
APIPort: 2500 + id,
2019-09-17 12:36:17 +00:00
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
}
2019-12-04 16:53:32 +00:00
initArgs := []string{"init", "--nosync"}
2019-09-17 12:36:17 +00:00
if fullNodeRepo == api.running[1].meta.Repo {
2020-02-04 23:06:18 +00:00
presealPrefix := filepath.Join(fullNodeRepo, "preseal")
initArgs = []string{"init", "--actor=t01000", "--genesis-miner", "--pre-sealed-sectors=" + presealPrefix, "--pre-sealed-metadata=" + filepath.Join(presealPrefix, "pre-seal-t01000.json")}
2019-09-17 12:36:17 +00:00
}
id := atomic.AddInt32(&api.cmds, 1)
2020-07-08 10:38:59 +00:00
cmd := exec.Command("./lotus-miner", initArgs...)
2019-09-17 12:36:17 +00:00
cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile)
cmd.Stdout = io.MultiWriter(os.Stdout, logfile)
2020-07-08 10:38:59 +00:00
cmd.Env = append(os.Environ(), "LOTUS_MINER_PATH="+dir, "LOTUS_PATH="+fullNodeRepo)
2019-09-17 12:36:17 +00:00
if err := cmd.Run(); err != nil {
return nodeInfo{}, err
}
time.Sleep(time.Millisecond * 300)
mux := newWsMux()
2020-07-08 10:38:59 +00:00
cmd = exec.Command("./lotus-miner", "run", "--api", fmt.Sprintf("%d", 2500+id), "--nosync")
2019-09-17 12:36:17 +00:00
cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile, mux.errpw)
cmd.Stdout = io.MultiWriter(os.Stdout, logfile, mux.outpw)
2020-07-08 10:38:59 +00:00
cmd.Env = append(os.Environ(), "LOTUS_MINER_PATH="+dir, "LOTUS_PATH="+fullNodeRepo)
2019-09-17 12:36:17 +00:00
if err := cmd.Start(); err != nil {
return nodeInfo{}, err
}
info := nodeInfo{
Repo: dir,
ID: id,
APIPort: 2500 + id,
2019-09-17 12:36:17 +00:00
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 {
2020-07-08 10:38:59 +00:00
cmd = exec.Command("./lotus-miner", "run", "--api", fmt.Sprintf("%d", 2500+id), "--nosync")
2019-09-17 12:36:17 +00:00
} 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
}