pond: storage miner init

This commit is contained in:
Łukasz Magiera 2019-07-31 01:18:21 +02:00
parent af73ae0b89
commit 282654bf7b
8 changed files with 138 additions and 12 deletions

View File

@ -155,7 +155,7 @@ var initCmd = &cli.Command{
return err
}
log.Infof("Waiting for confirmation (TODO: actually wait)")
log.Infof("Waiting for confirmation")
mw, err := api.ChainWaitMsg(ctx, signed.Cid())
if err != nil {

View File

@ -13,8 +13,9 @@
}
.CristalScroll {
display: flex;
min-width: 100%;
height: 100%;
min-height: 100%;
overflow: auto;
}

View File

@ -2,6 +2,7 @@ import React from 'react';
import { Client } from 'rpc-websockets'
import Cristal from 'react-cristal'
import { BlockLinks } from "./BlockLink";
import StorageNodeInit from "./StorageNodeInit";
const stateConnected = 'connected'
const stateConnecting = 'connecting'
@ -31,6 +32,8 @@ class FullNode extends React.Component {
this.loadInfo = this.loadInfo.bind(this)
this.startMining = this.startMining.bind(this)
this.newScepAddr = this.newScepAddr.bind(this)
this.startStorageMiner = this.startStorageMiner.bind(this)
this.connect()
}
@ -101,6 +104,7 @@ class FullNode extends React.Component {
async startMining() {
// TODO: Use actual miner address
// see cli/miner.go
this.setState({mining: true})
let addr = "t0523423423" // in case we have no wallets
if (this.state.defaultAddr) {
addr = this.state.defaultAddr
@ -110,6 +114,16 @@ class FullNode extends React.Component {
await this.state.client.call("Filecoin.MinerStart", [addr])
}
async newScepAddr() {
const t = "secp256k1"
await this.state.client.call("Filecoin.WalletNew", [t])
this.loadInfo()
}
async startStorageMiner() {
this.props.mountWindow((onClose) => <StorageNodeInit fullRepo={this.props.node.Repo} fullConn={this.props.conn} pondClient={this.props.pondClient} onClose={onClose} mountWindow={this.props.mountWindow}/>)
}
render() {
let runtime = <div></div>
if (this.state.state === stateConnected) {
@ -129,6 +143,8 @@ class FullNode extends React.Component {
mine = "[Mining]"
}
let storageMine = <a href="#" onClick={this.startStorageMiner}>[Spawn Storage Miner]</a>
let balances = this.state.balances.map(([addr, balance]) => {
let line = <span>{truncAddr(addr)}:&nbsp;{balance}&nbsp;(ActTyp)</span>
if (this.state.defaultAddr === addr) {
@ -142,9 +158,11 @@ class FullNode extends React.Component {
<div>v{this.state.version.Version}, <abbr title={this.state.id}>{this.state.id.substr(-8)}</abbr>, {this.state.peers} peers</div>
<div>Repo: LOTUS_PATH={this.props.node.Repo}</div>
{chainInfo}
{mine}
<div>
<div>Balances:</div>
{mine} {storageMine}
</div>
<div>
<div>Balances: [New <a href="#" onClick={this.newScepAddr}>[Secp256k1]</a>]</div>
<div>{balances}</div>
</div>

View File

@ -52,7 +52,7 @@ class NodeList extends React.Component {
this.setState({nextWindow: id + 1})
const window = cb(() => {
console.log("umount wnd todo")
this.setState(prev => ({windows: {...prev.windows, [id]: undefined}}))
})
this.setState(prev => ({windows: {...prev.windows, [id]: window}}))

View File

@ -0,0 +1,18 @@
import React from 'react';
import {Cristal} from "react-cristal";
class StorageNode extends React.Component {
render() {
return <Cristal
title={"Storage miner XYZ"}
initialPosition={'center'}>
<div className="CristalScroll">
<div className="StorageNodeInit">
I'm a node
</div>
</div>
</Cristal>
}
}
export default StorageNode

View File

@ -0,0 +1,26 @@
import React from 'react';
import {Cristal} from "react-cristal";
import StorageNode from "./StorageNode";
class StorageNodeInit extends React.Component {
async componentDidMount() {
const info = await this.props.pondClient.call('Pond.SpawnStorage', [this.props.fullRepo])
this.props.onClose()
this.props.mountWindow((onClose) => <StorageNode node={info} fullRepo={this.props.fullRepo} fullConn={this.props.fullConn} pondClient={this.props.pondClient} onClose={onClose} mountWindow={this.props.mountWindow}/>)
}
render() {
return <Cristal
title={"Storage miner initializing"}
initialPosition={'center'}>
<div className="CristalScroll">
<div className="StorageNodeInit">
Waiting for init, make sure at least one miner is enabled
</div>
</div>
</Cristal>
}
}
export default StorageNodeInit

View File

@ -37,6 +37,8 @@ type nodeInfo struct {
Repo string
ID int32
ApiPort int32
Storage bool
}
func (api *api) Spawn() (nodeInfo, error) {
@ -63,11 +65,11 @@ func (api *api) Spawn() (nodeInfo, error) {
}
errlogfile, err := os.OpenFile(dir + ".err.log", os.O_CREATE | os.O_WRONLY, 0644)
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)
logfile, err := os.OpenFile(dir+".out.log", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nodeInfo{}, err
}
@ -137,6 +139,65 @@ func (api *api) TokenFor(id int32) (string, error) {
return string(t), 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
}
id := atomic.AddInt32(&api.cmds, 1)
cmd := exec.Command("./lotus-storage-miner", "init")
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)
cmd = exec.Command("./lotus-storage-miner", "run", "--api", fmt.Sprintf("%d", 2500+id))
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.Start(); err != nil {
return nodeInfo{}, err
}
info := nodeInfo{
Repo: dir,
ID: id,
ApiPort: 2500 + id,
Storage: true,
}
api.runningLk.Lock()
api.running[id] = runningNode{
cmd: cmd,
meta: info,
stop: func() {
defer errlogfile.Close()
defer logfile.Close()
},
}
api.runningLk.Unlock()
time.Sleep(time.Millisecond * 750) // TODO: Something less terrible
return info, nil
}
func main() {
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Pond", &api{running: map[int32]runningNode{}})

View File

@ -67,15 +67,17 @@ func (fsr *FsRepo) Exists() (bool, error) {
}
func (fsr *FsRepo) Init() error {
if _, err := os.Stat(fsr.path); err == nil {
return fsr.initKeystore()
} else if !os.IsNotExist(err) {
exist, err := fsr.Exists()
if err != nil {
return err
}
if exist {
return nil
}
log.Infof("Initializing repo at '%s'", fsr.path)
err := os.Mkdir(fsr.path, 0755) //nolint: gosec
if err != nil {
err = os.Mkdir(fsr.path, 0755) //nolint: gosec
if err != nil && !os.IsExist(err) {
return err
}
c, err := os.Create(filepath.Join(fsr.path, fsConfig))