UNPKG

domotz-remote-pawn

Version:

Domotz Agent

180 lines (162 loc) 7.73 kB
/** 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 05/10/16. * */ const PROTOCOL_NAME = 'snmp'; const DISCOVERY_SEMAPHORE = 'SNMP_SEMAPHORE'; const OID_PORT_NUMBER = '1.3.6.1.2.1.2.1.0'; const snmpCommonDiscovery = require('./snmp_common'); var snmpDiscoveryFactory = function (resourceLocator, commandBuilder, responseRendering, snmpGetterFactory) { 'use strict'; var myConsole = resourceLocator.log.decorateLogs(); var snmpInterfacesNumberStorage = resourceLocator.snmpInterfacesNumberStorage; var communitiesProvider = resourceLocator.snmpCommunitiesProvider; var interfacesBinding = resourceLocator.interfacesBindingStorage; var mutex = resourceLocator.utils.mutex; var snmpDiscoverySnapshotData = {}; var snmpCommon = snmpCommonDiscovery.snmpCommonOptions(); var async = resourceLocator.async; var host = resourceLocator.discovery.host; var ipConflict = resourceLocator.networkTools.ipConflictDetection; var snmpCheckStatus = resourceLocator.discovery.snmp_check_status_discovery; var parallelLimit = resourceLocator.settingsManager.getSetting('configuration.settings.snmp.discovery.basic.parallel_limit', 30); var deferredSnmpBulkGet = function (snmpCommand, host, options, mac, callback) { var commandOptions = snmpCommon.getSnmpOptions(options); myConsole.debug('Command Options are %s -> %s', mac, JSON.stringify(commandOptions)); var callbackCalled = false; snmpGetterFactory(snmpCommand, resourceLocator).execute(function (result) { myConsole.debug('Received result for %s -> %s', mac, JSON.stringify(result)); result.host = host; result.mac = mac; if (!callbackCalled) { callbackCalled = true; callback(null, result); } }, commandOptions); }; var lockDiscovery = function () { return mutex.lock(DISCOVERY_SEMAPHORE, 1); }; var unlockDiscovery = function () { mutex.unlock(DISCOVERY_SEMAPHORE, 1); }; var renderSnmpResults = function (results) { for (var i = 0; i < results.length; i++) { var host = results[i].host; var mac = results[i].mac; var data = null; try { data = responseRendering(resourceLocator, results[i]); } catch (e) { data = undefined; } if (host === undefined || mac === undefined || data === null) { myConsole.error('Something went wrong in rendering the SNMP result, skipping'); } else { myConsole.debug('Parsed Result: %s - |%s|', mac, JSON.stringify(data)); if (!data.error) { snmpDiscoverySnapshotData[mac] = data; if (data.oids && data.oids[OID_PORT_NUMBER]) { var number = parseInt(data.oids[OID_PORT_NUMBER], 10); snmpInterfacesNumberStorage.store(mac, number); } } } } }; var discover = function (callback, errCallback) { if (!lockDiscovery()) { myConsole.warn('WARNING: SNMP Discovery already in progress, ignoring the call'); return; } return communitiesProvider .get() .then(function (communities) { var bulkGetList = []; myConsole.debug('Found communities %s ', JSON.stringify(communities)); var oidsToDiscover = resourceLocator.settingsManager.getOidsToDiscover(); interfacesBinding.listFresh(true).forEach(function (device) { /* Filter devices by removing the ones present in L3 Discovery Deny list */ if (!host.isDeviceMacInL3DiscoveryDenyList(device.mac)) { if (!snmpCheckStatus.isSNMPEnabledForMacAddress(device.mac)) { return; } var address = device.ip; if (ipConflict.checkIfIpInConflict(address)) { myConsole.warn('Skip SNMP basic discovery for conflicting IP: %s', address); return; } var snmpCommand = commandBuilder.buildBulkGetCommand(oidsToDiscover, address); myConsole.debug('Command for device %s [mac %s] %s ', device.ip, device.mac, JSON.stringify(snmpCommand)); myConsole.debug('Communities for device %s [mac %s] %s ', device.ip, device.mac, JSON.stringify(communities[device.mac])); bulkGetList.push(deferredSnmpBulkGet.bind(null, snmpCommand, address, communities[device.mac], device.mac)); } else { myConsole.debug('Skip SNMP Basic Discovery for device %s [mac %s] in L3 Discovery Deny List', device.ip, device.mac); } }); var startTime = new Date(); async.parallelLimit(bulkGetList, parallelLimit, function (error, result) { renderSnmpResults(result); var elapsed = (new Date() - startTime) / 1000; myConsole.info('completed in %s s', elapsed); unlockDiscovery(); if (callback) { callback(snmpDiscoverySnapshotData); } }); }) .catch(function (err, err2) { unlockDiscovery(); myConsole.error('Error on snmp information processing %s %s', err, err2); if (errCallback) { errCallback(err); } }); }; var applyFunctionToSnapshotEntries = function (functionToApply) { myConsole.debug('post-processing: ' + JSON.stringify(snmpDiscoverySnapshotData)); for (var macAddress in snmpDiscoverySnapshotData) { if (snmpDiscoverySnapshotData.hasOwnProperty(macAddress)) { functionToApply(macAddress, snmpDiscoverySnapshotData[macAddress], PROTOCOL_NAME); } } }; var searchEntryIntoSnapshot = function (deviceAddress) { return snmpDiscoverySnapshotData[deviceAddress]; }; return { discover: discover, applyFunctionToSnapshotEntries: applyFunctionToSnapshotEntries, searchEntryIntoSnapshot: searchEntryIntoSnapshot, isDiscoveryInProgress: function () { return mutex.isLocked(DISCOVERY_SEMAPHORE); }, getProtocolName: function () { return PROTOCOL_NAME; }, getProtocolNameUpperCase: function () { return PROTOCOL_NAME.toUpperCase(); }, getOidForInterfaceNumber: function () { return OID_PORT_NUMBER; }, }; }; module.exports.factory = snmpDiscoveryFactory;