Files
yunkong2.js-controller/lib/setup/setupMultihost.js
2018-09-17 20:32:19 +08:00

295 lines
12 KiB
JavaScript

'use strict';
function Multihost(options) {
var fs = require('fs');
var tools = require(__dirname + '/../tools.js');
var configName = tools.getConfigFileName();
var that = this;
options = options || {};
var params = options.params || {};
var objects = options.objects;
function getConfig() {
var config;
// read actual configuration
try {
if (fs.existsSync(configName)) {
config = JSON.parse(fs.readFileSync(configName, 'utf8'));
} else {
config = require(__dirname + '/../../conf/' + tools.appName + '-dist.json');
}
} catch (e) {
config = require(__dirname + '/../../conf/' + tools.appName + '-dist.json');
}
return config;
}
function leftPad(text, len) {
text = text || '';
if (text.length >= len) return len;
return new Array(len - text.length).join(' ') + text;
}
this.showHosts = function (list) {
if (!list || !list.length) {
console.info('Nothing found');
} else {
for (var i = 0; i < list.length; i++) {
console.log((i + 1) + ' | ' + leftPad(list[i].hostname, 20) + ' | ' + (list[i].slave ? 'slave' : ' host') + ' | ' + leftPad(list[i].ip, 20) + ' | ' + JSON.stringify(list[i].info));
}
}
};
this.browse = function (callback) {
var MHClient = require(__dirname + '/../multihostClient');
var mhClient = new MHClient();
mhClient.browse(2000, params.debug, function (err, list) {
if (err) {
callback('Cannot browse: ' + err);
} else {
callback(null, list);
}
});
};
function showMHState(config, changed, callback) {
if (config.multihostService.enabled) {
if (config.objects.type === 'file' && (config.objects.host === '127.0.0.1' || config.objects.host === 'localhost')) {
console.log('Server accept connections for objects on all IP addresses.');
config.objects.host = '0.0.0.0';
changed = true;
} else if (config.objects.type === 'redis') {
console.log('Please check the binding of redis service. By default it is only local: http://download.redis.io/redis-stable/redis.conf\nChange "bind 127.0.0.1" to "bind 0.0.0.0" or to others.')
}
if (config.states.type === 'file' && (config.states.host === '127.0.0.1' || config.states.host === 'localhost')) {
console.log('Server accept connections for states on all IP addresses.');
config.states.host = '0.0.0.0';
changed = true;
} else if (config.states.type === 'redis') {
console.log('Please check the binding of redis service. By default it is only local: http://download.redis.io/redis-stable/redis.conf\nChange "bind 127.0.0.1" to "bind 0.0.0.0" or to others.')
}
}
if (!changed) {
console.log('Nothing changed.');
} else {
fs.writeFileSync(configName, JSON.stringify(config, null, 2));
console.log('Please restart yunkong2: "yunkong2 restart"');
}
console.log('\n');
console.log('Miltihost: ' + (config.multihostService.enabled ? 'enabled' : 'disabled'));
console.log('Authentication: ' + (config.multihostService.secure ? 'enabled' : 'disabled'));
console.log('Objects: ' + config.objects.type + ' on ' + config.objects.host);
console.log('States: ' + config.states.type + ' on ' + config.states.host);
callback();
}
this.enable = function (isEnable, callback) {
var changed = false;
var config = getConfig();
config.multihostService = config.multihostService || {enabled: false, secure: true};
if (isEnable && !config.multihostService.enabled) {
changed = true;
config.multihostService.enabled = true;
config.multihostService.password = '';
console.log('Miltihost activated.')
} else if (!isEnable && config.multihostService.enabled) {
changed = true;
config.multihostService.enabled = false;
config.multihostService.password = '';
console.log('Miltihost deactivated.')
}
if (params.secure === undefined) {
params.secure = true;
}
if (isEnable && (config.multihostService.secure !== params.secure || (config.multihostService.secure && !config.multihostService.password))) {
changed = true;
config.multihostService.secure = params.secure;
console.log('Authentication ' + (params.secure ? 'activated' : 'deactivated') + '.');
if (config.multihostService.secure) {
var prompt = require('prompt');
prompt.message = '';
prompt.delimiter = '';
var schema = {
properties: {
password: {
description: 'Enter secret phrase for connection:',
pattern: /^[^'"]+$/,
message: 'No " are allowed',
hidden: true
},
passwordRepeat: {
description: 'Repeat secret phrase for connection:',
pattern: /^[^'"]+$/,
message: 'No " are allowed',
hidden: true
}
}
};
prompt.start();
prompt.get(schema, function (err, password) {
if (password && password.password) {
if (password.password !== password.passwordRepeat) {
callback('Secret phrases are not equal!');
} else {
objects.getObject('system.config', function (err, obj) {
tools.encryptPhrase(obj.native.secret, password.password, function (encoded) {
config.multihostService.password = encoded;
showMHState(config, changed, callback);
})
});
}
} else {
callback('No secret phrase entered!');
}
});
} else {
showMHState(config, changed, callback);
}
} else {
showMHState(config, changed, callback);
}
};
this.status = function (callback) {
var config = getConfig();
config.multihostService = config.multihostService || {enabled: false, secure: true};
showMHState(config, false, callback);
};
function readPassword(callback) {
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function hidden(query, callback) {
var stdin = process.openStdin();
process.stdin.on('data', function (char) {
char = char + '';
switch (char) {
case '\n':
case '\r':
case '\u0004':
stdin.pause();
break;
default:
process.stdout.write('\x1B[2K\x1B[200D' + query + new Array(rl.line.length + 1).join('*'));
break;
}
});
rl.question(query, function (value) {
rl.history = rl.history.slice(1);
callback(value);
});
}
hidden('Enter secret phrase for connection: ', function(password) {
callback(password);
});
}
function connect(mhClient, ip, pass, callback) {
mhClient.connect(ip, pass, function (err, oObjects, oStates, ipHost) {
if (err) {
callback('Cannot connect to "' + ip + '": ' + err);
} else if (oObjects && oStates) {
var config = getConfig();
config.objects = oObjects;
config.states = oStates;
if (config.objects.host === '127.0.0.1' || config.objects.host === 'localhost' || config.states.host === '127.0.0.1' || config.states.host === 'localhost') {
callback('IP Address of the host is 127.0.0.1. It accepts no connections. Please change.');
} else {
if (config.states.host === '0.0.0.0') {
config.states.host = ipHost;
}
if (config.objects.host === '0.0.0.0') {
config.objects.host = ipHost;
}
fs.writeFileSync(configName, JSON.stringify(config, null, 2));
console.log('Config ok. Please restart yunkong2: "yunkong2 restart"');
callback();
}
} else {
callback('No configuration received!');
}
});
}
this.connect = function (number, pass, callback) {
if (typeof pass === 'function') {
callback = pass;
pass = null;
}
if (typeof number === 'function') {
callback = number;
number = null;
}
var MHClient = require(__dirname + '/../multihostClient');
var mhClient = new MHClient();
mhClient.browse(2000, params.debug, function (err, list) {
if (err) {
callback('Cannot browse: ' + err);
} else {
that.showHosts(list);
if (number !== null && number !== undefined && parseInt(number, 10) > 0) {
number = parseInt(number, 10);
if (list && number < list.length + 1) {
if (!pass) {
callback('No password defined: please use "multihost connect <NUMBER> <PASSWORD>"');
} else {
connect(mhClient, list[number - 1].ip, pass, callback);
}
} else {
callback('Invalid index: ' + number);
}
} else
if (list && list.length) {
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Please select host [1]: ', function (answer) {
if (answer === '' || answer === null || answer === undefined) {
answer = 1;
}
answer = parseInt(answer, 10) - 1;
if (!list[answer]) {
rl.close();
callback('Invalid index: ' + answer);
} else {
if (list[answer].auth) {
readPassword(function (password) {
if (password) {
connect(mhClient, list[answer].ip, password, callback);
} else {
callback('No password entered!');
}
});
} else {
connect(mhClient, list[answer].ip, null, callback);
}
}
});
} else {
callback(null, list);
}
}
});
};
}
module.exports = Multihost;