From 712c9a8f1de11b87db8bd0814a609f34f3fd58fa Mon Sep 17 00:00:00 2001 From: Gordon Hall Date: Thu, 9 Feb 2017 15:51:36 -0500 Subject: [PATCH 1/5] cli cleanup, move daemon connection to util, allow detached shares to be started --- bin/storjshare-daemon.js | 34 +++++++++++++++---------------- bin/storjshare-destroy.js | 6 ++---- bin/storjshare-killall.js | 11 +++------- bin/storjshare-load.js | 6 ++---- bin/storjshare-logs.js | 13 +++++------- bin/storjshare-restart.js | 6 ++---- bin/storjshare-save.js | 6 ++---- bin/storjshare-start.js | 43 ++++++++++++++++++++++++++++----------- bin/storjshare-status.js | 5 ++--- bin/storjshare-stop.js | 6 ++---- bin/storjshare.js | 17 ++-------------- lib/utils.js | 17 ++++++++++++++++ package.json | 2 +- script/farmer.js | 8 ++++++-- 14 files changed, 94 insertions(+), 86 deletions(-) diff --git a/bin/storjshare-daemon.js b/bin/storjshare-daemon.js index 246144c..9adf589 100755 --- a/bin/storjshare-daemon.js +++ b/bin/storjshare-daemon.js @@ -23,22 +23,22 @@ function startDaemonRpcServer() { .listen(config.daemonRpcPort, config.daemonRpcAddress); } -function checkDaemonRpcStatus() { - utils.checkDaemonRpcStatus(config.daemonRpcPort, (isRunning) => { +utils.checkDaemonRpcStatus(config.daemonRpcPort, (isRunning) => { + if (storjshare_daemon.status) { console.info(`\n * daemon ${isRunning ? 'is' : 'is not'} running`); process.exitCode = isRunning ? 0 : 3; - }); -} - -if (storjshare_daemon.status) { - checkDaemonRpcStatus(); -} else if (!storjshare_daemon.foreground) { - daemonize(); - api.logger.pipe(logFile); - startDaemonRpcServer(); -} else { - api.logger.pipe(process.stdout); - startDaemonRpcServer(); -} - - + } else if (isRunning) { + return console.info('\n * daemon is already running'); + } else { + if (storjshare_daemon.foreground) { + console.info('\n * starting daemon in foreground\n'); + api.logger.pipe(process.stdout); + startDaemonRpcServer(); + } else { + console.info('\n * starting daemon in background'); + daemonize(); + api.logger.pipe(logFile); + startDaemonRpcServer(); + } + } +}); diff --git a/bin/storjshare-destroy.js b/bin/storjshare-destroy.js index c8616b1..23bccfa 100755 --- a/bin/storjshare-destroy.js +++ b/bin/storjshare-destroy.js @@ -3,7 +3,7 @@ 'use strict'; const config = require('../lib/config/daemon'); -const dnode = require('dnode'); +const utils = require('../lib/utils'); const storjshare_destroy = require('commander'); storjshare_destroy @@ -16,9 +16,7 @@ if (!storjshare_destroy.nodeid) { process.exit(1); } -const sock = dnode.connect(config.daemonRpcPort); - -sock.on('remote', function(rpc) { +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { rpc.destroy(storjshare_destroy.nodeid, (err) => { if (err) { console.error(`\n cannot destroy node, reason: ${err.message}`); diff --git a/bin/storjshare-killall.js b/bin/storjshare-killall.js index 8018afe..3e0dea3 100755 --- a/bin/storjshare-killall.js +++ b/bin/storjshare-killall.js @@ -3,19 +3,14 @@ 'use strict'; const config = require('../lib/config/daemon'); -const dnode = require('dnode'); +const utils = require('../lib/utils'); const storjshare_killall = require('commander'); storjshare_killall .description('destroys all running shares and stop daemon') .parse(process.argv); -const sock = dnode.connect(config.daemonRpcPort); - -sock.on('end', function() { - console.info('\n * daemon has stopped'); -}); - -sock.on('remote', function(rpc) { +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { + sock.on('end', () => console.info('\n * daemon has stopped')); rpc.killall(() => sock.end()); }); diff --git a/bin/storjshare-load.js b/bin/storjshare-load.js index 24d0b5e..b3e1dcc 100755 --- a/bin/storjshare-load.js +++ b/bin/storjshare-load.js @@ -5,7 +5,7 @@ const os = require('os'); const path = require('path'); const config = require('../lib/config/daemon'); -const dnode = require('dnode'); +const utils = require('../lib/utils'); const storjshare_load = require('commander'); storjshare_load @@ -25,9 +25,7 @@ if (!path.isAbsolute(storjshare_load.snapshot)) { storjshare_load.snapshot); } -const sock = dnode.connect(config.daemonRpcPort); - -sock.on('remote', function(rpc) { +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { rpc.load(storjshare_load.snapshot, (err) => { if (err) { console.error(`\n cannot load snapshot, reason: ${err.message}`); diff --git a/bin/storjshare-logs.js b/bin/storjshare-logs.js index 02f6068..907b602 100755 --- a/bin/storjshare-logs.js +++ b/bin/storjshare-logs.js @@ -3,7 +3,6 @@ 'use strict'; const config = require('../lib/config/daemon'); -const dnode = require('dnode'); const utils = require('../lib/utils'); const {Tail} = require('tail'); const colors = require('colors/safe'); @@ -67,14 +66,12 @@ function prettyLog(line) { console.log(output); } -const sock = dnode.connect(config.daemonRpcPort); - -process.on('exit', () => { - sock.end(); - process.exit(0); -}); +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { + process.on('exit', () => { + sock.end(); + process.exit(0); + }); -sock.on('remote', function(rpc) { rpc.status((err, shares) => { if (err) { console.error(`\n cannot get status, reason: ${err.message}`); diff --git a/bin/storjshare-restart.js b/bin/storjshare-restart.js index 8ee0c5b..818479b 100755 --- a/bin/storjshare-restart.js +++ b/bin/storjshare-restart.js @@ -3,7 +3,7 @@ 'use strict'; const config = require('../lib/config/daemon'); -const dnode = require('dnode'); +const utils = require('../lib/utils'); const storjshare_restart = require('commander'); storjshare_restart @@ -17,9 +17,7 @@ if (!storjshare_restart.nodeid && !storjshare_restart.all) { process.exit(1); } -const sock = dnode.connect(config.daemonRpcPort); - -sock.on('remote', function(rpc) { +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { if (storjshare_restart.all) { console.info('\n * restarting all managed shares'); } diff --git a/bin/storjshare-save.js b/bin/storjshare-save.js index 12da209..4edae46 100755 --- a/bin/storjshare-save.js +++ b/bin/storjshare-save.js @@ -5,7 +5,7 @@ const os = require('os'); const path = require('path'); const config = require('../lib/config/daemon'); -const dnode = require('dnode'); +const utils = require('../lib/utils'); const storjshare_save = require('commander'); storjshare_save @@ -25,9 +25,7 @@ if (!path.isAbsolute(storjshare_save.snapshot)) { storjshare_save.snapshot); } -const sock = dnode.connect(config.daemonRpcPort); - -sock.on('remote', function(rpc) { +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { rpc.save(storjshare_save.snapshot, (err) => { if (err) { console.error(`\n cannot save snapshot, reason: ${err.message}`); diff --git a/bin/storjshare-start.js b/bin/storjshare-start.js index 0cb0f77..39d65df 100755 --- a/bin/storjshare-start.js +++ b/bin/storjshare-start.js @@ -2,7 +2,8 @@ 'use strict'; -const dnode = require('dnode'); +const {spawn} = require('child_process'); +const utils = require('../lib/utils'); const path = require('path'); const config = require('../lib/config/daemon'); const storjshare_start = require('commander'); @@ -10,6 +11,7 @@ const storjshare_start = require('commander'); storjshare_start .description('starts a new network share') .option('-c, --config ', 'specify the configuration path') + .option('-d, --detached', 'run share without management from daemon') .parse(process.argv); if (!storjshare_start.config) { @@ -20,15 +22,32 @@ if (!storjshare_start.config) { const configPath = path.isAbsolute(storjshare_start.config) ? path.normalize(storjshare_start.config) : path.join(process.cwd(), storjshare_start.config); -const sock = dnode.connect(config.daemonRpcPort); - -sock.on('remote', function(rpc) { - rpc.start(configPath, (err) => { - if (err) { - console.error(`\n failed to start share, reason: ${err.message}`); - return sock.end(); - } - console.info(`\n * starting share with config at ${configPath}`); - sock.end(); + +if (storjshare_start.detached) { + runDetachedShare(); +} else { + runManagedShare(); +} + +function runDetachedShare() { + const scriptPath = path.join(__dirname, '../script/farmer.js'); + const shareProc = spawn(scriptPath, ['--config', configPath]); + + process.stdin.pipe(shareProc.stdin); + shareProc.stdout.pipe(process.stdout); + shareProc.stderr.pipe(process.stderr); + shareProc.on('exit', (code) => process.exit(code)) +} + +function runManagedShare() { + utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { + rpc.start(configPath, (err) => { + if (err) { + console.error(`\n failed to start share, reason: ${err.message}`); + return sock.end(); + } + console.info(`\n * starting share with config at ${configPath}`); + sock.end(); + }); }); -}); +} diff --git a/bin/storjshare-status.js b/bin/storjshare-status.js index d41aa6c..332f028 100755 --- a/bin/storjshare-status.js +++ b/bin/storjshare-status.js @@ -4,9 +4,8 @@ const prettyMs = require('pretty-ms'); const config = require('../lib/config/daemon'); -const dnode = require('dnode'); +const utils = require('../lib/utils'); const Table = require('cli-table'); -const sock = dnode.connect(config.daemonRpcPort); const colors = require('colors/safe'); const storjshare_status = require('commander'); @@ -14,7 +13,7 @@ storjshare_status .description('prints the status of all managed shares') .parse(process.argv); -sock.on('remote', function(rpc) { +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { rpc.status(function(err, shares) { let table = new Table({ head: ['Share', 'Status', 'Uptime', 'Restarts', 'Peers', 'Shared'], diff --git a/bin/storjshare-stop.js b/bin/storjshare-stop.js index 2808d91..415f1f4 100755 --- a/bin/storjshare-stop.js +++ b/bin/storjshare-stop.js @@ -3,7 +3,7 @@ 'use strict'; const config = require('../lib/config/daemon'); -const dnode = require('dnode'); +const utils = require('../lib/utils'); const storjshare_stop = require('commander'); storjshare_stop @@ -16,9 +16,7 @@ if (!storjshare_stop.nodeid) { process.exit(1); } -const sock = dnode.connect(config.daemonRpcPort); - -sock.on('remote', function(rpc) { +utils.connectToDaemon(config.daemonRpcPort, function(rpc, sock) { rpc.stop(storjshare_stop.nodeid, (err) => { if (err) { console.error(`\n cannot stop node, reason: ${err.message}`); diff --git a/bin/storjshare.js b/bin/storjshare.js index e4718d8..3958212 100755 --- a/bin/storjshare.js +++ b/bin/storjshare.js @@ -25,18 +25,5 @@ storjshare .command('load', 'load a snapshot of previously managed shares') .command('destroy', 'kills the farming node') .command('killall', 'kills all shares and stops the daemon') - .command('daemon', 'starts the daemon'); - -if (!['daemon'].includes(process.argv[2])) { - utils.checkDaemonRpcStatus(config.daemonRpcPort, (isRunning) => { - if (isRunning) { - setTimeout(() => storjshare.parse(process.argv), TIME_WAIT_IF_STARTED); - } else { - console.info('\n * daemon is not running, starting...'); - fork(path.join(__dirname, 'storjshare-daemon.js'), []); - setTimeout(() => storjshare.parse(process.argv), TIME_WAIT_AFTER_START); - } - }); -} else { - storjshare.parse(process.argv); -} + .command('daemon', 'starts the daemon') + .parse(process.argv); diff --git a/lib/utils.js b/lib/utils.js index 977feac..d5bde4e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -4,6 +4,7 @@ 'use strict'; +const dnode = require('dnode'); const net = require('net'); const fs = require('fs'); const storj = require('storj-lib'); @@ -162,3 +163,19 @@ exports.checkDaemonRpcStatus = function(port, callback) { callback(true); }); }; + +/** + * Connects to the daemon and callback with rpc + * @param {Number} port + * @param {Function} callback + */ +exports.connectToDaemon = function(port, callback) { + const sock = dnode.connect(port); + + sock.on('error', function(err) { + process.exitCode = 1; + console.error('\n daemon is not running, try: storjshare daemon'); + }); + + sock.on('remote', (rpc) => callback(rpc, sock)); +}; diff --git a/package.json b/package.json index 54b19da..78ee441 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "storjshare-daemon", - "version": "2.3.0", + "version": "2.4.0", "description": "daemon + process manager for sharing space on the storj network", "main": "index.js", "bin": { diff --git a/script/farmer.js b/script/farmer.js index 86081b7..f83a2f2 100755 --- a/script/farmer.js +++ b/script/farmer.js @@ -8,6 +8,7 @@ const Logger = require('kad-logger-json'); const Telemetry = require('storj-telemetry-reporter'); const config = JSON.parse(JSON.stringify(require('../lib/config/farmer'))); const bytes = require('bytes'); +const processIsManaged = typeof process.send === 'function'; let spaceAllocation = bytes.parse(config.storageAllocation); let farmerState = { @@ -71,10 +72,13 @@ function sendTelemetryReport() { } updatePercentUsed(); -sendFarmerState(); -setInterval(sendFarmerState, 10 * 1000); // Update state every 10 secs setInterval(updatePercentUsed, 10 * 60 * 1000); // Update space every 10 mins +if (processIsManaged) { + sendFarmerState(); + setInterval(sendFarmerState, 10 * 1000); // Update state every 10 secs +} + if (config.enableTelemetryReporting) { setInterval(sendTelemetryReport, 10 * 60 * 1000); } From 25d55f3b225ce843488d83f3966fe5c555234eaa Mon Sep 17 00:00:00 2001 From: Gordon Hall Date: Thu, 9 Feb 2017 16:03:39 -0500 Subject: [PATCH 2/5] add tests for new util --- test/utils.unit.js | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/utils.unit.js b/test/utils.unit.js index 418a1a3..d27494c 100644 --- a/test/utils.unit.js +++ b/test/utils.unit.js @@ -222,4 +222,44 @@ describe('module:utils', function() { }); + describe('#connectToDaemon', function() { + + it('should set the process exit code and log error', function(done) { + let socket = new EventEmitter(); + let error = sinon.stub(console, 'error'); + let _utils = proxyquire('../lib/utils', { + dnode: { + connect: () => socket + } + }); + _utils.connectToDaemon(45015, () => null); + setImmediate(() => { + socket.emit('error', new Error('Failed to connect')); + setImmediate(() => { + error.restore(); + expect(process.exitCode).to.equal(1); + process.exitCode = 0; + done(); + }); + }); + }); + + it('should callback with remote object and socket', function(done) { + let socket = new EventEmitter(); + let rpc = {}; + let _utils = proxyquire('../lib/utils', { + dnode: { + connect: () => socket + } + }); + _utils.connectToDaemon(45015, (_rpc, sock) => { + expect(_rpc).to.equal(rpc); + expect(sock).to.equal(socket); + done(); + }); + setImmediate(() => socket.emit('remote', rpc)); + }); + + }); + }); From ef157b152fa5878a0dfc2ba0a9371c4a41d29b7a Mon Sep 17 00:00:00 2001 From: Gordon Hall Date: Thu, 9 Feb 2017 16:09:27 -0500 Subject: [PATCH 3/5] remove extraneous vars --- bin/storjshare.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/bin/storjshare.js b/bin/storjshare.js index 3958212..e0d7dcf 100755 --- a/bin/storjshare.js +++ b/bin/storjshare.js @@ -2,17 +2,10 @@ 'use strict'; -const config = require('../lib/config/daemon'); const storjshare = require('commander'); -const {fork} = require('child_process'); -const path = require('path'); -const utils = require('../lib/utils'); const {version} = require('../package'); const {software: core, protocol} = require('storj-lib').version; -const TIME_WAIT_IF_STARTED = 1000; -const TIME_WAIT_AFTER_START = 6000; - storjshare .version(`\n * daemon: ${version}, core: ${core}, protocol: ${protocol}`) .command('start', 'start a farming node') From b5c0e8a7231b69d60486d04f7f67e962538c1de9 Mon Sep 17 00:00:00 2001 From: Gordon Hall Date: Thu, 9 Feb 2017 16:10:24 -0500 Subject: [PATCH 4/5] fix linting errors --- bin/storjshare-start.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/bin/storjshare-start.js b/bin/storjshare-start.js index 39d65df..696017d 100755 --- a/bin/storjshare-start.js +++ b/bin/storjshare-start.js @@ -23,12 +23,6 @@ const configPath = path.isAbsolute(storjshare_start.config) ? path.normalize(storjshare_start.config) : path.join(process.cwd(), storjshare_start.config); -if (storjshare_start.detached) { - runDetachedShare(); -} else { - runManagedShare(); -} - function runDetachedShare() { const scriptPath = path.join(__dirname, '../script/farmer.js'); const shareProc = spawn(scriptPath, ['--config', configPath]); @@ -36,7 +30,7 @@ function runDetachedShare() { process.stdin.pipe(shareProc.stdin); shareProc.stdout.pipe(process.stdout); shareProc.stderr.pipe(process.stderr); - shareProc.on('exit', (code) => process.exit(code)) + shareProc.on('exit', (code) => process.exit(code)); } function runManagedShare() { @@ -51,3 +45,11 @@ function runManagedShare() { }); }); } + +if (storjshare_start.detached) { + runDetachedShare(); +} else { + runManagedShare(); +} + + From 48101ec73aeb57571b5c2bc94cd4a0994ea3d884 Mon Sep 17 00:00:00 2001 From: Gordon Hall Date: Thu, 9 Feb 2017 16:31:27 -0500 Subject: [PATCH 5/5] remove unused var --- lib/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index d5bde4e..0a64208 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -172,7 +172,7 @@ exports.checkDaemonRpcStatus = function(port, callback) { exports.connectToDaemon = function(port, callback) { const sock = dnode.connect(port); - sock.on('error', function(err) { + sock.on('error', function() { process.exitCode = 1; console.error('\n daemon is not running, try: storjshare daemon'); });