domotz-remote-pawn
Version:
Domotz Agent
172 lines (149 loc) • 7.14 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/>.
**/
/**
* Created by Massimiliano Cuzzoli <massi@domotz.com> on 18/10/16.
*/
const DISCOVERY_SEMAPHORE = 'SNMP_INTERFACE_SEMAPHORE';
const OIDS_TO_DISCOVER = {
'1.3.6.1.2.1.2.2.1.3': 'int', // ifType
'1.3.6.1.2.1.31.1.1.1.1': 'string', // ifName
'1.3.6.1.2.1.2.2.1.2': 'string', // ifDescription
'1.3.6.1.2.1.31.1.1.1.15': 'int', // ifHighSpeed
'1.3.6.1.2.1.31.1.1.1.18': 'string', // ifAlias
'1.3.6.1.2.1.2.2.1.7': 'int', // ifAdminStatus
'1.3.6.1.2.1.2.2.1.8': 'int', // ifOperationalStatus
'1.3.6.1.2.1.2.2.1.10': 'int', // ifInOctets
'1.3.6.1.2.1.2.2.1.16': 'int', // ifOutOctets
'1.3.6.1.2.1.2.2.1.13': 'int', // ifInDiscards
'1.3.6.1.2.1.2.2.1.19': 'int', // ifOutDiscards
'1.3.6.1.2.1.2.2.1.14': 'int', // ifInErrors
'1.3.6.1.2.1.2.2.1.20': 'int' // ifOutErrors
};
const DEFAULT_READ_COMMUNITY = 'public';
const SNMP_SUBTREE_TIMEOUT = 20000;
var snmpDiscoveryFactory = function (resourceLocator, commandBuilder, responseRendering, snmpSubtreeFactory) {
"use strict";
var mutex = resourceLocator.utils.mutex;
var q = resourceLocator.q;
var engineRequest = resourceLocator.engineRequest;
var discoveryUtils = resourceLocator.discovery.utils;
var hostInfo = resourceLocator.devices.info;
var deviceDetailsByIp = {};
var ipToId = {};
var snmpDiscoverySnapshotData = {};
var deferredSnmpSubtree = function (snmpCommand, host) {
var deferred = q.defer();
snmpSubtreeFactory(snmpCommand, resourceLocator).execute(
function (result) {
console.debug('SNMP Interface Discovery:: Received result for %s -> %s', host, JSON.stringify(result));
result['host'] = host;
result['timestamp'] = new Date().toISOString();
deferred.resolve(result);
}
);
return deferred.promise;
};
var lock_discovery = function () {
return mutex.lock(DISCOVERY_SEMAPHORE, 1);
};
var unlock_discovery = function () {
mutex.unlock(DISCOVERY_SEMAPHORE, 1);
};
var gatherInterfaceInfoForDevice = function (ipAddress, community) {
var snmpCommand = commandBuilder.buildSubtreeCommand(OIDS_TO_DISCOVER, ipAddress,
community || DEFAULT_READ_COMMUNITY, SNMP_SUBTREE_TIMEOUT);
console.info("SNMP Interface Discovery:: Gathering information for %s", ipAddress);
return deferredSnmpSubtree(snmpCommand, ipAddress);
};
var renderDiscoveryData = function (rawResultList) {
for (var i = 0; i < rawResultList.length; i++) {
var dataToRender = rawResultList[i];
var ipAddress = dataToRender.host;
console.debug("SNMP Interface Discovery:: Rendering discovery data for %s", dataToRender.host);
snmpDiscoverySnapshotData[ipAddress] = responseRendering(dataToRender);
}
};
var _do_discovery = function (callback, errCallback) {
snmpDiscoverySnapshotData = {};
ipToId = discoveryUtils.getDevicesMaps().ipToId;
deviceDetailsByIp = discoveryUtils.getDetailsFieldsForDevices(['interface_number_snmp', 'snmp_read_community']);
var devicePromises = [];
for (var ipAddress in deviceDetailsByIp) {
if (deviceDetailsByIp.hasOwnProperty(ipAddress) && deviceDetailsByIp[ipAddress] &&
deviceDetailsByIp[ipAddress].interface_number_snmp) {
devicePromises.push(gatherInterfaceInfoForDevice(ipAddress,
deviceDetailsByIp[ipAddress].snmp_read_community));
}
}
q.all(devicePromises)
.then(function (results) {
renderDiscoveryData(results);
unlock_discovery();
if (callback) callback(snmpDiscoverySnapshotData, ipToId);
})
.catch(function (err) {
unlock_discovery();
console.error("SNMP Interface Discovery:: Error on snmp information processing", err);
if (errCallback) errCallback(err);
});
};
var discover = function (callback, errCallback, forceInvalidateList) {
if (!lock_discovery()) {
console.warn("WARNING: SNMP Interface Discovery already in progress, ignoring the call");
return;
}
var deviceListGetter = (forceInvalidateList) ? hostInfo.invalidateList : hostInfo.getList;
deviceListGetter().then(function (deviceList) {
console.info("SNMP Interface Discovery: %d devices present", Object.keys(deviceList).length);
return _do_discovery(callback, errCallback);
});
};
var sendDiscoveryDataToEngine = function (discoveryData, ipToIdMap) {
console.info("SNMP Interface Discovery: records to send %d", Object.keys(discoveryData).length);
try {
for (var ipAddress in discoveryData) {
if (discoveryData.hasOwnProperty(ipAddress) && discoveryData[ipAddress]
&& discoveryData[ipAddress].oids) {
var deviceId = ipToIdMap[ipAddress];
if (!deviceId) {
console.info("SNMP Interface Discovery: ID not found for %s", ipAddress);
continue;
}
console.info("SNMP Interface Discovery: Sending data for deviceId=%d", deviceId);
engineRequest.sendWithPromise('/device/' + deviceId + '/interface/snmp-info', 'POST',
discoveryData[ipAddress])
.catch(function (e) {
console.error("Error sending snmp data to Engine: %s", JSON.stringify(e));
});
}
}
} catch(e) {
console.error("Error preparing data to send %s", JSON.stringify(e));
}
};
return {
discover: discover,
sendDiscoveryDataToEngine: sendDiscoveryDataToEngine,
isDiscoveryInProgress: function () {
return mutex.isLocked(DISCOVERY_SEMAPHORE);
},
getCurrentSnapshotData: function () {
return snmpDiscoverySnapshotData;
}
};
};
module.exports.factory = snmpDiscoveryFactory;