mecano
Version:
Common functions for system deployment.
121 lines (117 loc) • 5.76 kB
JavaScript
// Generated by CoffeeScript 1.11.1
var each, misc,
slice = [].slice;
module.exports = function(options) {
var extract_servers, host, i, j, k, len, len1, port, quorum_target, ref, ref1, ref2, ref3, server, servers;
options.log({
message: "Entering wait for connection",
level: 'DEBUG',
module: 'mecano/connection/wait'
});
extract_servers = function(options) {
var host, hosts, i, j, k, l, len, len1, len2, len3, m, port, ports, ref, ref1, ref2, ref3, servers;
if ((options.port || options.ports) && !options.host) {
throw Error("Invalid host: " + server.host);
}
if ((options.host || options.hosts) && !options.port) {
throw Error("Invalid port: " + server.port);
}
ref = ['host', 'hosts'];
for (i = 0, len = ref.length; i < len; i++) {
k = ref[i];
if (options[k] == null) {
options[k] = [];
}
if ((ref1 = typeof options[k]) !== 'string' && ref1 !== 'object') {
throw error("Invalid option '" + options[k] + "'");
}
if (!Array.isArray(options[k])) {
options[k] = [options[k]];
}
}
hosts = slice.call(options.host).concat(slice.call(options.hosts));
ref2 = ['port', 'ports'];
for (j = 0, len1 = ref2.length; j < len1; j++) {
k = ref2[j];
if (options[k] == null) {
options[k] = [];
}
if ((ref3 = typeof options[k]) !== 'string' && ref3 !== 'number' && ref3 !== 'object') {
throw error("Invalid option '" + options[k] + "'");
}
if (!Array.isArray(options[k])) {
options[k] = [options[k]];
}
}
ports = slice.call(options.port).concat(slice.call(options.ports));
servers = [];
for (l = 0, len2 = hosts.length; l < len2; l++) {
host = hosts[l];
for (m = 0, len3 = ports.length; m < len3; m++) {
port = ports[m];
servers.push({
host: host,
port: port
});
}
}
return servers;
};
servers = extract_servers(options);
ref = ['server', 'servers'];
for (i = 0, len = ref.length; i < len; i++) {
k = ref[i];
if (options[k] == null) {
options[k] = [];
}
if ((ref1 = typeof options[k]) !== 'string' && ref1 !== 'object') {
throw error("Invalid option '" + options[k] + "'");
}
if (typeof options[k] === 'string') {
ref2 = options[k].split(':'), host = ref2[0], port = ref2[1];
options[k] = {
host: host,
port: port
};
}
if (!Array.isArray(options[k])) {
options[k] = [options[k]];
}
options[k] = misc.array.flatten(options[k]);
ref3 = options[k];
for (j = 0, len1 = ref3.length; j < len1; j++) {
server = ref3[j];
servers.push.apply(servers, extract_servers(server));
}
}
if (!servers.length) {
options.log({
message: "No connection to wait for",
level: 'WARN',
module: 'mecano/connection/wait'
});
return;
}
if (options.interval == null) {
options.interval = 2000;
}
options.interval = Math.round(options.interval / 1000);
quorum_target = options.quorum;
if (quorum_target && quorum_target === true) {
quorum_target = Math.ceil(servers.length / 2);
} else if (quorum_target == null) {
quorum_target = servers.length;
}
if (!(options.timeout > 0)) {
options.timeout = '';
}
return this.execute({
cmd: "function compute_md5 {\n echo $1 | openssl md5 | sed 's/^.* \\([a-z0-9]*\\)$/\\1/g'\n}\naddresses=( " + (servers.map(function(server) {
return "'" + server.host + ":" + server.port + "'";
}).join(' ')) + " )\ntimeout=" + (options.timeout || '') + "\nmd5=`compute_md5 ${addresses[@]}`\nranddir=\"" + (options.randdir || '') + "\"\nif [ -z $randir ]; then\n if [ -w /dev/shm ]; then\n randdir=\"/dev/shm/$md5\"\n else\n randdir=\"/tmp/$md5\"\n fi\nfi\nquorum_target=" + quorum_target + "\necho \"[INFO] randdir is: $randdir\"\nmkdir -p $randdir\necho 3 > $randdir/signal\necho 0 > $randdir/quorum\nfunction remove_randdir {\n for address in \"${addresses[@]}\" ; do\n host=\"${address%%:*}\"\n port=\"${address##*:}\"\n rm -f $randdir/`compute_md5 $host:$port`\n done\n}\nfunction check_quorum {\n quorum_current=`cat $randdir/quorum`\n if [ $quorum_current -ge $quorum_target ]; then\n echo '[INFO] Quorum is reached'\n remove_randdir\n fi\n}\nfunction check_timeout {\n local timeout=$1\n local randfile=$2\n wait $timeout\n rm -f $randfile\n}\nfunction wait_connection {\n local host=$1\n local port=$2\n local randfile=$3\n local count=0\n echo \"[DEBUG] Start wait for $host:$port\"\n isopen=\"echo > '/dev/tcp/$host/$port'\"\n touch \"$randfile\"\n while [[ -f \"$randfile\" ]] && ! `bash -c \"$isopen\" 2>/dev/null`; do\n ((count++))\n echo \"[DEBUG] Connection failed to $host:$port on attempt $count\" >&2\n sleep " + options.interval + "\n done\n if [[ -f \"$randfile\" ]]; then\n echo \"[DEBUG] Connection ready to $host:$port\"\n fi\n echo $(( $(cat $randdir/quorum) + 1 )) > $randdir/quorum\n check_quorum\n if [ \"$count\" -gt \"0\" ]; then\n echo \"[WARN] Status is now active, count is $count\"\n echo 0 > $randdir/signal\n fi\n}\nif [ ! -z \"$timeout\" ]; then\n host=\"${address%%:*}\"\n port=\"${address##*:}\"\n check_timeout $timeout `compute_md5 $host:$port` &\nfi\nfor address in \"${addresses[@]}\" ; do\n host=\"${address%%:*}\"\n port=\"${address##*:}\"\n randfile=$randdir/`compute_md5 $host:$port`\n wait_connection $host $port $randfile &\ndone\nwait\n# Clean up\nsignal=`cat $randdir/signal`\nremove_randdir\necho \"[INFO] Exit code is $signal\"\nexit $signal",
code_skipped: 3,
stdin_log: false
});
};
each = require('each');
misc = require('../misc');