domotz-remote-pawn
Version:
Domotz Agent
163 lines (141 loc) • 7.08 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz UK LLP
*
* 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/>.
**/
const DEFAULT_MAX_REPETITIONS = 24;
var SUBTREE_HARD_TIMEOUT_SETTING = 'configuration.settings.snmp.hard_timeout.subtree';
var DEFAULT_SUBTREE_HARD_TIMEOUT_VALUE = 300000;
var SUBTREE_SOFT_TIMEOUT_SETTING = 'configuration.settings.snmp.soft_timeout.subtree';
var DEFAULT_SUBTREE_SOFT_TIMEOUT_VALUE = 45000;
var TimedSnmpSession = require('./timedSnmpSession');
var snmpSubtrees = function (message, resourceLocator) {
var snmp = resourceLocator.netSnmp;
var cmdUtils = resourceLocator.utils.command;
var snmpCommon = resourceLocator.snmpCommon;
var cid = message.correlationId;
var settingsManager = resourceLocator.settingsManager;
var myConsole = resourceLocator.log.decorateLogs().decorate(String(cid));
var options = message.payload;
var oidsMapping = cmdUtils.extractFromOptions(options, 'oids', {});
var host = cmdUtils.extractFromOptions(options, 'host', 'localhost');
var oids = snmpCommon.extractOids(oidsMapping);
var transformer = message.customTransformer ? message.customTransformer : snmpCommon.transformer;
var hardTimeout = parseInt(settingsManager.getSetting(SUBTREE_HARD_TIMEOUT_SETTING, DEFAULT_SUBTREE_HARD_TIMEOUT_VALUE));
var softTimeout = parseInt(settingsManager.getSetting(SUBTREE_SOFT_TIMEOUT_SETTING, DEFAULT_SUBTREE_SOFT_TIMEOUT_VALUE));
options.timeout = options.timeout || softTimeout;
myConsole.debug('Hard Timeout %s, Soft Timeout %s ', hardTimeout, options.timeout);
// Adjust the default
var maxRepetitions = options.maxRepetitions || DEFAULT_MAX_REPETITIONS;
delete options.maxRepetitions;
return {
execute: function (callback, authProvider) {
var bindings = snmpCommon.getInterfaceBindings(options, resourceLocator);
var snmpSession = null;
try {
snmpSession = snmpCommon.getSession(bindings, host, options, authProvider);
} catch (error) {
callback({ error: error.toString() });
return;
}
var timedSnmpSession = new TimedSnmpSession(snmpSession, { host: host, oids: oids }, myConsole);
myConsole.debug('using version %d', snmpSession.version);
var response = { oids: {} };
var waiting = {};
for (var j = 0; j < oids.length; j++) {
oid = oids[j];
response.oids[oid] = { error: 'Unrecognized oid' };
}
snmpSession.on('error', function (error) {
var errorMessage = error.toString();
myConsole.error('(socket error) %s', errorMessage);
try {
snmpSession.close();
} catch (error) {
myConsole.error('cannot close session: ' + error);
}
});
function done(oid) {
return function (error) {
myConsole.debug('response received for oid: %s', oid);
if (error) {
myConsole.info('error retrieving oid: %s => %s', oid, error.message);
response.oids[oid] = { error: error };
}
waiting[oid] = false;
for (var i = 0; i < oids.length; i++) {
if (waiting[oids[i]]) {
myConsole.debug('still waiting for oid: %s', oids[i]);
return;
}
}
if (response && response.error && response.error.stack) {
delete response.error.stack;
}
myConsole.debug('command execution concluded, yielding result of %s bytes', JSON.stringify(response).length);
try {
snmpSession.close();
} catch (error) {
myConsole.error('cannot close session: %s', error);
} finally {
callback(response);
}
};
}
function valueArrived(oid) {
return function (varbinds) {
myConsole.verbose('varbind callback invoked for oid: %s', oid);
if (response.oids[oid].error !== undefined) {
response.oids[oid] = {};
}
var values = 0;
for (var i = 0; i < varbinds.length; i++) {
if (snmp.isVarbindError(varbinds[i])) {
myConsole.warn('error retrieving oid: %s => varbind error: %s', oid, snmp.varbindError(varbinds[i]));
response.oids[oid] = { error: snmp.varbindError(varbinds[i]) };
break;
} else {
var subOid = varbinds[i].oid.substring(oid.length + 1);
var value = transformer(oidsMapping[oid])(varbinds[i].value, varbinds[i].type);
myConsole.verbose('SNMP value arrived: [%s].[%s]: %s', oid, subOid, value);
response.oids[oid][subOid] = value;
values++;
}
}
myConsole.verbose(
'%s values arrived for oid %s. Original data: %s. Result: %s',
values,
oid,
JSON.stringify(varbinds),
JSON.stringify(response)
);
};
}
var oid;
for (var i = 0; i < oids.length; i++) {
oid = oids[i];
timedSnmpSession.subtree(oid, maxRepetitions, valueArrived(oid), done(oid), hardTimeout);
}
myConsole.debug('version (%d) => request to host %s for oids: %s', options.version, host, JSON.stringify(oids));
// Initialise structures for multi oid retrieval
for (var k = 0; k < oids.length; k++) {
waiting[oids[k]] = true;
}
},
describe: function () {
return 'snmpSubtrees - ' + host + ' - ' + JSON.stringify(oids);
},
};
};
module.exports.command = snmpSubtrees;