domotz-remote-pawn
Version:
Domotz Agent
158 lines (134 loc) • 5.07 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2021 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 Fausto Lelli <fausto@domotz.com>
*/
var path = require('path');
var os = require('os');
const OID_DB_REMOTE_ENDPOINT = '/overlay/device-catalog';
const OVERLAY_DB_SEMAPHORE = 'SNMP_OVERLAY_DEVICE_DB_SEMAPHORE';
const OID_DB_FILE = path.join(os.tmpdir(), 'overlay_device_db.json');
var snmpOverlayDeviceDBFactory = function (resourceLocator) {
'use strict';
var fileUtils = resourceLocator.utils.file;
var crypto = resourceLocator.crypto;
var mutex = resourceLocator.utils.mutex;
var engineRequest = resourceLocator.engineRequest;
var forceOverlayDiscovery = require('../../events/handler/snmpOverlayDiscovery').forceNextDiscovery;
var myConsole = resourceLocator.log.decorateLogs();
// the following variables must be invalidated
var currentMD5 = null;
var currentDB = null;
var lockDiscovery = function () {
return mutex.lock(OVERLAY_DB_SEMAPHORE, 1);
};
var unlockDiscovery = function () {
mutex.safeUnlock(OVERLAY_DB_SEMAPHORE, 1);
};
function getOverlayDeviceDBFromFile() {
var content = fileUtils.readFile(OID_DB_FILE);
if (content) {
try {
return JSON.parse(content);
} catch (e) {
myConsole.info('Can not parse db file: %s', e);
}
}
return null;
}
function getOverlayDeviceDB() {
if (currentDB) {
return currentDB;
}
var db = getOverlayDeviceDBFromFile();
if (db && db.hasOwnProperty('devices')) {
currentDB = db.devices;
return db.devices;
} else {
return null;
}
}
function saveOverlayDB(db) {
fileUtils.writeFileSafe(OID_DB_FILE, db);
currentMD5 = null;
currentDB = null;
getOverlayMD5();
}
function getOverlayMD5() {
if (currentMD5) {
return currentMD5;
}
var devices = getOverlayDeviceDB();
if (devices) {
var contentMD5 = '';
if (devices.length > 0) {
contentMD5 = devices[0].device_hw_address + '-' + devices[0].overlay_id;
}
for (var i = 1; i < devices.length; i++) {
contentMD5 += ',' + devices[i].device_hw_address + '-' + devices[i].overlay_id;
}
currentMD5 = crypto.createHash('md5').update(contentMD5).digest('hex');
myConsole.info('New MD5 computed: %s ', currentMD5);
return currentMD5;
} else {
return null;
}
}
function invalidate() {
myConsole.info('Force check of Overlay Device DB cache');
currentMD5 = null;
checkOverlayDeviceDB(true);
}
function checkOverlayDeviceDB(forceDiscoveryOnChange) {
if (!lockDiscovery()) {
myConsole.warn('WARNING: SNMP Overlay DB Check already in progress, ignoring the call');
return;
}
var currentMD5 = getOverlayMD5();
var url = OID_DB_REMOTE_ENDPOINT;
if (currentMD5 !== null) {
url = OID_DB_REMOTE_ENDPOINT + '?md5=' + currentMD5;
}
myConsole.info('Check MIB Overlay DB, url: ' + url);
engineRequest
.sendWithPromise(url, 'GET', null, function (response) {
myConsole.debug('Received response code : ' + response.statusCode);
if (response.statusCode === 304) {
myConsole.info('MIB Overlay DB is unchanged, using cached info ');
} else {
myConsole.info('Writing MIB Overlay DB to filesystem');
saveOverlayDB(response.body);
if (forceDiscoveryOnChange) {
forceOverlayDiscovery(resourceLocator);
}
}
})
.catch(function (err) {
myConsole.error('Can not retrieve MIB Overlay DB ' + err);
})
.finally(function () {
unlockDiscovery();
});
}
return {
getOverlayMD5: getOverlayMD5,
getOverlayDeviceDB: getOverlayDeviceDB,
checkOverlayDeviceDB: checkOverlayDeviceDB,
invalidate: invalidate,
};
};
module.exports.factory = snmpOverlayDeviceDBFactory;