Skip to content
This repository was archived by the owner on Oct 30, 2018. It is now read-only.

Commit c0bf156

Browse files
author
Gordon Hall
committed
more options in storjshare-create, add --all flag to restart, extend time to wait for daemon, update readme
1 parent bb7c328 commit c0bf156

7 files changed

+156
-42
lines changed

README.md

+17-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use or inclusion in other packages.
1414
Make sure you have the following prerequisites installed:
1515

1616
* Git
17-
* Node.js LTS
17+
* Node.js LTS (6.9.x)
1818
* NPM
1919
* Python 2.7
2020
* GCC/G++/Make
@@ -109,15 +109,25 @@ You can also get more detailed help for a specific command.
109109
```
110110
storjshare help create
111111
112-
Usage: storjshare-create [options]
112+
Usage: storjshare-create [options]
113+
114+
generates a new share configuration
113115
114116
Options:
115117
116118
-h, --help output usage information
117-
-a, --sjcx <addr> specify the sjcx address (required)
118-
-s, --storage <path> specify the storage path
119-
-l, --logfile <path> specify the logfile path
120-
-k, --privkey <privkey> specify the private key
119+
--sjcx <addr> specify the sjcx address (required)
120+
--key <privkey> specify the private key
121+
--storage <path> specify the storage path
122+
--size <maxsize> specify share size (ex: 10GB, 1TB)
123+
--rpcport <port> specify the rpc port number
124+
--rpcaddress <addr> specify the rpc address
125+
--maxtunnels <tunnels> specify the max tunnels
126+
--tunnelportmin <port> specify min gateway port
127+
--tunnelportmax <port> specify max gateway port
128+
--manualforwarding do not use nat traversal strategies
129+
--logfile <path> specify the logfile path
130+
--noedit do not open generated config in editor
121131
-o, --outfile <writepath> write config to path
122132
```
123133

@@ -235,7 +245,7 @@ Now that you have Storj Share installed, use the `create` command to generate
235245
your configuration.
236246

237247
```
238-
storjshare create -k 4154e8... -a 1K1rPg... -s <datadir> -o <writepath>
248+
storjshare create --key 4154e8... --sjcx 1K1rPg... --storage <datadir> -o <writepath>
239249
```
240250

241251
This will generate your configuration file given the parameters you passed in,

bin/storjshare-create.js

+71-20
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,51 @@
22

33
'use strict';
44

5+
const blindfold = require('blindfold');
56
const editor = require('editor');
67
const {tmpdir, homedir} = require('os');
78
const fs = require('fs');
89
const storj = require('storj-lib');
910
const path = require('path');
1011
const mkdirp = require('mkdirp');
11-
const config = require('../lib/config/daemon');
12+
const stripJsonComments = require('strip-json-comments');
1213
const storjshare_create = require('commander');
1314

15+
const defaultConfig = JSON.parse(stripJsonComments(fs.readFileSync(
16+
path.join(__dirname, '../example/farmer.config.json')
17+
).toString()));
18+
1419
storjshare_create
1520
.description('generates a new share configuration')
16-
.option('-a, --sjcx <addr>', 'specify the sjcx address (required)')
17-
.option('-s, --storage <path>', 'specify the storage path')
18-
.option('-l, --logfile <path>', 'specify the logfile path')
19-
.option('-k, --privkey <privkey>', 'specify the private key')
21+
.option('--sjcx <addr>', 'specify the sjcx address (required)')
22+
.option('--key <privkey>', 'specify the private key')
23+
.option('--storage <path>', 'specify the storage path')
24+
.option('--size <maxsize>', 'specify share size (ex: 10GB, 1TB)')
25+
.option('--rpcport <port>', 'specify the rpc port number')
26+
.option('--rpcaddress <addr>', 'specify the rpc address')
27+
.option('--maxtunnels <tunnels>', 'specify the max tunnels')
28+
.option('--tunnelportmin <port>', 'specify min gateway port')
29+
.option('--tunnelportmax <port>', 'specify max gateway port')
30+
.option('--manualforwarding', 'do not use nat traversal strategies')
31+
.option('--logfile <path>', 'specify the logfile path')
32+
.option('--noedit', 'do not open generated config in editor')
2033
.option('-o, --outfile <writepath>', 'write config to path')
21-
.option('-n, --noedit', 'do not open generated config in editor')
2234
.parse(process.argv);
2335

2436
if (!storjshare_create.sjcx) {
2537
console.error('\n no payment address was given, try --help');
2638
process.exit(1);
2739
}
2840

29-
if (!storjshare_create.privkey) {
30-
storjshare_create.privkey = storj.KeyPair().getPrivateKey();
41+
if (!storjshare_create.key) {
42+
storjshare_create.key = storj.KeyPair().getPrivateKey();
3143
}
3244

3345
if (!storjshare_create.storage) {
3446
storjshare_create.storage = path.join(
3547
homedir(),
3648
'.config/storjshare/shares',
37-
storj.KeyPair(storjshare_create.privkey).getNodeID()
49+
storj.KeyPair(storjshare_create.key).getNodeID()
3850
);
3951
mkdirp.sync(storjshare_create.storage);
4052
}
@@ -43,33 +55,72 @@ if (!storjshare_create.logfile) {
4355
storjshare_create.logfile = path.join(
4456
homedir(),
4557
'.config/storjshare/logs',
46-
storj.KeyPair(storjshare_create.privkey).getNodeID() + '.log'
58+
storj.KeyPair(storjshare_create.key).getNodeID() + '.log'
4759
);
4860
}
4961

5062
if (!storjshare_create.outfile) {
5163
storjshare_create.outfile = path.join(
5264
tmpdir(),
53-
storj.KeyPair(storjshare_create.privkey).getNodeID() + '.json'
65+
storj.KeyPair(storjshare_create.key).getNodeID() + '.json'
5466
);
5567
}
5668

5769
let exampleConfigPath = path.join(__dirname, '../example/farmer.config.json');
5870
let exampleConfigString = fs.readFileSync(exampleConfigPath).toString();
5971

60-
function replaceEmptyConfig(prop, value) {
61-
value = value.split('\\').join('\\\\'); // NB: Hack windows paths into JSON
72+
function getDefaultConfigValue(prop) {
73+
return {
74+
value: blindfold(defaultConfig, prop),
75+
type: typeof blindfold(defaultConfig, prop)
76+
};
77+
}
78+
79+
function replaceDefaultConfigValue(prop, value) {
80+
let defaultValue = getDefaultConfigValue(prop);
81+
82+
function toStringReplace(prop, value, type) {
83+
switch (type) {
84+
case 'string':
85+
value = value.split('\\').join('\\\\'); // NB: Hack windows paths
86+
return`"${prop}": "${value}"`;
87+
case 'boolean':
88+
case 'number':
89+
return `"${prop}": ${value}`;
90+
default:
91+
return '';
92+
}
93+
}
94+
95+
prop = prop.split('.').pop();
6296
exampleConfigString = exampleConfigString.replace(
63-
`"${prop}": ""`,
64-
`"${prop}": "${value}"`
97+
toStringReplace(prop, defaultValue.value, defaultValue.type),
98+
toStringReplace(prop, value, defaultValue.type)
6599
);
66100
}
67101

68-
replaceEmptyConfig('paymentAddress', storjshare_create.sjcx);
69-
replaceEmptyConfig('networkPrivateKey', storjshare_create.privkey);
70-
replaceEmptyConfig('storagePath', path.normalize(storjshare_create.storage));
71-
replaceEmptyConfig('loggerOutputFile',
72-
path.normalize(storjshare_create.logfile));
102+
replaceDefaultConfigValue('paymentAddress', storjshare_create.sjcx);
103+
replaceDefaultConfigValue('networkPrivateKey', storjshare_create.key);
104+
replaceDefaultConfigValue('storagePath',
105+
path.normalize(storjshare_create.storage));
106+
replaceDefaultConfigValue('loggerOutputFile',
107+
path.normalize(storjshare_create.logfile));
108+
109+
const optionalReplacements = [
110+
{ option: storjshare_create.size, name: 'storageAllocation' },
111+
{ option: storjshare_create.rpcaddress, name: 'rpcAddress' },
112+
{ option: storjshare_create.rpcport, name: 'rpcPort' },
113+
{ option: storjshare_create.maxtunnels, name: 'maxTunnels' },
114+
{ option: storjshare_create.tunnelportmin, name: 'tunnelGatewayRange.min' },
115+
{ option: storjshare_create.tunnelportmax, name: 'tunnelGatewayRange.max' },
116+
{ option: storjshare_create.manualforwarding, name: 'doNotTraverseNat' }
117+
];
118+
119+
optionalReplacements.forEach((repl) => {
120+
if (repl.option) {
121+
replaceDefaultConfigValue(repl.name, repl.option);
122+
}
123+
});
73124

74125
let outfile = path.isAbsolute(storjshare_create.outfile) ?
75126
path.normalize(storjshare_create.outfile) :

bin/storjshare-restart.js

+14-3
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,33 @@ const storjshare_restart = require('commander');
99
storjshare_restart
1010
.description('restarts the running share specified')
1111
.option('-i, --nodeid <nodeid>', 'id of the running share')
12+
.option('-a, --all', 'restart all running shares')
1213
.parse(process.argv);
1314

14-
if (!storjshare_restart.nodeid) {
15+
if (!storjshare_restart.nodeid && !storjshare_restart.all) {
1516
console.error('\n missing node id, try --help');
1617
process.exit(1);
1718
}
1819

1920
const sock = dnode.connect(config.daemonRpcPort);
2021

2122
sock.on('remote', function(rpc) {
22-
rpc.restart(storjshare_restart.nodeid, (err) => {
23+
if (storjshare_restart.all) {
24+
console.info('\n * restarting all managed shares');
25+
}
26+
27+
rpc.restart(storjshare_restart.nodeid || '*', (err) => {
2328
if (err) {
2429
console.error(`\n cannot restart node, reason: ${err.message}`);
2530
return sock.end();
2631
}
27-
console.info(`\n * share ${storjshare_restart.nodeid} restarted`);
32+
33+
if (storjshare_restart.nodeid) {
34+
console.info(`\n * share ${storjshare_restart.nodeid} restarted`);
35+
} else {
36+
console.info('\n * all shares restarted successfully');
37+
}
38+
2839
sock.end();
2940
});
3041
});

bin/storjshare.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ if (!['daemon'].includes(process.argv[2])) {
2626
sock.once('error', function() {
2727
console.info('\n * daemon is not running, starting...');
2828
fork(path.join(__dirname, 'storjshare-daemon.js'), []);
29-
setTimeout(() => storjshare.parse(process.argv), 2000);
29+
setTimeout(() => storjshare.parse(process.argv), 4000);
3030
});
3131

3232
sock.once('connect', function() {

lib/api.js

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22

3+
const async = require('async');
34
const storj = require('storj-lib');
45
const fs = require('fs');
56
const {statSync, readFileSync} = require('fs');
@@ -20,6 +21,7 @@ class RPC {
2021
constructor(options={}) {
2122
this.logger = new JsonLogger(options.logVerbosity);
2223
this.shares = new Map();
24+
this._restarts = {};
2325
}
2426

2527
/**
@@ -49,11 +51,11 @@ class RPC {
4951
*/
5052
start(configPath, callback) {
5153
const self = this;
54+
self._restarts[configPath] = self._restarts[configPath] || 0;
5255
let share = {
5356
config: null,
5457
meta: {
5558
uptimeMs: 0,
56-
numRestarts: 0,
5759
farmerState: {}
5860
},
5961
process: null,
@@ -124,14 +126,15 @@ class RPC {
124126

125127
// NB: Listen for exits and restart the share if not stopped manually
126128
share.process.on('exit', (code, signal) => {
127-
let maxRestartsReached = share.meta.numRestarts >= RPC.MAX_RESTARTS;
129+
let totalRestarts = self._restarts[configPath];
130+
let maxRestartsReached = totalRestarts >= RPC.MAX_RESTARTS;
128131
share.readyState = RPC.SHARE_STOPPED;
129132

130133
self._log(`share ${nodeId} exited with code ${code}`);
131134
clearInterval(uptimeCounter);
132135

133136
if (signal !== 'SIGINT' && !maxRestartsReached) {
134-
share.meta.numRestarts++;
137+
self._restarts[configPath]++;
135138
self.restart(nodeId, () => null);
136139
}
137140
});
@@ -173,6 +176,15 @@ class RPC {
173176
*/
174177
restart(nodeId, callback) {
175178
this._log(`attempting to restart share with node id ${nodeId}`);
179+
180+
if (nodeId === '*') {
181+
return async.eachSeries(
182+
this.shares.keys(),
183+
(nodeId, next) => this.restart(nodeId, next),
184+
callback
185+
);
186+
}
187+
176188
this.stop(nodeId, () => {
177189
this.start(this.shares.get(nodeId).path, callback);
178190
});
@@ -187,11 +199,12 @@ class RPC {
187199
* @param {RPC~statusCallback}
188200
*/
189201
status(callback) {
190-
this._log(`got status query`);
191-
192-
let statuses = [];
202+
const self = this;
203+
const statuses = [];
193204

205+
this._log(`got status query`);
194206
this.shares.forEach((share, nodeId) => {
207+
share.meta.numRestarts = self._restarts[share.path];
195208
statuses.push({
196209
id: nodeId,
197210
config: share.config,
@@ -234,7 +247,10 @@ class RPC {
234247
return callback(new Error(`share ${nodeId} is not running`));
235248
}
236249

237-
this.shares.get(nodeId).process.kill('SIGINT');
250+
let share = this.shares.get(nodeId);
251+
this._restarts[share.path] = 0;
252+
253+
share.process.kill('SIGINT');
238254
this.shares.delete(nodeId);
239255
callback(null);
240256
}

package.json

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
{
22
"name": "storjshare-daemon",
3-
"version": "2.0.1",
3+
"version": "2.0.2",
44
"description": "daemon + process manager for sharing space on the storj network",
55
"main": "index.js",
66
"bin": {
7-
"storjshare": "bin/storjshare.js"
7+
"storjshare": "bin/storjshare.js",
8+
"storjshare-start": "bin/storjshare-start.js",
9+
"storjshare-stop": "bin/storjshare-stop.js",
10+
"storjshare-restart": "bin/storjshare-restart.js",
11+
"storjshare-status": "bin/storjshare-status.js",
12+
"storjshare-logs": "bin/storjshare-logs.js",
13+
"storjshare-killall": "bin/storjshare-killall.js",
14+
"storjshare-destroy": "bin/storjshare-destroy.js",
15+
"storjshare-daemon": "bin/storjshare-daemon.js",
16+
"storjshare-create": "bin/storjshare-create.js"
817
},
918
"directories": {
1019
"test": "test",
@@ -40,6 +49,8 @@
4049
},
4150
"homepage": "https://github.com/storj/storjshare-daemon#readme",
4251
"dependencies": {
52+
"async": "^2.1.4",
53+
"blindfold": "0.0.1",
4354
"bytes": "^2.4.0",
4455
"cli-table": "^0.3.1",
4556
"colors": "^1.1.2",

0 commit comments

Comments
 (0)