domotz-remote-pawn
Version:
Domotz Agent
133 lines (122 loc) • 4.66 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz Ltd
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
**/
/**
* Created by Georgi Tsatsev <gtsatsev@domotz.com> on 14/8/17.
*/
const SSH_EXEC_TIMEOUT = 2000;
const MODULE = 'SSH Send Factory ';
var factory = function (async, q, ssh, lodash) {
function logCommand(message) {
// Removing passwords and log ssh Command payload
var payload = JSON.parse(JSON.stringify(message.payload));
var command = ' - Executing command';
if (typeof payload.commandList !== 'undefined') {
for (var i = 0; i < payload.commandList.length; i++) {
delete payload.commandList[i].command_params.password;
}
command = command + ' sshBulkSend ';
} else {
command = command + ' sshSend ';
delete payload.password;
}
return command + JSON.stringify(payload);
}
function sshSend(payload, correlationId) {
var command = payload.cmd + ' ' + (payload.args || []).join(' ');
return ssh
.exec(command, getOptsForSshCommand(payload), correlationId)
.then(function (result) {
return { output: result };
})
.catch(function (error) {
return {
error: error.message,
error_code: error.code,
};
});
}
function sshBulkSend(payload) {
return executeCommands(payload)
.then(function (result) {
return { output: result };
})
.catch(function (error) {
return { error: error.message || error };
});
}
function executeCommands(payload) {
var commandList = payload.commandList || [];
var maxParallel = payload.maxParallelExecutors || 4;
var deferred = q.defer();
executeCommandAsync(commandList, maxParallel, deferred);
return deferred.promise;
}
function executeCommandAsync(commandList, maxParallel, deferred) {
function commandExecutor(cmd, cb) {
ssh.exec(cmd.command, getOptsForSshCommand(cmd.command_params))
.then(function (stdout) {
var result = { command_id: cmd.command_id, output: stdout };
cb(null, result);
})
.catch(function (error) {
cb(error, null); //return a null value in the final array in case of error
});
}
if (commandList.length === 0) {
deferred.reject('command list was empty');
}
var commands = [];
for (var i = 0; i < commandList.length; i++) {
commands.push(commandExecutor.bind(null, commandList[i]));
}
async.parallelLimit(commands, maxParallel, function (err, details) {
var commandResultsDict = {};
if (err) {
deferred.reject(err);
return;
}
details
.filter(function (elem) {
return elem !== null;
})
.forEach(function (result) {
commandResultsDict[result.command_id] = result.output;
});
deferred.resolve(commandResultsDict);
});
}
function getOptsForSshCommand(payload) {
var sshOptions = payload.ssh_options || {};
var DefaultOpts = {
user: payload.username,
password: payload.password,
host: payload.host,
port: payload.port,
host_key_checking: 'no',
disable_pseudo_tty_alloc: true,
log_prefix: MODULE,
ttl: payload.timeout ? payload.timeout : SSH_EXEC_TIMEOUT,
};
return lodash.extend(DefaultOpts, sshOptions);
}
return {
sshBulkSend: sshBulkSend,
sshSend: sshSend,
logCommand: logCommand,
};
};
module.exports.factory = factory;