Browse Source

merged changes in shepherd

pkg_automation_electrum
michal maxian 8 years ago
parent
commit
c74da5e491
  1. 2
      README.md
  2. BIN
      assets/bin/osx/iguana
  3. BIN
      assets/bin/osx/komodo-cli
  4. BIN
      assets/bin/osx/komodod
  5. 0
      assets/bin/osx/libgcc_s.1.dylib
  6. 0
      assets/bin/osx/libgomp.1.dylib
  7. 0
      assets/bin/osx/libstdc++.6.dylib
  8. 2
      gui/EasyDEX-GUI
  9. 10
      gui/init.js
  10. 38
      gui/loading.js
  11. 91
      main.js
  12. 30
      private/kmdcli.js
  13. 342
      routes/cache.js
  14. 511
      routes/shepherd.js

2
README.md

@ -15,7 +15,7 @@ cd ../../
Install Agama App
```shell
cd iguana
cd Agama
npm install
```

BIN
assets/bin/osx/iguana

Binary file not shown.

BIN
assets/bin/osx/komodo-cli

Binary file not shown.

BIN
assets/bin/osx/komodod

Binary file not shown.

0
assets/bin/osx/libgcc_s.1.dylib

0
assets/bin/osx/libgomp.1.dylib

0
assets/bin/osx/libstdc++.6.dylib

2
gui/EasyDEX-GUI

@ -1 +1 @@
Subproject commit 59ff487c1f068700d381b07a4e873d2ab9d7c86d
Subproject commit d48b6500f4eff5e9a1d55490d11e5f1502f647af

10
gui/init.js

@ -20,14 +20,18 @@ $(document).ready(function() {
function startcheck() {
portcheck = setInterval(function(){
Iguana_activehandle().then(function(result){
Iguana_activehandle(appConf).then(function(result){
console.log(result);
if (result !== 'error') {
stopcheck();
StartIguana_Cache();
if (appConf && appConf.forks && appConf.forks.basilisk) {
StartIguana_Cache();
}
$('#loading_status_text').text('Connecting to Basilisk Network...');
EDEX_DEXgetinfoAll(appConf.skipBasiliskNetworkCheck, appConf.minNotaries);
EDEX_DEXgetinfoAll(appConf.skipBasiliskNetworkCheck, appConf.minNotaries, appConf);
}
})
//var check = Iguana_activehandle();

38
gui/loading.js

@ -12,13 +12,13 @@ function IguanaAJAX(url, ajax_data, timeout) {
});
}
function Iguana_activehandle(callback) {
function Iguana_activehandle(appConf) {
return new Promise((resolve) => {
var ajax_data = {
'agent': 'SuperNET',
'method': 'activehandle'
},
AjaxOutputData = IguanaAJAX('http://127.0.0.1:' + config.iguanaPort, ajax_data).done(function(data) {
AjaxOutputData = IguanaAJAX('http://127.0.0.1:' + appConf.iguanaCorePort, ajax_data).done(function(data) {
//$('#loading_status_text').text('Retrieving active handle...');
//console.log(AjaxOutputData.responseText);
AjaxOutputData = JSON.parse(AjaxOutputData.responseText)
@ -66,7 +66,10 @@ function StartIguana() {
}
function StartIguana_Cache() {
ajax_data = { 'name': 'IGUANA_CACHE' };
var ajax_data = {
'mode': 'basilisk',
'coin': 'all'
};
var start_iguana_cache= $.ajax({
type: 'POST',
data: JSON.stringify(ajax_data),
@ -108,30 +111,7 @@ function GetAppConf(cb) { // get iguana app conf
return data;
}
function EDEX_DEXnotarychains() {
return new Promise((resolve) => {
var ajax_data = {
'agent': 'dpow',
'method': 'notarychains'
},
AjaxOutputData = IguanaAJAX('http://127.0.0.1:' + config.iguanaPort, ajax_data).done(function(data) {
//console.log(AjaxOutputData.responseText);
AjaxOutputData = JSON.parse(AjaxOutputData.responseText);
//console.log(AjaxOutputData);
resolve(AjaxOutputData);
})
.fail(function(xhr, textStatus, error) {
// handle request failures
console.log(xhr.statusText);
if ( xhr.readyState == 0 ) {
}
console.log(textStatus);
console.log(error);
});
});
}
function EDEX_DEXgetinfoAll(skip, minNotaries) {
function EDEX_DEXgetinfoAll(skip, minNotaries, appConf) {
const remote = require('electron').remote;
var window = remote.getCurrentWindow();
@ -143,7 +123,7 @@ function EDEX_DEXgetinfoAll(skip, minNotaries) {
'method': 'notarychains'
},
tmp_index = 0,
get_dex_notarychains = IguanaAJAX('http://127.0.0.1:' + config.iguanaPort, ajax_data, 10000).done(function(data) {
get_dex_notarychains = IguanaAJAX('http://127.0.0.1:' + appConf.iguanaCorePort, ajax_data, 10000).done(function(data) {
get_dex_notarychains = JSON.parse(get_dex_notarychains.responseText);
if (minNotaries > get_dex_notarychains.length) { // if config value exceeds total num of notaries
minNotaries = get_dex_notarychains.length;
@ -163,7 +143,7 @@ function EDEX_DEXgetinfoAll(skip, minNotaries) {
console.log(ajax_data);
if (coin_value !== 'MESH' || coin_value !== 'CEAL') {
var getinfo_each_chain = IguanaAJAX('http://127.0.0.1:' + config.iguanaPort, ajax_data).done(function(data) {
var getinfo_each_chain = IguanaAJAX('http://127.0.0.1:' + appConf.iguanaCorePort, ajax_data).done(function(data) {
getinfo_each_chain = JSON.parse(getinfo_each_chain.responseText);
console.log(getinfo_each_chain);

91
main.js

@ -21,13 +21,18 @@ var express = require('express'),
pm2 = require('pm2'),
cluster = require('cluster'),
numCPUs = require('os').cpus().length,
coincli = require('./private/coincli.js'),
//coincli = require('./private/coincli.js'),
ipc = require('electron').ipcMain;
Promise = require('bluebird');
app.setName('Agama');
app.setVersion('0.1.6.2e-beta');
const appBasicInfo = {
name: 'Agama',
version: '0.1.6.2e-beta'
};
app.setName(appBasicInfo.name);
app.setVersion(appBasicInfo.version);
if (os.platform() === 'linux') {
process.env.ELECTRON_RUN_AS_NODE = true;
@ -36,11 +41,28 @@ if (os.platform() === 'linux') {
// GUI APP settings and starting gui on address http://120.0.0.1:17777
var shepherd = require('./routes/shepherd'),
guiapp = express(),
appConfig = shepherd.loadLocalConfig(); // load app config
guiapp = express();
shepherd.writeLog('app init');
shepherd.writeLog('app info: ' + appBasicInfo.name + ' ' + appBasicInfo.version);
shepherd.writeLog('sys info:');
shepherd.writeLog('totalmem_readable: ' + formatBytes(os.totalmem()));
shepherd.writeLog('arch: ' + os.arch());
shepherd.writeLog('cpu: ' + os.cpus()[0].model);
shepherd.writeLog('cpu_cores: ' + os.cpus().length);
shepherd.writeLog('platform: ' + os.platform());
shepherd.writeLog('os_release: ' + os.release());
shepherd.writeLog('os_type: ' + os.type());
var appConfig = shepherd.loadLocalConfig(); // load app config
shepherd.writeLog('app started in ' + (appConfig.dev ? 'dev mode' : ' user mode'));
shepherd.setConfKMD();
if (appConfig.killIguanaOnStart) {
var iguanaGrep;
if (os.platform() === 'darwin') {
iguanaGrep = "ps -p $(ps -A | grep -m1 iguana | awk '{print $1}') | grep -i iguana";
}
@ -53,24 +75,28 @@ if (appConfig.killIguanaOnStart) {
exec(iguanaGrep, function(error, stdout, stderr) {
if (stdout.indexOf('iguana') > -1) {
console.log('found another iguana process(es)');
var pkillCmd = os.platform() === 'win32' ? 'taskkill /f /im iguana.exe' : 'pkill -9 iguana';
shepherd.writeLog('found another iguana process(es)');
const pkillCmd = os.platform() === 'win32' ? 'taskkill /f /im iguana.exe' : 'pkill -15 iguana';
exec(pkillCmd, function(error, stdout, stderr) {
console.log(pkillCmd + ' is issued');
shepherd.writeLog(pkillCmd + ' is issued');
if (error !== null) {
console.log(pkillCmd + ' exec error: ' + error);
shepherd.writeLog(pkillCmd + ' exec error: ' + error);
};
});
}
if (error !== null) {
console.log(iguanaGrep + ' exec error: ' + error);
shepherd.writeLog(iguanaGrep + ' exec error: ' + error);
};
});
}
guiapp.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', appConfig.dev ? '*' : 'http://127.0.0.1:' + appConfig.iguanaAppPort);
res.header('Access-Control-Allow-Origin', appConfig.dev ? '*' : 'http://127.0.0.1:3000');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Headers', 'Content-Type');
@ -119,12 +145,14 @@ var server = require('http').createServer(guiapp),
server.listen(appConfig.iguanaAppPort, function() {
console.log('guiapp and sockets.io are listening on port ' + appConfig.iguanaAppPort + '!');
shepherd.writeLog('guiapp and sockets.io are listening on port ' + appConfig.iguanaAppPort + '!');
});
io.set('origins', 'http://127.0.0.1:' + appConfig.iguanaAppPort); // set origin
io.set('origins', appConfig.dev ? 'http://127.0.0.1:3000' : 'http://127.0.0.1:' + appConfig.iguanaAppPort); // set origin
io.on('connection', function(client) {
console.log('EDEX GUI is connected...');
shepherd.writeLog('EDEX GUI is connected...');
client.on('event', function(data) { // listen for client requests
console.log(data);
@ -139,6 +167,7 @@ io.on('connection', function(client) {
});
shepherd.setIO(io); // pass sockets object to shepherd router
shepherd.setVar('appBasicInfo', appBasicInfo);
module.exports = guiapp;
// END GUI App Settings
@ -218,6 +247,7 @@ function createLoadingWindow() {
// load our index.html (i.e. easyDEX GUI)
loadingWindow.loadURL('http://' + appConfig.host + ':' + appConfig.iguanaAppPort + '/gui/');
shepherd.writeLog('show loading window');
// DEVTOOLS - only for dev purposes - ca333
//loadingWindow.webContents.openDevTools()
@ -327,7 +357,14 @@ function createWindow (status) {
// load our index.html (i.e. easyDEX GUI)
if (appConfig.edexGuiOnly) {
mainWindow.loadURL('http://' + appConfig.host + ':' + appConfig.iguanaAppPort + '/gui/EasyDEX-GUI/');
if (appConfig.v2) {
shepherd.writeLog('show edex gui');
mainWindow.loadURL('http://127.0.0.1:3000');
//mainWindow.loadURL('http://' + appConfig.host + ':' + appConfig.iguanaAppPort + '/gui/EasyDEX-GUI/react/build');
} else {
shepherd.writeLog('show edex gui');
mainWindow.loadURL('http://' + appConfig.host + ':' + appConfig.iguanaAppPort + '/gui/EasyDEX-GUI/');
}
} else {
mainWindow.loadURL('http://' + appConfig.host + ':' + appConfig.iguanaAppPort + '/gui/main.html');
}
@ -349,9 +386,18 @@ function createWindow (status) {
var ConnectToPm2 = function() {
return new Promise(function(resolve, reject) {
console.log('Closing Main Window...');
shepherd.writeLog('exiting app...');
shepherd.dumpCacheBeforeExit();
shepherd.quitKomodod();
// if komodod is under heavy load it may not respond to cli stop the first time
setInterval(function() {
shepherd.quitKomodod();
}, 100);
pm2.connect(true, function(err) {
console.log('connecting to pm2...');
shepherd.writeLog('connecting to pm2...');
if (err) {
console.log(err);
@ -361,6 +407,7 @@ function createWindow (status) {
var result = 'Connecting To Pm2: done';
console.log(result);
shepherd.writeLog(result);
resolve(result);
})
}
@ -368,10 +415,12 @@ function createWindow (status) {
var KillPm2 = function() {
return new Promise(function(resolve, reject) {
console.log('killing to pm2...');
shepherd.writeLog('killing to pm2...');
pm2.killDaemon(function(err) {
pm2.disconnect();
console.log('killed to pm2...');
shepherd.writeLog('killed to pm2...');
if (err)
throw err;
@ -381,6 +430,7 @@ function createWindow (status) {
setTimeout(function() {
console.log(result);
shepherd.writeLog(result);
resolve(result);
}, 2000)
@ -439,6 +489,7 @@ app.on('before-quit', function (event) {
if (mainWindow === null && loadingWindow != null) { // mainWindow not intitialised and loadingWindow not dereferenced
// loading window is still open
console.log('before-quit prevented');
shepherd.writeLog('quit app after loading is done');
closeAppAfterLoading = true;
let code = `$('#loading_status_text').html('Preparing to shutdown the wallet.<br/>Please wait while all daemons are closed...')`;
loadingWindow.webContents.executeJavaScript(code);
@ -470,3 +521,25 @@ app.on('activate', function () {
// createWindow('open');
}
});
function formatBytes(bytes, decimals) {
if (bytes === 0)
return '0 Bytes';
var k = 1000,
dm = decimals + 1 || 3,
sizes = [
'Bytes',
'KB',
'MB',
'GB',
'TB',
'PB',
'EB',
'ZB',
'YB'
],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

30
private/coincli.js → private/kmdcli.js

@ -50,13 +50,12 @@ console.log(komodocliBin)
* The **komodo-cli** command is used to get komodo api calls answer.
*
* @private
* @category coincli
* @category kmdcli
*
*/
var coincli = module.exports = {
var kmdcli = module.exports = {
exec: child_process.exec,
kmdcommand: kmdcommand,
zeccommand: zeccommand
command: command
};
/**
@ -64,11 +63,11 @@ var coincli = module.exports = {
*
* @private
* @static
* @category coincli
* @category kmdcli
* @param {function} callback The callback function.
*
*/
function parse_coincli_commands(callback) {
function parse_kmdcli_commands(callback) {
return function(error, stdout, stderr) {
if (error) callback(error, stderr);
else callback(error, stdout);
@ -81,13 +80,13 @@ function parse_coincli_commands(callback) {
*
* @private
* @static
* @category coincli
* @category kmdcli
* @param {function} callback The callback function.
* @example
*
* var coincli = require('./coincli');
* var kmdcli = require('./kmdcli');
*
* coincli.kmdcommand('getinfo', function(err, command) {
* kmdcli.command('getinfo', function(err, command) {
* console.log(command);
* });
*
@ -119,18 +118,9 @@ function parse_coincli_commands(callback) {
* }
*
*/
function kmdcommand(kmd_command, callback) {
function command(kmd_command, callback) {
if (callback) {
return this.exec(komodocliBin + " " + kmd_command,
parse_coincli_commands(callback));
}
}
function zeccommand(zec_command, callback) {
if (callback) {
return this.exec(zcashcliBin + " " + zec_command,
parse_coincli_commands(callback));
parse_kmdcli_commands(callback));
}
}

342
routes/cache.js

@ -3,66 +3,91 @@ const fs = require('fs-extra'),
async = require('async');
var cache = {};
var inMemCache;
var inMemPubkey;
cache.setVar = function(variable, value) {
cache[variable] = value;
}
/*
* cache data is dumped to disk before app quit or after cache.one call is finished
*/
cache.dumpCacheBeforeExit = function() {
if (inMemCache) {
console.log('dumping cache before exit');
fs.writeFileSync(cache.iguanaDir + '/shepherd/cache-' + inMemPubkey + '.json', JSON.stringify(inMemCache), 'utf8');
}
}
cache.get = function(req, res, next) {
var pubkey = req.query.pubkey;
const pubkey = req.query.pubkey;
if (pubkey) {
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json')) {
fs.readFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8', function (err, data) {
if (err) {
var errorObj = {
'msg': 'error',
'result': err
};
res.end(JSON.stringify(errorObj));
} else {
//var parsedJSON = 'JPARSE';//'JSON parse error';
inMemPubkey = pubkey;
try {
var parsedJSON = JSON.parse(data);
if (!inMemCache) {
console.log('serving cache from disk');
var successObj = {
'msg': 'success',
'result': parsedJSON
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json')) {
fs.readFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8', function (err, data) {
if (err) {
const errorObj = {
'msg': 'error',
'result': err
};
res.end(JSON.stringify(successObj));
} catch (e) {
console.log(e);
if (e.toString().indexOf('at position') > -1) {
const errorPos = e.toString().split(' ');
//console.log(errorPos[errorPos.length - 1]);
//JSON.parse(data.substring(0, errorPos[errorPos.length - 1]));
console.log('JSON error ---> ' + data.substring(errorPos[errorPos.length - 1] - 20, errorPos[errorPos.length - 1] + 20) + ' | error sequence: ' + data.substring(errorPos[errorPos.length - 1], errorPos[errorPos.length - 1] + 1));
console.log('attempting to recover JSON data');
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', data.substring(0, errorPos[errorPos.length - 1]), function(err) {
var successObj = {
'msg': 'success',
'result': data.substring(0, errorPos[errorPos.length - 1])
};
res.end(JSON.stringify(successObj));
});
res.end(JSON.stringify(errorObj));
} else {
try {
const parsedJSON = JSON.parse(data),
successObj = {
'msg': 'success',
'result': parsedJSON
};
inMemCache = parsedJSON;
res.end(JSON.stringify(successObj));
} catch (e) {
console.log('JSON parse error while reading cache data from disk:');
console.log(e);
if (e.toString().indexOf('at position') > -1) {
const errorPos = e.toString().split(' ');
console.log('JSON error ---> ' + data.substring(errorPos[errorPos.length - 1] - 20, errorPos[errorPos.length - 1] + 20) + ' | error sequence: ' + data.substring(errorPos[errorPos.length - 1], errorPos[errorPos.length - 1] + 1));
console.log('attempting to recover JSON data');
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', data.substring(0, errorPos[errorPos.length - 1]), function(err) {
const successObj = {
'msg': 'success',
'result': data.substring(0, errorPos[errorPos.length - 1])
};
inMemCache = JSON.parse(data.substring(0, errorPos[errorPos.length - 1]));
res.end(JSON.stringify(successObj));
});
}
}
}
}
});
});
} else {
const errorObj = {
'msg': 'error',
'result': 'no file with handle ' + pubkey
};
res.end(JSON.stringify(errorObj));
}
} else {
var errorObj = {
'msg': 'error',
'result': 'no file with handle ' + pubkey
const successObj = {
'msg': 'success',
'result': inMemCache
};
res.end(JSON.stringify(errorObj));
res.end(JSON.stringify(successObj));
}
} else {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no pubkey provided'
};
@ -72,20 +97,20 @@ cache.get = function(req, res, next) {
}
cache.groomGet = function(req, res, next) {
var _filename = req.query.filename;
const _filename = req.query.filename;
if (_filename) {
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json')) {
fs.readFile(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json', 'utf8', function (err, data) {
if (err) {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': err
};
res.end(JSON.stringify(errorObj));
} else {
var successObj = {
const successObj = {
'msg': 'success',
'result': data ? JSON.parse(data) : ''
};
@ -94,7 +119,7 @@ cache.groomGet = function(req, res, next) {
}
});
} else {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no file with name ' + _filename
};
@ -102,7 +127,7 @@ cache.groomGet = function(req, res, next) {
res.end(JSON.stringify(errorObj));
}
} else {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no file name provided'
};
@ -112,20 +137,22 @@ cache.groomGet = function(req, res, next) {
}
cache.groomDelete = function(req, res, next) {
var _filename = req.body.filename;
const _filename = req.body.filename;
if (_filename) {
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json')) {
inMemCache = null;
fs.unlink(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json', function(err) {
if (err) {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': err
};
res.end(JSON.stringify(errorObj));
} else {
var successObj = {
const successObj = {
'msg': 'success',
'result': 'deleted'
};
@ -134,7 +161,7 @@ cache.groomDelete = function(req, res, next) {
}
});
} else {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no file with name ' + _filename
};
@ -142,7 +169,7 @@ cache.groomDelete = function(req, res, next) {
res.end(JSON.stringify(errorObj));
}
} else {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no file name provided'
};
@ -152,40 +179,57 @@ cache.groomDelete = function(req, res, next) {
}
cache.groomPost = function(req, res) {
var _filename = req.body.filename,
_payload = req.body.payload;
const _filename = req.body.filename,
_payload = req.body.payload;
if (_filename) {
if (!_payload) {
var errorObj = {
if (!cacheCallInProgress) {
cacheCallInProgress = true;
if (_filename) {
if (!_payload) {
const errorObj = {
'msg': 'error',
'result': 'no payload provided'
};
res.end(JSON.stringify(errorObj));
} else {
inMemCache = JSON.parse(_payload);
console.log('appending groom post to in mem cache');
console.log('appending groom post to on disk cache');
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json', _payload, function (err) {
if (err) {
const errorObj = {
'msg': 'error',
'result': err
};
cacheCallInProgress = false;
res.end(JSON.stringify(errorObj));
} else {
const successObj = {
'msg': 'success',
'result': 'done'
};
cacheCallInProgress = false;
res.end(JSON.stringify(successObj));
}
});
}
} else {
const errorObj = {
'msg': 'error',
'result': 'no payload provided'
'result': 'no file name provided'
};
res.end(JSON.stringify(errorObj));
} else {
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json', _payload, function (err) {
if (err) {
var errorObj = {
'msg': 'error',
'result': err
};
res.end(JSON.stringify(errorObj));
} else {
var successObj = {
'msg': 'success',
'result': 'done'
};
res.end(JSON.stringify(successObj));
}
});
}
} else {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no file name provided'
'result': 'another job is in progress'
};
res.end(JSON.stringify(errorObj));
@ -193,11 +237,43 @@ cache.groomPost = function(req, res) {
}
var cacheCallInProgress = false,
cacheGlobLifetime = 300; // sec
cacheGlobLifetime = 600; // sec
// TODO: reset calls' states on new /cache call start
var mock = require('./mock');
var callStack = {},
checkCallStack = function() {
var total = 0;
for (var coin in callStack) {
total =+ callStack[coin];
}
if (total / Object.keys(callStack).length === 1) {
cache.dumpCacheBeforeExit();
/*fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', JSON.stringify(inMemCache), function(err) {
if (err) {
return console.log(err);
}
console.log('file ' + cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json is updated');
});*/
cacheCallInProgress = false;
cache.io.emit('messages', {
'message': {
'shepherd': {
'method': 'cache-one',
'status': 'done',
'resp': 'success'
}
}
});
// add timestamp to cache file
// writeCache(Date.now());
}
};
/*
* type: GET
* params: userpass, pubkey, coin, address, skip
@ -207,14 +283,22 @@ cache.one = function(req, res, next) {
cacheCallInProgress = false;
}
if (cacheCallInProgress) {
checkCallStack();
}
if (!cacheCallInProgress) {
fs.readFile(cache.iguanaDir + '/shepherd/cache-' + req.query.pubkey + '.json', 'utf8', function (err, data) {
if (data) {
data = data.replace('waiting', 'failed');
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + req.query.pubkey + '.json', data, function(err) {
});
cache.dumpCacheBeforeExit();
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + req.query.pubkey + '.json')) {
let _data = fs.readFileSync(cache.iguanaDir + '/shepherd/cache-' + req.query.pubkey + '.json', 'utf8');
if (_data) {
inMemCache = JSON.parse(_data);
_data = _data.replace('waiting', 'failed');
cache.dumpCacheBeforeExit();
}
});
}
// TODO: add check to allow only one cache call/sequence in progress
cacheCallInProgress = true;
@ -238,39 +322,7 @@ cache.one = function(req, res, next) {
outObj.timestamp = timeStamp;
}
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', JSON.stringify(outObj), function(err) {
if (err) {
return console.log(err);
}
console.log('file ' + cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json is updated');
if (timeStamp) {
console.log('file ' + cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json is timestamped');
}
});
},
callStack = {},
checkCallStack = function() {
var total = 0;
for (var coin in callStack) {
total =+ callStack[coin];
}
if (total / Object.keys(callStack).length === 1) {
cacheCallInProgress = false;
cache.io.emit('messages', {
'message': {
'shepherd': {
'method': 'cache-one',
'status': 'done',
'resp': 'success'
}
}
});
// add timestamp to cache file
// writeCache(Date.now());
}
inMemCache = outObj;
},
checkTimestamp = function(dateToCheck) {
var currentEpochTime = new Date(Date.now()) / 1000,
@ -280,12 +332,13 @@ cache.one = function(req, res, next) {
},
internalError = false;
inMemPubkey = pubkey;
callStack[coin] = 1;
console.log(callsArray);
console.log('iguana core port ' + iguanaCorePort);
if (!sessionKey) {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no session key provided'
};
@ -295,7 +348,7 @@ cache.one = function(req, res, next) {
}
if (!pubkey) {
var errorObj = {
const errorObj = {
'msg': 'error',
'result': 'no pubkey provided'
};
@ -306,9 +359,40 @@ cache.one = function(req, res, next) {
console.log('cache-one call started');
function fixJSON(data) {
if (data && data.length) {
try {
var parsedJSON = JSON.parse(data);
return parsedJSON;
} catch (e) {
console.log(e);
if (e.toString().indexOf('at position') > -1) {
const errorPos = e.toString().split(' ');
console.log('JSON error ---> ' + data.substring(errorPos[errorPos.length - 1] - 20, errorPos[errorPos.length - 1] + 20) + ' | error sequence: ' + data.substring(errorPos[errorPos.length - 1], errorPos[errorPos.length - 1] + 1));
console.log('attempting to recover JSON data');
return JSON.parse(data.substring(0, errorPos[errorPos.length - 1]));
}
if (e.toString().indexOf('Unexpected end of JSON input')) {
return {};
}
}
} else {
return {};
}
}
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json') && coin !== 'all') {
var _file = fs.readFileSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8');
outObj = _file ? JSON.parse(_file) : {};
if (inMemCache) {
console.log('cache one from mem');
outObj = inMemCache;
} else {
var _file = fs.readFileSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8');
console.log('cache one from disk');
//outObj = _file ? JSON.parse(_file) : {};
outObj = fixJSON(_file);
}
if (!outObj || !outObj.basilisk) {
console.log('no local basilisk info');
@ -340,7 +424,7 @@ cache.one = function(req, res, next) {
}
});
function execDEXRequests(address, coin) {
function execDEXRequests(coin, address) {
let dexUrls = {
'listunspent': 'http://' + cache.appConfig.host + ':' + iguanaCorePort + '/api/dex/listunspent?userpass=' + sessionKey + '&symbol=' + coin + '&address=' + address,
'listtransactions': 'http://' + cache.appConfig.host + ':' + iguanaCorePort + '/api/dex/listtransactions?userpass=' + sessionKey + '&count=100&skip=0&symbol=' + coin + '&address=' + address,
@ -359,6 +443,7 @@ cache.one = function(req, res, next) {
}
console.log(coin + ' address ' + address);
if (!outObj.basilisk[coin][address]) {
outObj.basilisk[coin][address] = {};
writeCache();
@ -517,8 +602,10 @@ cache.one = function(req, res, next) {
outObj.basilisk[coin].addresses = addrArray;
console.log(addrArray);
writeCache();
var addrCount = outObj.basilisk[coin].addresses ? outObj.basilisk[coin].addresses.length : 0;
const addrCount = outObj.basilisk[coin].addresses ? outObj.basilisk[coin].addresses.length : 0;
var callsArrayBTC = callsArray.length;
if (callsArray.indexOf('getbalance') > - 1) {
callsArrayBTC--;
}
@ -540,7 +627,7 @@ cache.one = function(req, res, next) {
}
});
async.each(outObj.basilisk[coin].addresses, function(address) {
execDEXRequests(address, coin);
execDEXRequests(coin, address);
});
}
@ -548,7 +635,7 @@ cache.one = function(req, res, next) {
if (addresses) {
parseAddresses(coin, addresses);
} else {
var tempUrl = 'http://' + cache.appConfig.host + ':' + iguanaCorePort + '/api/bitcoinrpc/getaddressesbyaccount?userpass=' + sessionKey + '&coin=' + coin + '&account=*';
const tempUrl = 'http://' + cache.appConfig.host + ':' + cache.appConfig.iguanaCorePort /*iguanaCorePort*/ + '/api/bitcoinrpc/getaddressesbyaccount?userpass=' + sessionKey + '&coin=' + coin + '&account=*';
request({
url: mock ? 'http://localhost:17777/shepherd/mock?url=' + tempUrl : tempUrl,
method: 'GET'
@ -579,7 +666,7 @@ cache.one = function(req, res, next) {
});
if (coin === 'all') {
var tempUrl = 'http://' + cache.appConfig.host + ':' + iguanaCorePort + '/api/InstantDEX/allcoins?userpass=' + sessionKey;
const tempUrl = 'http://' + cache.appConfig.host + ':' + /*iguanaCorePort*/ cache.appConfig.iguanaCorePort + '/api/InstantDEX/allcoins?userpass=' + sessionKey;
request({
url: mock ? 'http://localhost:17777/shepherd/mock?url=' + tempUrl : tempUrl,
method: 'GET'
@ -654,7 +741,8 @@ cache.one = function(req, res, next) {
'method': 'cache-one',
'status': 'in progress',
'iguanaAPI': {
'totalStackLength': callStack[coin]
'totalStackLength': callStack[coin],
'currentStackLength': callStack[coin]
}
}
}

511
routes/shepherd.js

@ -16,17 +16,18 @@ const electron = require('electron'),
request = require('request'),
async = require('async'),
rimraf = require('rimraf'),
portscanner = require('portscanner');
Promise = require('bluebird');
portscanner = require('portscanner'),
Promise = require('bluebird');
const fixPath = require('fix-path');
var ps = require('ps-node'),
setconf = require('../private/setconf.js'),
coincli = require('../private/coincli.js'),
//coincli = require('../private/coincli.js'),
assetChainPorts = require('./ports.js')
shepherd = express.Router(),
iguanaInstanceRegistry = {};
iguanaInstanceRegistry = {},
syncOnlyIguanaInstanceInfo = {},
syncOnlyInstanceInterval = -1;
// IGUANA FILES AND CONFIG SETTINGS
var iguanaConfsDirSrc = path.join(__dirname, '../assets/deps/confs'),
@ -66,9 +67,8 @@ if (os.platform() === 'win32') {
iguanaConfsDir = process.env.APPDATA + '/iguana/confs';
iguanaConfsDir = path.normalize(iguanaConfsDir);
iguanaIcon = path.join(__dirname, '/assets/icons/agama_icons/agama_app_icon.ico'),
iguanaConfsDirSrc = path.normalize(iguanaConfsDirSrc);
komododBin = path.join(__dirname, '../build/artifacts.supernet.org/latest/windows/komodod.exe'),
iguanaConfsDirSrc = path.normalize(iguanaConfsDirSrc),
komododBin = path.join(__dirname, '../assets/bin/win64/komodod.exe'),
komododBin = path.normalize(komododBin),
komodocliBin = path.join(__dirname, '../build/artifacts.supernet.org/latest/windows/komodo-cli.exe'),
komodocliBin = path.normalize(komodocliBin),
@ -90,9 +90,130 @@ shepherd.appConfig = {
"linux": 1000000
},
"killIguanaOnStart": true,
"dev": false
"dev": false,
"v2": false,
"forks": {
"basilisk": false,
"all": false
}
};
shepherd.writeLog = function(data) {
const logLocation = iguanaDir + '/shepherd';
const timeFormatted = new Date(Date.now()).toLocaleString().replace('AM', '').replace('PM', '');
if (fs.existsSync(logLocation + '/agamalog.txt')) {
fs.appendFile(logLocation + '/agamalog.txt', timeFormatted + ' ' + data + '\r\n', function (err) {
if (err) {
console.log('error writing log file');
}
});
} else {
fs.writeFile(logLocation + '/agamalog.txt', timeFormatted + ' ' + data + '\r\n', function (err) {
if (err) {
console.log('error writing log file');
}
});
}
}
shepherd.get('/coinslist', function(req, res, next) {
if (fs.existsSync(iguanaDir + '/shepherd/coinslist.json')) {
fs.readFile(iguanaDir + '/shepherd/coinslist.json', 'utf8', function (err, data) {
if (err) {
const errorObj = {
'msg': 'error',
'result': err
};
res.end(JSON.stringify(errorObj));
} else {
const successObj = {
'msg': 'success',
'result': data ? JSON.parse(data) : ''
};
res.end(JSON.stringify(successObj));
}
});
} else {
const errorObj = {
'msg': 'error',
'result': 'coin list doesn\'t exist'
};
res.end(JSON.stringify(errorObj));
}
});
shepherd.post('/coinslist', function(req, res, next) {
const _payload = req.body.payload;
if (!_payload) {
const errorObj = {
'msg': 'error',
'result': 'no payload provided'
};
res.end(JSON.stringify(errorObj));
} else {
fs.writeFile(cache.iguanaDir + '/shepherd/coinslist.json', JSON.stringify(_payload), function (err) {
if (err) {
const errorObj = {
'msg': 'error',
'result': err
};
res.end(JSON.stringify(errorObj));
} else {
const successObj = {
'msg': 'success',
'result': 'done'
};
res.end(JSON.stringify(successObj));
}
});
}
});
// TODO: check if komodod is running
shepherd.quitKomodod = function(chain) {
// exit komodod gracefully
console.log('exec ' + komodocliBin + (chain ? ' ac_name=' + chain : '') + ' stop');
exec(komodocliBin + (chain ? ' ac_name=' + chain : '') + ' stop', function(error, stdout, stderr) {
console.log('stdout: ' + stdout)
console.log('stderr: ' + stderr)
if (error !== null) {
console.log('exec error: ' + error)
}
});
}
/*
* type: POST
* params: payload
*/
shepherd.post('/appconf', function(req, res, next) {
if (!req.body.payload) {
const errorObj = {
'msg': 'error',
'result': 'no payload provided'
};
res.end(JSON.stringify(errorObj));
} else {
shepherd.saveLocalAppConf(req.body.payload);
const errorObj = {
'msg': 'success',
'result': 'config saved'
};
res.end(JSON.stringify(errorObj));
}
});
shepherd.saveLocalAppConf = function(appSettings) {
var appConfFileName = iguanaDir + '/config.json';
@ -104,6 +225,7 @@ shepherd.saveLocalAppConf = function(appSettings) {
setTimeout(function() {
console.log(result);
shepherd.writeLog(result);
resolve(result);
}, 1000);
});
@ -127,6 +249,7 @@ shepherd.saveLocalAppConf = function(appSettings) {
setTimeout(function() {
console.log(result);
console.log('app conf.json file is created successfully at: ' + iguanaConfsDir);
shepherd.writeLog('app conf.json file is created successfully at: ' + iguanaConfsDir);
resolve(result);
}, 2000);
});
@ -140,6 +263,7 @@ shepherd.loadLocalConfig = function() {
if (fs.existsSync(iguanaDir + '/config.json')) {
var localAppConfig = fs.readFileSync(iguanaDir + '/config.json', 'utf8');
console.log('app config set from local file');
shepherd.writeLog('app config set from local file');
// find diff between local and hardcoded configs
// append diff to local config
@ -163,6 +287,9 @@ shepherd.loadLocalConfig = function() {
console.log('config diff is found, updating local config');
console.log('config diff:');
console.log(compareConfigs);
shepherd.writeLog('aconfig diff is found, updating local config');
shepherd.writeLog('config diff:');
shepherd.writeLog(compareConfigs);
shepherd.saveLocalAppConf(newConfig);
return newConfig;
@ -174,6 +301,7 @@ shepherd.loadLocalConfig = function() {
}
} else {
console.log('local config file is not found!');
shepherd.writeLog('local config file is not found!');
shepherd.saveLocalAppConf(shepherd.appConfig);
return shepherd.appConfig;
@ -187,22 +315,48 @@ console.log('iguana bin: ' + iguanaBin);
console.log('--------------------------')
console.log('iguana dir: ' + komododBin);
console.log('iguana bin: ' + komodoDir);
shepherd.writeLog('iguana dir: ' + iguanaDir);
shepherd.writeLog('iguana bin: ' + iguanaBin);
shepherd.writeLog('iguana dir: ' + komododBin);
shepherd.writeLog('iguana bin: ' + komodoDir);
// END IGUANA FILES AND CONFIG SETTINGS
// default route
shepherd.get('/', function(req, res, next) {
res.send('Iguana app server');
});
/*
* type: GET
*
*/
shepherd.get('/appconf', function(req, res, next) {
var obj = shepherd.loadLocalConfig();
res.send(obj);
});
/*
* type: GET
*
*/
shepherd.get('/sysinfo', function(req, res, next) {
var obj = shepherd.SystemInfo();
res.send(obj);
});
/*
* type: GET
*
*/
shepherd.get('/appinfo', function(req, res, next) {
var obj = shepherd.appInfo();
res.send(obj);
});
shepherd.dumpCacheBeforeExit = function() {
cache.dumpCacheBeforeExit();
}
var cache = require('./cache');
var mock = require('./mock');
@ -212,9 +366,135 @@ shepherd.setIO = function(io) {
cache.setVar('io', io);
};
shepherd.setVar = function(_name, _body) {
shepherd[_name] = _body;
};
cache.setVar('iguanaDir', iguanaDir);
cache.setVar('appConfig', shepherd.appConfig);
// fetch sync only forks info
shepherd.getSyncOnlyForksInfo = function() {
async.forEachOf(iguanaInstanceRegistry, function(data, port) {
if (iguanaInstanceRegistry[port].mode.indexOf('/sync') > -1) {
syncOnlyIguanaInstanceInfo[port] = {};
request({
url: 'http://localhost:' + port + '/api/bitcoinrpc/getinfo?userpass=tmpIgRPCUser@1234',
method: 'GET'
}, function (error, response, body) {
if (response && response.statusCode && response.statusCode === 200) {
// console.log(body);
try {
syncOnlyIguanaInstanceInfo[port].getinfo = JSON.parse(body);
} catch(e) {}
} else {
// TODO: error
}
});
request({
url: 'http://localhost:' + port + '/api/SuperNET/activehandle?userpass=tmpIgRPCUser@1234',
method: 'GET'
}, function (error, response, body) {
if (response && response.statusCode && response.statusCode === 200) {
// console.log(body);
try {
syncOnlyIguanaInstanceInfo[port].activehandle = JSON.parse(body);
} catch(e) {}
} else {
// TODO: error
}
});
syncOnlyIguanaInstanceInfo[port].registry = iguanaInstanceRegistry[port];
}
});
}
/*
* type: GET
*
*/
shepherd.get('/forks/info/start', function(req, res, next) {
var successObj = {
'msg': 'success',
'result': 'started'
};
res.end(JSON.stringify(successObj));
shepherd.getSyncOnlyForksInfo();
});
/*
* type: GET
*
*/
shepherd.get('/forks/info/show', function(req, res, next) {
var successObj = {
'msg': 'success',
'result': JSON.stringify(syncOnlyIguanaInstanceInfo)
};
res.end(JSON.stringify(successObj));
});
/*
* type: GET
*
*/
shepherd.get('/forks/restart', function(req, res, next) {
var _pmid = req.query.pmid;
pm2.connect(function(err) {
if (err) {
console.error(err);
}
pm2.restart(_pmid, function(err, ret) {
if (err) {
console.error(err);
}
pm2.disconnect();
var successObj = {
'msg': 'success',
'result': 'restarted'
};
shepherd.writeLog('iguana fork pmid ' + _pmid + ' restarted');
res.end(JSON.stringify(successObj));
});
});
});
/*
* type: GET
*
*/
shepherd.get('/forks/stop', function(req, res, next) {
var _pmid = req.query.pmid;
pm2.connect(function(err) {
if (err) {
console.error(err);
}
pm2.stop(_pmid, function(err, ret) {
if (err) {
console.error(err);
}
pm2.disconnect();
var successObj = {
'msg': 'success',
'result': 'stopped'
};
shepherd.writeLog('iguana fork pmid ' + _pmid + ' stopped');
res.end(JSON.stringify(successObj));
});
});
});
/*
* type: GET
*
@ -233,7 +513,8 @@ shepherd.get('/forks', function(req, res, next) {
* params: name
*/
shepherd.post('/forks', function(req, res, next) {
const name = req.body.name;
const mode = req.body.mode,
coin = req.body.coin,
port = shepherd.appConfig.iguanaCorePort;
portscanner.findAPortNotInUse(port, port + 100, '127.0.0.1', function(error, _port) {
@ -244,14 +525,32 @@ shepherd.post('/forks', function(req, res, next) {
}
console.log('iguana core fork port ' + _port);
shepherd.writeLog('iguana core fork port ' + _port);
pm2.start({
script: iguanaBin, // path to binary
name: 'IGUANA ' + _port + ' ' + name,
name: 'IGUANA ' + _port + ' ' + mode + ' / ' + coin,
exec_mode : 'fork',
args: ['-port=' + _port],
cwd: iguanaDir //set correct iguana directory
}, function(err, apps) {
iguanaInstanceRegistry[_port] = name;
iguanaInstanceRegistry[_port] = {
'mode': mode,
'coin': coin,
'pid': apps[0].process && apps[0].process.pid,
'pmid': apps[0].pm2_env.pm_id
};
cache.setVar('iguanaInstances', iguanaInstanceRegistry);
// get sync only forks info
if (syncOnlyInstanceInterval === -1) {
setTimeout(function() {
shepherd.getSyncOnlyForksInfo();
}, 5000);
setInterval(function() {
shepherd.getSyncOnlyForksInfo();
}, 20000);
}
var successObj = {
'msg': 'success',
@ -263,6 +562,7 @@ shepherd.post('/forks', function(req, res, next) {
pm2.disconnect(); // Disconnect from PM2
if (err) {
throw err;
shepherd.writeLog('iguana fork error: ' + err);
console.log('iguana fork error: ' + err);
}
});
@ -298,7 +598,7 @@ shepherd.delete('/groom', function(req, res, next) {
* type: POST
* params: filename, payload
*/
shepherd.post('/groom', function(req, res) {
shepherd.post('/groom', function(req, res, next) {
cache.groomPost(req, res, next);
});
@ -382,6 +682,7 @@ shepherd.post('/herd', function(req, res) {
portscanner.checkPortStatus(_port, '127.0.0.1', function(error, status) {
// Status is 'open' if currently in use or 'closed' if available
if (status === 'closed') {
shepherd.writeLog('komodod service start error at port ' + _port + ', reason: port is closed');
cache.io.emit('service', {
'komodod': {
'error': 'start error'
@ -410,6 +711,8 @@ shepherd.post('/herdlist', function(req, res) {
console.log(list[0].pm2_env.status) // print status of IGUANA proc
console.log(list[0].pid) // print pid of IGUANA proc
shepherd.writeLog(list[0].pm2_env.status);
shepherd.writeLog(list[0].pid);
var obj = {
'herdname': req.body.herdname,
@ -469,6 +772,9 @@ shepherd.post('/getconf', function(req, res) {
var confpath = getConf(req.body.chain);
console.log('got conf path is:');
console.log(confpath);
shepherd.writeLog('got conf path is:');
shepherd.writeLog(confpath);
var obj = {
'msg': 'success',
'result': confpath
@ -559,7 +865,7 @@ shepherd.get('/kick', function(req, res, next) {
'type': 'folder'
}
],
'brutal': [ // delete coin related data
'brutal': [ // delete all coin related data
{
'name': 'DB/[coin]',
'type': 'folder'
@ -625,6 +931,7 @@ shepherd.readDebugLog = function(fileLocation, lastNLines) {
_fs.access(fileLocation, fs.constants.R_OK, function(err) {
if (err) {
console.log('error reading ' + fileLocation);
shepherd.writeLog('error reading ' + fileLocation);
reject('readDebugLog error: ' + err);
} else {
console.log('reading ' + fileLocation);
@ -653,6 +960,8 @@ function herder(flock, data) {
if (flock === 'iguana') {
console.log('iguana flock selected...');
console.log('selected data: ' + data);
shepherd.writeLog('iguana flock selected...');
shepherd.writeLog('selected data: ' + data);
// MAKE SURE IGUANA DIR IS THERE FOR USER
mkdirp(iguanaDir, function(err) {
@ -684,6 +993,7 @@ function herder(flock, data) {
return console.error(err);
console.log('confs files copied successfully at: ' + iguanaConfsDir);
shepherd.writeLog('confs files copied successfully at: ' + iguanaConfsDir);
});
pm2.connect(true,function(err) { //start up pm2 god
@ -693,6 +1003,8 @@ function herder(flock, data) {
}
console.log('iguana core port ' + shepherd.appConfig.iguanaCorePort);
shepherd.writeLog('iguana core port ' + shepherd.appConfig.iguanaCorePort);
pm2.start({
script: iguanaBin, // path to binary
name: 'IGUANA',
@ -700,10 +1012,18 @@ function herder(flock, data) {
args: ['-port=' + shepherd.appConfig.iguanaCorePort],
cwd: iguanaDir //set correct iguana directory
}, function(err, apps) {
iguanaInstanceRegistry[shepherd.appConfig.iguanaCorePort] = 'main';
iguanaInstanceRegistry[shepherd.appConfig.iguanaCorePort] = {
'mode': 'main',
'coin': 'none',
'pid': apps[0].process.pid,
'pmid': apps[0].pm2_env.pm_id
};
shepherd.writeLog('iguana core started at port ' + shepherd.appConfig.iguanaCorePort + ' pid ' + apps[0].process.pid);
pm2.disconnect(); // Disconnect from PM2
if (err) {
throw err;
shepherd.writeLog('iguana core port ' + shepherd.appConfig.iguanaCorePort);
console.log('iguana fork error: ' + err);
}
});
@ -714,19 +1034,24 @@ function herder(flock, data) {
var kmdDebugLogLocation = ( data.ac_name ? komodoDir + '/' + data.ac_name : komodoDir ) + '/debug.log';
console.log('komodod flock selected...');
console.log('selected data: ' + data);
shepherd.writeLog('komodod flock selected...');
shepherd.writeLog('selected data: ' + data);
// truncate debug.log
try {
_fs.access(kmdDebugLogLocation, fs.constants.R_OK, function(err) {
if (err) {
console.log('error accessing ' + kmdDebugLogLocation);
shepherd.writeLog('error accessing ' + kmdDebugLogLocation);
} else {
console.log('truncate ' + kmdDebugLogLocation);
shepherd.writeLog('truncate ' + kmdDebugLogLocation);
fs.unlink(kmdDebugLogLocation);
}
});
} catch(e) {
console.log('komodod debug.log access err: ' + e);
shepherd.writeLog('komodod debug.log access err: ' + e);
}
// get komodod instance port
@ -737,30 +1062,54 @@ function herder(flock, data) {
portscanner.checkPortStatus(_port, '127.0.0.1', function(error, status) {
// Status is 'open' if currently in use or 'closed' if available
if (status === 'closed') {
pm2.connect(true, function(err) { // start up pm2 god
if (err) {
console.error(err);
process.exit(2);
}
pm2.start({
script: komododBin, // path to binary
name: data.ac_name, // REVS, USD, EUR etc.
exec_mode : 'fork',
cwd: komodoDir,
args: data.ac_options
}, function(err, apps) {
pm2.disconnect(); // Disconnect from PM2
if (err)
throw err;
// start komodod via exec
if (data.ac_name === 'komodod') {
console.log('exec' + komododBin + ' ' + data.ac_options.join(' '));
shepherd.writeLog('exec' + komododBin + ' ' + data.ac_options.join(' '));
exec(komododBin + ' ' + data.ac_options.join(' '), {
maxBuffer: 1024 * 10000 // 10 mb
}, function(error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
shepherd.writeLog('stdout: ' + stdout);
shepherd.writeLog('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error)
shepherd.writeLog('exec error: ' + error);
}
});
});
} else {
pm2.connect(true, function(err) { // start up pm2 god
if (err) {
console.error(err);
process.exit(2);
}
pm2.start({
script: komododBin, // path to binary
name: data.ac_name, // REVS, USD, EUR etc.
exec_mode : 'fork',
cwd: komodoDir,
args: data.ac_options
}, function(err, apps) {
shepherd.writeLog('komodod fork started ' + data.ac_name + ' ' + JSON.stringify(data.ac_options));
pm2.disconnect(); // Disconnect from PM2
if (err)
throw err;
});
});
}
} else {
console.log('port ' + _port + ' (' + data.ac_name + ') is already in use');
shepherd.writeLog('port ' + _port + ' (' + data.ac_name + ') is already in use');
}
});
} catch(e) {
console.log('failed to start komodod err: ' + e);
shepherd.writeLog('failed to start komodod err: ' + e);
}
}
@ -768,6 +1117,8 @@ function herder(flock, data) {
var kmdDebugLogLocation = zcashDir + '/debug.log';
console.log('zcashd flock selected...');
console.log('selected data: ' + data);
shepherd.writeLog('zcashd flock selected...');
shepherd.writeLog('selected data: ' + data);
pm2.connect(true, function(err) { // start up pm2 god
if (err) {
@ -782,6 +1133,8 @@ function herder(flock, data) {
cwd: zcashDir,
args: data.ac_options
}, function(err, apps) {
shepherd.writeLog('zcashd fork started ' + data.ac_name + ' ' + JSON.stringify(data.ac_options));
pm2.disconnect(); // Disconnect from PM2
if (err)
throw err;
@ -789,6 +1142,7 @@ function herder(flock, data) {
});
}
// deprecated, to be removed
if (flock === 'corsproxy') {
console.log('corsproxy flock selected...');
console.log('selected data: ' + data);
@ -818,12 +1172,45 @@ function slayer(flock) {
pm2.delete(flock, function(err, ret) {
pm2.disconnect();
shepherd.writeLog('deleting flock ' + flock);
shepherd.writeLog(ret);
console.log(ret);
});
}
shepherd.setConfKMD = function() {
if (os.platform() === 'darwin') {
var komodoDir = process.env.HOME + '/Library/Application Support/Komodo',
ZcashDir = process.env.HOME + '/Library/Application Support/Zcash';
}
if (os.platform() === 'linux') {
var komodoDir = process.env.HOME + '/.komodo',
ZcashDir = process.env.HOME + '/.zcash';
}
if (os.platform() === 'win32') {
var komodoDir = process.env.APPDATA + '/Komodo',
ZcashDir = process.env.APPDATA + '/Zcash';
}
// check if kmd conf exists
_fs.access(komodoDir + '/komodo.conf', fs.constants.R_OK, function(err) {
if (err) {
console.log('creating komodo conf');
shepherd.writeLog('creating komodo conf in ' + komodoDir + '/komodo.conf');
setConf('komodod');
} else {
shepherd.writeLog('komodo conf exists');
console.log('komodo conf exists');
}
});
}
function setConf(flock) {
console.log(flock);
shepherd.writeLog('setconf ' + flock);
if (os.platform() === 'darwin') {
var komodoDir = process.env.HOME + '/Library/Application Support/Komodo',
@ -855,12 +1242,14 @@ function setConf(flock) {
break;
default:
var DaemonConfPath = komodoDir + '/' + flock + '/' + flock + '.conf';
if (os.platform() === 'win32') {
DaemonConfPath = path.normalize(DaemonConfPath);
}
}
console.log(DaemonConfPath);
shepherd.writeLog('setconf ' + DaemonConfPath);
var CheckFileExists = function() {
return new Promise(function(resolve, reject) {
@ -872,6 +1261,8 @@ function setConf(flock) {
setTimeout(function() {
console.log(result);
shepherd.writeLog('setconf ' + result);
resolve(result);
}, 2000);
});
@ -885,6 +1276,8 @@ function setConf(flock) {
setTimeout(function() {
console.log(result);
shepherd.writeLog('setconf ' + result);
resolve(result);
}, 1000);
});
@ -896,6 +1289,7 @@ function setConf(flock) {
fs.readFile(DaemonConfPath, 'utf8', function(err, data) {
if (err) {
shepherd.writeLog('setconf error ' + err);
return console.log(err);
}
@ -909,7 +1303,9 @@ function setConf(flock) {
fsnode.chmodSync(DaemonConfPath, '0666');
setTimeout(function() {
shepherd.writeLog('setconf ' + result);
console.log(result);
resolve(result);
}, 2000);
});
@ -926,14 +1322,18 @@ function setConf(flock) {
if (status[0].hasOwnProperty('rpcuser')) {
console.log('rpcuser: OK');
shepherd.writeLog('rpcuser: OK');
} else {
console.log('rpcuser: NOT FOUND');
var randomstring = md5(Math.random() * Math.random() * 999);
console.log('rpcuser: NOT FOUND');
shepherd.writeLog('rpcuser: NOT FOUND');
fs.appendFile(DaemonConfPath, '\nrpcuser=user' + randomstring.substring(0, 16), (err) => {
if (err)
throw err;
console.log('rpcuser: ADDED');
shepherd.writeLog('rpcuser: ADDED');
});
}
@ -947,14 +1347,18 @@ function setConf(flock) {
if (status[0].hasOwnProperty('rpcpassword')) {
console.log('rpcpassword: OK');
shepherd.writeLog('rpcpassword: OK');
} else {
console.log('rpcpassword: NOT FOUND');
var randomstring = md5(Math.random() * Math.random() * 999);
console.log('rpcpassword: NOT FOUND');
shepherd.writeLog('rpcpassword: NOT FOUND');
fs.appendFile(DaemonConfPath, '\nrpcpassword=' + randomstring, (err) => {
if (err)
throw err;
console.log('rpcpassword: ADDED');
shepherd.writeLog('rpcpassword: ADDED');
});
}
@ -968,12 +1372,16 @@ function setConf(flock) {
if (status[0].hasOwnProperty('server')) {
console.log('server: OK');
shepherd.writeLog('server: OK');
} else {
console.log('server: NOT FOUND');
shepherd.writeLog('server: NOT FOUND');
fs.appendFile(DaemonConfPath, '\nserver=1', (err) => {
if (err)
throw err;
console.log('server: ADDED');
shepherd.writeLog('server: ADDED');
});
}
@ -987,6 +1395,7 @@ function setConf(flock) {
if (status[0].hasOwnProperty('addnode')) {
console.log('addnode: OK');
shepherd.writeLog('addnode: OK');
} else {
console.log('addnode: NOT FOUND')
fs.appendFile(DaemonConfPath,
@ -1000,6 +1409,7 @@ function setConf(flock) {
if (err)
throw err;
console.log('addnode: ADDED');
shepherd.writeLog('addnode: ADDED');
});
}
@ -1017,6 +1427,8 @@ function setConf(flock) {
setTimeout(function() {
console.log(result);
shepherd.writeLog('checkconf addnode ' + result);
resolve(result);
}, 2000);
});
@ -1030,6 +1442,8 @@ function setConf(flock) {
setTimeout(function() {
console.log(result);
shepherd.writeLog('MakeConfReadOnly ' + result);
resolve(result);
}, 1000);
});
@ -1046,10 +1460,11 @@ function setConf(flock) {
function getConf(flock) {
var komodoDir = '',
ZcashDir = '',
DaemonConfPath = '';
ZcashDir = '',
DaemonConfPath = '';
console.log(flock);
shepherd.writeLog('getconf flock: ' + flock);
if (os.platform() === 'darwin') {
komodoDir = process.env.HOME + '/Library/Application Support/Komodo';
@ -1087,12 +1502,13 @@ function getConf(flock) {
}
}
shepherd.writeLog('getconf path: ' + DaemonConfPath);
console.log(DaemonConfPath);
return DaemonConfPath;
}
function formatBytes(bytes, decimals) {
if (bytes == 0)
if (bytes === 0)
return '0 Bytes';
var k = 1000,
@ -1116,7 +1532,7 @@ function formatBytes(bytes, decimals) {
shepherd.SystemInfo = function() {
const os_data = {
'totalmem_bytes': os.totalmem(),
'totalmem_readble': formatBytes(os.totalmem()),
'totalmem_readable': formatBytes(os.totalmem()),
'arch': os.arch(),
'cpu': os.cpus()[0].model,
'cpu_cores': os.cpus().length,
@ -1128,4 +1544,23 @@ shepherd.SystemInfo = function() {
return os_data;
}
shepherd.appInfo = function() {
const sysInfo = shepherd.SystemInfo();
const releaseInfo = shepherd.appBasicInfo;
const dirs = {
iguanaDir,
iguanaBin,
komodoDir,
komododBin,
configLocation: iguanaDir + '/config.json',
cacheLocation: iguanaDir + '/shepherd',
};
return {
sysInfo,
releaseInfo,
dirs,
};
}
module.exports = shepherd;
Loading…
Cancel
Save