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

Commit

Permalink
Merge pull request #188 from aleitner/master
Browse files Browse the repository at this point in the history
Closing issues
  • Loading branch information
aleitner committed Jul 17, 2017
2 parents 56ec512 + 6297378 commit 0d2b690
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 65 deletions.
34 changes: 27 additions & 7 deletions bin/storjshare-create.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,27 @@ const defaultConfig = JSON.parse(stripJsonComments(fs.readFileSync(
path.join(__dirname, '../example/farmer.config.json')
).toString()));

function vimIsInstalled() {
try {
execSync('which vim');
} catch (err) {
return false;
function whichEditor() {

const editors = ['vi', 'nano'];

function checkIsInstalled(editor) {
try {
execSync('which ' + editor);
} catch (err) {
return false;
}

return true;
}

for (let i = 0; i < editors.length; i++) {
if (checkIsInstalled(editors[i])) {
return editors[i];
}
}

return true;
return null;
}

storjshare_create
Expand Down Expand Up @@ -85,6 +98,13 @@ if (!storjshare_create.logdir) {
);
}

if (storjshare_create.size &&
!storjshare_create.size.match(/[0-9]+(T|M|G|K)?B/g)) {
console.error('\n Invalid storage size specified: '+
storjshare_create.size);
process.exit(1);
}

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

Expand Down Expand Up @@ -170,7 +190,7 @@ if (!storjshare_create.noedit) {
// NB: Not all distros ship with vim, so let's use GNU Nano
editor: process.platform === 'win32'
? null
: (vimIsInstalled() ? 'vim' : 'nano')
: whichEditor()
}, () => {
console.log(' ...');
console.log(` * use new config: storjshare start --config ${outfile}`);
Expand Down
157 changes: 106 additions & 51 deletions bin/storjshare-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ storjshare_status
.description('prints the status of all managed shares')
.option('-r, --remote <hostname:port>',
'hostname and optional port of the daemon')
.option('-j, --json',
'JSON formatted status of all managed shares')
.parse(process.argv);

function getColoredValue(status, value) {
Expand Down Expand Up @@ -45,59 +47,112 @@ if (storjshare_status.remote) {
}
}

// Prepare json formatted status for each share
function prepareJson(shares) {
/*jshint maxcomplexity:7 */
let json = [];

for (let i = 0; i < shares.length; i++) {
let share = shares[i];

json[i] = {};
json[i].id = share.id;

let status = '?';

switch (share.state) {
case 0:
status = 'stopped';
break;
case 1:
status = 'running';
break;
case 2:
status = 'errored';
break;
default:
status = 'unknown';
}

json[i].status = status;
json[i].configPath = share.config.storagePath;
json[i].uptime = prettyMs(share.meta.uptimeMs);
json[i].restarts = share.meta.numRestarts || 0;
json[i].peers = share.meta.farmerState.totalPeers || 0;
json[i].contracts = fixContractValue(
share.meta.farmerState.contractCount
);
json[i].dataReceivedCount = fixContractValue(
share.meta.farmerState.dataReceivedCount
);
json[i].delta = share.meta.farmerState.ntpStatus.delta;
json[i].port = share.meta.farmerState.portStatus.listenPort;
json[i].shared = share.meta.farmerState.spaceUsed;
json[i].sharedPercent = share.meta.farmerState.percentUsed;
}

return json;
}

utils.connectToDaemon(port, function(rpc, sock) {
rpc.status(function(err, shares) {
let table = new Table({
head: ['Share', 'Status', 'Uptime', 'Restarts', 'Peers',
'Contracts', 'Delta', 'Port', 'Shared'],
style: {
head: ['cyan', 'bold'],
border: []
},
colWidths: [45, 10, 10, 10, 10, 11, 9, 11, 10]
});
shares.forEach((share) => {
let status = '?';

switch (share.state) {
case 0:
status = colors.gray('stopped');
break;
case 1:
status = colors.green('running');
break;
case 2:
status = colors.red('errored');
break;
default:
status = 'unknown';
}

let portStatus = share.meta.farmerState.portStatus;
let port = getColoredValue(portStatus.connectionStatus,
portStatus.listenPort);
let connectionType = getColoredValue(portStatus.connectionStatus,
portStatus.connectionType);

let ntpStatus = getColoredValue(share.meta.farmerState.ntpStatus.status,
share.meta.farmerState.ntpStatus.delta);

let contracts = fixContractValue(share.meta.farmerState.contractCount);

table.push([
`${share.id}\n → ${share.config.storagePath}`,
status,
prettyMs(share.meta.uptimeMs),
share.meta.numRestarts || 0,
share.meta.farmerState.totalPeers || 0,
contracts,
ntpStatus,
port + '\n' + connectionType,
share.meta.farmerState.spaceUsed + '\n' +
`(${share.meta.farmerState.percentUsed}%)`
]);
});
console.log('\n' + table.toString());
if (storjshare_status.json) {
// Print out json formatted share statuses
const json = prepareJson(shares);
console.log(json);
} else {
let table = new Table({
head: ['Share', 'Status', 'Uptime', 'Restarts', 'Peers',
'Contracts', 'Delta', 'Port', 'Shared'],
style: {
head: ['cyan', 'bold'],
border: []
},
colWidths: [45, 10, 10, 10, 10, 11, 9, 11, 10]
});
shares.forEach((share) => {
let status = '?';

switch (share.state) {
case 0:
status = colors.gray('stopped');
break;
case 1:
status = colors.green('running');
break;
case 2:
status = colors.red('errored');
break;
default:
status = 'unknown';
}

let portStatus = share.meta.farmerState.portStatus;
let port = getColoredValue(portStatus.connectionStatus,
portStatus.listenPort);
let connectionType = getColoredValue(portStatus.connectionStatus,
portStatus.connectionType);

let ntpStatus = getColoredValue(share.meta.farmerState.ntpStatus.status,
share.meta.farmerState.ntpStatus.delta);

let contracts = fixContractValue(share.meta.farmerState.contractCount);

table.push([
`${share.id}\n → ${share.config.storagePath}`,
status,
prettyMs(share.meta.uptimeMs),
share.meta.numRestarts || 0,
share.meta.farmerState.totalPeers || 0,
contracts,
ntpStatus,
port + '\n' + connectionType,
share.meta.farmerState.spaceUsed + '\n' +
`(${share.meta.farmerState.percentUsed}%)`
]);
});
console.log('\n' + table.toString());
}
sock.end();
});
}, address);
8 changes: 7 additions & 1 deletion example/farmer.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
// Port to bind for RPC server, make sure this is forwarded if behind a
// NAT or firewall - otherwise Storj Share will try to punch out
"rpcPort": 4000,
// Enables NAT traversal strategies, first UPnP, then reverse HTTP tunnel
// doNotTraverseNat: true requires you to have an external ip address.
// You can use a proxy to gain an external IP address.
// doNotTraverseNat: false Enables NAT traversal strategies
// first UPnP, then reverse HTTP tunnel
// if that fails. Disable if you are public or using dynamic DNS
"doNotTraverseNat": false,
// Maximum number of tunnels to provide to the network
Expand Down Expand Up @@ -59,6 +62,9 @@
// Amount of space to lease to the network, as human readable string
// Valid units are B, KB, MB, GB, TB
"storageAllocation": "2GB",
// Max size of shards that will be accepted and stored
// Use this and make this lower if you don't have a strong internet connection
// "maxShardSize": "100MB",
// Periodically report your used and free capacity to Storj Labs to improve
// the network - no personally identifiable information is sent
"enableTelemetryReporting": true
Expand Down
9 changes: 7 additions & 2 deletions lib/api.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

const async = require('async');
const storj = require('storj-lib');
const fs = require('fs');
const {statSync, readFileSync} = require('fs');
const stripJsonComments = require('strip-json-comments');
Expand Down Expand Up @@ -71,6 +70,7 @@ class RPC {
} catch (err) {
throw new Error(err.message.toLowerCase());
}

return config;
}

Expand All @@ -82,6 +82,7 @@ class RPC {
* @see https://storj.github.io/core/FarmerInterface.html
*/
start(configPath, callback, unsafeFlag=false) {
/*jshint maxcomplexity:7 */
let config = null;

if (this.running >= cpus().length && !unsafeFlag) {
Expand All @@ -94,7 +95,11 @@ class RPC {
return callback(err);
}

const nodeId = storj.KeyPair(config.networkPrivateKey).getNodeID();
const nodeId = utils.getNodeID(config.networkPrivateKey);
if (nodeId === null) {
return callback(new Error('Invalid Private Key'));
}

const share = this.shares.get(nodeId) || {
config: config,
meta: {
Expand Down
2 changes: 1 addition & 1 deletion lib/config/farmer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const config = require('rc')('storjfarmer', {
seedList: [],
rpcAddress: '127.0.0.1',
rpcPort: 4000,
doNotTraverseNat: false,
doNotTraverseNat: true,
maxTunnels: 3,
maxConnections: 150,
tunnelGatewayRange: {
Expand Down
21 changes: 21 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ exports.validate = function(config) {
exports.validateAllocation = function(conf, callback) {
const self = this;

if (!conf.storageAllocation.match(/[0-9]+([Tt]|[Mm]|[Gg]|[Kk])?[Bb]/g)) {
return callback(
new Error('Invalid storage size specified: '+ conf.storageAllocation)
);
}

self.getFreeSpace(conf.storagePath, function(err, free) {
var allocatedSpace = bytes.parse(conf.storageAllocation);

Expand Down Expand Up @@ -237,3 +243,18 @@ exports.connectToDaemon = function(port, callback, hostname = null) {

sock.on('remote', (rpc) => callback(rpc, sock));
};

/**
* Get node Id by Private Key
* @param {String} privateKey
*/
exports.getNodeID = function(privateKey) {
let nodeId = null;
try {
nodeId = storj.KeyPair(privateKey).getNodeID();
} catch (err) {
return null;
}

return nodeId;
};
2 changes: 2 additions & 0 deletions script/farmer.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ let farmerState = {
totalPeers: 0,
lastActivity: Date.now(),
contractCount: 0,
dataReceivedCount: 0,
portStatus: {
listenPort: '...',
connectionStatus: -1,
Expand Down Expand Up @@ -99,6 +100,7 @@ function sendFarmerState() {
farmerState.portStatus.connectionStatus = getConnectionStatus();
farmerState.totalPeers = farmer.router.length;
farmerState.contractCount = farmer._contractCount || 0;
farmerState.dataReceivedCount = farmer._dataReceivedCount || 0;
process.send(farmerState);
}

Expand Down
Loading

0 comments on commit 0d2b690

Please sign in to comment.