pond: storage miner init
This commit is contained in:
parent
af73ae0b89
commit
282654bf7b
@ -155,7 +155,7 @@ var initCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Waiting for confirmation (TODO: actually wait)")
|
log.Infof("Waiting for confirmation")
|
||||||
|
|
||||||
mw, err := api.ChainWaitMsg(ctx, signed.Cid())
|
mw, err := api.ChainWaitMsg(ctx, signed.Cid())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,8 +13,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.CristalScroll {
|
.CristalScroll {
|
||||||
|
display: flex;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
height: 100%;
|
min-height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import { Client } from 'rpc-websockets'
|
import { Client } from 'rpc-websockets'
|
||||||
import Cristal from 'react-cristal'
|
import Cristal from 'react-cristal'
|
||||||
import { BlockLinks } from "./BlockLink";
|
import { BlockLinks } from "./BlockLink";
|
||||||
|
import StorageNodeInit from "./StorageNodeInit";
|
||||||
|
|
||||||
const stateConnected = 'connected'
|
const stateConnected = 'connected'
|
||||||
const stateConnecting = 'connecting'
|
const stateConnecting = 'connecting'
|
||||||
@ -31,6 +32,8 @@ class FullNode extends React.Component {
|
|||||||
|
|
||||||
this.loadInfo = this.loadInfo.bind(this)
|
this.loadInfo = this.loadInfo.bind(this)
|
||||||
this.startMining = this.startMining.bind(this)
|
this.startMining = this.startMining.bind(this)
|
||||||
|
this.newScepAddr = this.newScepAddr.bind(this)
|
||||||
|
this.startStorageMiner = this.startStorageMiner.bind(this)
|
||||||
|
|
||||||
this.connect()
|
this.connect()
|
||||||
}
|
}
|
||||||
@ -101,6 +104,7 @@ class FullNode extends React.Component {
|
|||||||
async startMining() {
|
async startMining() {
|
||||||
// TODO: Use actual miner address
|
// TODO: Use actual miner address
|
||||||
// see cli/miner.go
|
// see cli/miner.go
|
||||||
|
this.setState({mining: true})
|
||||||
let addr = "t0523423423" // in case we have no wallets
|
let addr = "t0523423423" // in case we have no wallets
|
||||||
if (this.state.defaultAddr) {
|
if (this.state.defaultAddr) {
|
||||||
addr = this.state.defaultAddr
|
addr = this.state.defaultAddr
|
||||||
@ -110,6 +114,16 @@ class FullNode extends React.Component {
|
|||||||
await this.state.client.call("Filecoin.MinerStart", [addr])
|
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() {
|
render() {
|
||||||
let runtime = <div></div>
|
let runtime = <div></div>
|
||||||
if (this.state.state === stateConnected) {
|
if (this.state.state === stateConnected) {
|
||||||
@ -129,6 +143,8 @@ class FullNode extends React.Component {
|
|||||||
mine = "[Mining]"
|
mine = "[Mining]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let storageMine = <a href="#" onClick={this.startStorageMiner}>[Spawn Storage Miner]</a>
|
||||||
|
|
||||||
let balances = this.state.balances.map(([addr, balance]) => {
|
let balances = this.state.balances.map(([addr, balance]) => {
|
||||||
let line = <span>{truncAddr(addr)}: {balance} (ActTyp)</span>
|
let line = <span>{truncAddr(addr)}: {balance} (ActTyp)</span>
|
||||||
if (this.state.defaultAddr === addr) {
|
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>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>
|
<div>Repo: LOTUS_PATH={this.props.node.Repo}</div>
|
||||||
{chainInfo}
|
{chainInfo}
|
||||||
{mine}
|
|
||||||
<div>
|
<div>
|
||||||
<div>Balances:</div>
|
{mine} {storageMine}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Balances: [New <a href="#" onClick={this.newScepAddr}>[Secp256k1]</a>]</div>
|
||||||
<div>{balances}</div>
|
<div>{balances}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class NodeList extends React.Component {
|
|||||||
this.setState({nextWindow: id + 1})
|
this.setState({nextWindow: id + 1})
|
||||||
|
|
||||||
const window = cb(() => {
|
const window = cb(() => {
|
||||||
console.log("umount wnd todo")
|
this.setState(prev => ({windows: {...prev.windows, [id]: undefined}}))
|
||||||
})
|
})
|
||||||
|
|
||||||
this.setState(prev => ({windows: {...prev.windows, [id]: window}}))
|
this.setState(prev => ({windows: {...prev.windows, [id]: window}}))
|
||||||
|
18
lotuspond/front/src/StorageNode.js
Normal file
18
lotuspond/front/src/StorageNode.js
Normal 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
|
26
lotuspond/front/src/StorageNodeInit.js
Normal file
26
lotuspond/front/src/StorageNodeInit.js
Normal 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
|
@ -37,6 +37,8 @@ type nodeInfo struct {
|
|||||||
Repo string
|
Repo string
|
||||||
ID int32
|
ID int32
|
||||||
ApiPort int32
|
ApiPort int32
|
||||||
|
|
||||||
|
Storage bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *api) Spawn() (nodeInfo, error) {
|
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 {
|
if err != nil {
|
||||||
return nodeInfo{}, err
|
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 {
|
if err != nil {
|
||||||
return nodeInfo{}, err
|
return nodeInfo{}, err
|
||||||
}
|
}
|
||||||
@ -137,6 +139,65 @@ func (api *api) TokenFor(id int32) (string, error) {
|
|||||||
return string(t), nil
|
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() {
|
func main() {
|
||||||
rpcServer := jsonrpc.NewServer()
|
rpcServer := jsonrpc.NewServer()
|
||||||
rpcServer.Register("Pond", &api{running: map[int32]runningNode{}})
|
rpcServer.Register("Pond", &api{running: map[int32]runningNode{}})
|
||||||
|
@ -67,15 +67,17 @@ func (fsr *FsRepo) Exists() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fsr *FsRepo) Init() error {
|
func (fsr *FsRepo) Init() error {
|
||||||
if _, err := os.Stat(fsr.path); err == nil {
|
exist, err := fsr.Exists()
|
||||||
return fsr.initKeystore()
|
if err != nil {
|
||||||
} else if !os.IsNotExist(err) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if exist {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
log.Infof("Initializing repo at '%s'", fsr.path)
|
log.Infof("Initializing repo at '%s'", fsr.path)
|
||||||
err := os.Mkdir(fsr.path, 0755) //nolint: gosec
|
err = os.Mkdir(fsr.path, 0755) //nolint: gosec
|
||||||
if err != nil {
|
if err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c, err := os.Create(filepath.Join(fsr.path, fsConfig))
|
c, err := os.Create(filepath.Join(fsr.path, fsConfig))
|
||||||
|
Loading…
Reference in New Issue
Block a user