domotz-remote-pawn
Version:
Domotz Agent
167 lines (150 loc) • 6.32 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/>.
*
*
* This module has the responsibility to coordinate both the delta and the full IP devices
* discovery.
* It calls the InterfacesBindingStorage to update the interfaces binding discovered by the
* BindingDiscoverer. Then it sends the results to the engine.
*
* Created by Iacopo Papalini <iacopo@domotz.com> on 18/05/16.
*/
const q = require('q');
module.exports.factory = function (
event,
bindingDiscoverer,
interfacesBinding,
engineReportingStrategy,
discoveryRetry,
host,
log,
diagnostic,
telemetry,
utils,
settingsManager,
resourceLocator
) {
'use strict';
var performing = false;
var iteration = 0;
var initialTime = 0;
var telemetry_chunk_size = settingsManager.getSetting('configuration.settings.telemetry.discovery.report_chunk_size', 10);
var myConsole = log.decorateLogs();
function checkStall() {
var missedDiscoveryCounter = diagnostic.getMissedDiscoveryCounter();
var skipped_discovery_threshold = settingsManager.getSetting('configuration.settings.discovery.skipped_threshold', 18);
if (missedDiscoveryCounter >= skipped_discovery_threshold) {
myConsole.error('(%d): Discovery stopped for %d cycles, restart the agent', iteration, missedDiscoveryCounter);
setTimeout(utils.proc.gracefulShutdown, 1000);
}
}
var runningIteration = null;
function performDiscovery() {
diagnostic.incDiscoveryIterationCounter();
if (performing) {
diagnostic.incMissedDiscoveryCounter();
myConsole.warn(
'Avoiding double run of IP network devices discovery skipped %d cycles; running iteration=%s',
diagnostic.getMissedDiscoveryCounter(),
runningIteration
);
checkStall();
return;
}
diagnostic.resetMissedDiscoveryCounter();
iteration++;
var iterConsole = log.decorateLogs('iter.' + String(iteration), myConsole);
performing = true;
runningIteration = iteration;
iterConsole.info('START OF IP network devices discovery');
function finished(step) {
return function (param) {
initialTime = telemetry.updateTelemetry('discovery', step, initialTime);
iterConsole.verbose('%s finished', step);
return param;
};
}
function discoveryRetryOnStaleDevices() {
var deferred = q.defer();
discoveryRetry.retryOnStaleBindingsForAllInterfaces(function () {
deferred.resolve();
});
return deferred.promise;
}
function checkEmergencyInterfaceEnabled() {
var emergencyNetworkRestore = resourceLocator.emergencyNetworkRestore;
var deferred = q.defer();
if (emergencyNetworkRestore.isEmergencyInterfaceEnabled()) {
myConsole.info('Emergency interface is enable - skip Discovery');
deferred.reject({ message: 'Emergency interface is enable - skip Discovery', stack: null });
}
else {
deferred.resolve();
}
return deferred.promise;
}
initialTime = new Date().getTime();
return interfacesBinding
.assureInitialized()
.then(checkEmergencyInterfaceEnabled)
.then(finished('checkEmergencyInterfaceEnabled'))
.then(interfacesBinding.staleAll)
.then(setIteration)
.then(host.resolveExternalHosts)
.then(bindingDiscoverer.assureInterfaces)
.then(bindingDiscoverer.discoverAll)
.then(finished('bindingDiscoverer.discoverAll'))
.then(interfacesBinding.setFreshDiscoveredBindings)
.then(finished('interfacesBinding.setFreshDiscoveredBinding'))
.then(discoveryRetryOnStaleDevices)
.then(finished('discoveryRetry.retryOnStaleBindings'))
.then(engineReportingStrategy.reportDiscovery)
.then(finished('engineReportingStrategy.reportDiscovery'))
.then(interfacesBinding.purgeStale)
.then(finished('interfacesBinding.purgeStale'))
.then(interfacesBinding.saveLastSnapshot)
.then(finished('interfacesBinding.saveLastSnapshot'))
.then(event.endFastDeviceDiscovery)
.then(finished('event.endFastDeviceDiscovery'))
.catch(errorHandler)
.finally(function () {
iterConsole.info('END OF IP network devices discovery ');
performing = false;
diagnostic.incActualDiscoveryCounter();
telemetry.incTelemetryCounter('discovery');
if(telemetry.getTelemetryCounter('discovery') >= telemetry_chunk_size) {
telemetry.reportTelemetry('discovery');
}
});
}
function setIteration() {
host.setIteration(iteration);
bindingDiscoverer.setIteration(iteration);
discoveryRetry.setIteration(iteration);
engineReportingStrategy.setIteration(iteration);
}
function errorHandler(err) {
myConsole.error('Iteration %s, Discovery error: %s', iteration, err.message);
if (err.code && err.code === 'DISCOVERY_EMPTY') {
myConsole.error("All discovery commands failed");
return;
}
myConsole.error(err.stack);
}
return {
performDiscovery: performDiscovery,
};
};