Files
ameos_monitoring/backend/index.js

221 lines
7.9 KiB
JavaScript

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const cors = require('cors');
const ping = require('ping');
const snmp = require('net-snmp');
const fs = require('fs');
const path = require('path');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
app.use(cors());
app.use(express.json());
const DATA_FILE = path.join(__dirname, 'monitor_data.json');
const OIDS = {
name: "1.3.6.1.2.1.1.5.0",
location: "1.3.6.1.2.1.1.6.0"
};
// Initial Data
const initialIPs = [
"10.131.213.65", "10.131.213.95", "10.131.213.124", "10.131.213.90", "10.131.213.92",
"10.131.213.88", "10.131.213.67", "10.131.213.120", "10.131.213.121", "10.131.213.171",
"10.131.213.170", "10.131.213.161", "10.131.213.162", "10.131.213.74", "10.131.213.125",
"10.131.213.69", "10.131.213.75", "10.131.213.102", "10.131.213.155", "10.131.213.85",
"10.131.213.123", "10.131.213.140", "10.131.213.142", "10.131.213.143", "10.131.213.180",
"10.131.213.181", "10.131.213.103", "10.131.213.104", "10.131.213.105", "10.131.213.106",
"10.131.213.107", "10.131.213.108", "10.131.213.110", "10.131.213.111", "10.131.213.122",
"10.131.213.126", "10.131.213.127", "10.131.213.128", "10.131.213.129", "10.131.213.130",
"10.131.213.132", "10.131.213.133", "10.131.213.134", "10.131.213.135", "10.131.213.136",
"10.131.213.137", "10.131.213.138", "10.131.213.141", "10.131.213.144", "10.131.213.145",
"10.131.213.146", "10.131.213.148", "10.131.213.150", "10.131.213.153", "10.131.213.154",
"10.131.213.156", "10.131.213.157", "10.131.213.191", "10.131.213.192", "10.131.213.200",
"10.131.213.202", "10.131.213.250", "10.131.213.249", "10.131.213.51", "10.131.213.52",
"10.131.213.53", "10.131.213.54", "10.131.213.55", "10.131.213.56", "10.131.213.57",
"10.131.213.58", "10.131.213.59", "10.131.213.61", "10.131.213.62", "10.131.213.63",
"10.131.213.64", "10.131.213.66", "10.131.213.68", "10.131.213.71", "10.131.213.72",
"10.131.213.73", "10.131.213.76", "10.131.213.77", "10.131.213.78", "10.131.213.79",
"10.131.213.81", "10.131.213.82", "10.131.213.84", "10.131.213.86", "10.131.213.87",
"10.131.213.93", "10.131.213.94", "10.131.213.96", "10.131.213.97", "10.131.213.99",
"10.131.213.147", "10.131.213.146", "10.131.213.155", "10.131.213.141", "10.131.213.131",
"10.131.213.152", "10.131.213.154", "10.131.213.145", "10.131.213.151", "10.131.213.148",
"10.131.213.149", "10.131.213.153", "10.131.213.201", "10.131.213.35", "10.131.213.32",
"10.131.213.24", "10.131.213.25", "10.131.213.31", "10.131.213.34", "10.131.213.41",
"10.131.213.254", "10.131.213.11", "10.131.213.12", "10.131.213.50", "10.131.213.113",
"10.131.213.112", "10.131.213.115", "10.131.213.114", "10.131.213.117", "10.131.213.118",
"10.131.213.119", "10.131.213.101"
];
// Remove duplicates
const uniqueIPs = [...new Set(initialIPs)];
let store = {
ips: uniqueIPs,
communities: ['public', 'private'], // Default communities
results: {}, // { ip: { alive: bool, name: str, location: str, community: str, lastCheck: timestamp } }
};
// Load data
if (fs.existsSync(DATA_FILE)) {
try {
store = JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'));
} catch (e) {
console.error("Failed to load data", e);
}
} else {
// If starting fresh, initialize results structure
store.ips.forEach(ip => {
store.results[ip] = { alive: false, name: null, location: null, community: null, lastCheck: 0 };
});
}
const saveData = () => {
fs.writeFileSync(DATA_FILE, JSON.stringify(store, null, 2));
};
// Helper for SNMP
const getSnmpData = (ip, community) => {
return new Promise((resolve, reject) => {
// User requested v2c
const session = snmp.createSession(ip, community, {
timeout: 5000,
retries: 1,
version: snmp.Version2c
});
session.get([OIDS.name, OIDS.location], (error, varbinds) => {
session.close();
if (error) {
reject(error);
} else {
const name = snmp.isVarbindError(varbinds[0]) ? null : varbinds[0].value.toString();
const location = snmp.isVarbindError(varbinds[1]) ? null : varbinds[1].value.toString();
resolve({ name, location });
}
});
});
};
// Check a single IP
const checkIp = async (ip) => {
const timestamp = Date.now();
// Ping with slightly higher timeout
let isAlive = false;
try {
const res = await ping.promise.probe(ip, { timeout: 2 });
isAlive = res.alive;
} catch (e) {
console.error(`Ping error ${ip}:`, e);
}
const currentResult = store.results[ip] || {};
let newResult = { ...currentResult, alive: isAlive, lastCheck: timestamp };
if (isAlive) {
// SNMP
// Try last successful community first
let community = currentResult.community;
let pdu = null;
if (community) {
try {
pdu = await getSnmpData(ip, community);
} catch (e) {
console.log(`[${ip}] Community '${community}' failed (${e.message}), trying others...`);
community = null; // Reset if failed
}
}
// If no community or failed, try all global communities
if (!community) {
console.log(`[${ip}] Probing ${store.communities.length} communities...`);
for (const c of store.communities) {
try {
pdu = await getSnmpData(ip, c);
community = c;
console.log(`[${ip}] Found new community: '${c}'`);
break;
} catch (e) {
console.log(`[${ip}] '${c}' failed: ${e.message}`);
}
}
}
if (pdu) {
newResult = { ...newResult, name: pdu.name, location: pdu.location, community: community };
} else {
console.log(`[${ip}] No valid community found (Alive: true).`);
}
}
store.results[ip] = newResult;
io.emit('update', { ip, data: newResult });
};
const monitorLoop = async () => {
console.log(`Starting monitoring cycle for ${store.ips.length} IPs using ${store.communities.length} communities...`);
// Process in batches to speed up (parallelism) but avoid network congestion
const BATCH_SIZE = 10;
for (let i = 0; i < store.ips.length; i += BATCH_SIZE) {
const batch = store.ips.slice(i, i + BATCH_SIZE);
await Promise.all(batch.map(ip => checkIp(ip)));
}
saveData();
console.log("Cycle finished.");
setTimeout(monitorLoop, 5000); // Run every 5 seconds
};
// API
app.get('/api/status', (req, res) => {
res.json({
ips: store.ips,
results: store.results,
communities: store.communities
});
});
app.post('/api/communities', (req, res) => {
const { communities } = req.body;
if (Array.isArray(communities)) {
store.communities = communities;
saveData();
res.json({ success: true });
} else {
res.status(400).json({ error: "Invalid format" });
}
});
app.post('/api/ips', (req, res) => {
const { ips } = req.body;
if (Array.isArray(ips)) {
// Sync results
store.ips = ips;
// Clean up old results
const newResults = {};
ips.forEach(ip => {
newResults[ip] = store.results[ip] || { alive: false, name: null, location: null, community: null, lastCheck: 0 };
});
store.results = newResults;
saveData();
res.json({ success: true });
} else {
res.status(400).json({ error: "Invalid format" });
}
});
const PORT = 3001;
server.listen(PORT, () => {
console.log(`Backend listening on port ${PORT}`);
monitorLoop();
});