UNPKG

domotz-remote-pawn

Version:

Domotz Agent

192 lines (162 loc) 6.01 kB
/** 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/catalog'; const OVERLAY_DB_SEMAPHORE = 'SNMP_OVERLAY_DB_SEMAPHORE'; const OID_DB_FILE = path.join(os.tmpdir(), 'overlay_db.json'); var snmpOverlayDBFactory = function (resourceLocator) { 'use strict'; var fileUtils = resourceLocator.utils.file; var crypto = resourceLocator.crypto; var mutex = resourceLocator.utils.mutex; var engineRequest = resourceLocator.engineRequest; var myConsole = resourceLocator.log.decorateLogs(); // the following variables must be invalidated var currentMD5 = null; var overlayMap = {}; var lockDiscovery = function () { return mutex.lock(OVERLAY_DB_SEMAPHORE, 1); }; var unlockDiscovery = function () { mutex.safeUnlock(OVERLAY_DB_SEMAPHORE, 1); }; function getOverlay(overlayId) { if (overlayMap.hasOwnProperty(overlayId)) { return overlayMap[overlayId]; } var content = getOverlayDB(); if (content && content.hasOwnProperty('overlays')) { var overlays = content.overlays; var min = 0; var max = overlays.length - 1; var guess; while (min <= max) { guess = Math.floor((max + min) / 2); if (overlays[guess].id === overlayId) { overlayMap[overlayId] = overlays[guess]; return overlays[guess]; } else if (overlays[guess].id < overlayId) { min = guess + 1; } else { max = guess - 1; } } return null; } else { return null; } } function getOverlayDB() { 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 saveOverlayDB(db) { fileUtils.writeFileSafe(OID_DB_FILE, db); currentMD5 = null; overlayMap = {}; getOverlayMD5(); } function computeSingleOverlayMD5(overlay) { var overlayContent = overlay.id; var oidScalar = Object.keys(overlay.oid_scalar); if (oidScalar && oidScalar.length > 0) { oidScalar.sort(); for (var iScalar = 0; iScalar < oidScalar.length; iScalar++) { overlayContent += oidScalar[iScalar]; } } var oidColumn = Object.keys(overlay.oid_column); if (oidColumn && oidColumn.length > 0) { oidColumn.sort(); for (var iColumn = 0; iColumn < oidColumn.length; iColumn++) { overlayContent += oidColumn[iColumn]; } } return crypto.createHash('md5').update(overlayContent).digest('hex'); } function getOverlayMD5() { if (currentMD5) { return currentMD5; } var content = getOverlayDB(); if (content && content.hasOwnProperty('overlays')) { var overlays = content.overlays; var contentMD5 = ''; for (var i = 0; i < overlays.length; i++) { contentMD5 += computeSingleOverlayMD5(overlays[i]); } 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 DB cache'); currentMD5 = null; checkOverlayDB(); } function checkOverlayDB() { 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: %s', url); engineRequest .sendWithPromise(url, 'GET', null, function (response) { myConsole.debug('Received response code : %s', 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); } }) .catch(function (err) { myConsole.error('Can not retrieve MIB Overlay DB %s', err); }) .finally(function () { unlockDiscovery(); }); } return { getOverlay: function (overlayId) { return getOverlay(overlayId); }, getOverlayMD5: getOverlayMD5, checkOverlayDB: checkOverlayDB, invalidate: invalidate, }; }; module.exports.factory = snmpOverlayDBFactory;