@daemonitor/plugins 1.1.19 → 1.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -92,7 +92,7 @@ function decodeSnmp(s) {
|
|
|
92
92
|
}
|
|
93
93
|
async function snmpGet(t, oid, timeout = 8000) {
|
|
94
94
|
try {
|
|
95
|
-
const { stdout } = await pexec("snmpget", ["-v", t.version || "2c", "-c", t.community || "public", "-
|
|
95
|
+
const { stdout } = await pexec("snmpget", ["-v", t.version || "2c", "-c", t.community || "public", "-Oevq", "-t", "2", "-r", "1", t.ip, oid], { timeout });
|
|
96
96
|
const raw = stdout.trim().replace(/^"|"$/g, "");
|
|
97
97
|
if (!raw || /No Such|no response|Timeout/i.test(raw))
|
|
98
98
|
return null;
|
|
@@ -104,7 +104,7 @@ async function snmpGet(t, oid, timeout = 8000) {
|
|
|
104
104
|
}
|
|
105
105
|
async function snmpWalk(t, oid, timeout = 10000) {
|
|
106
106
|
try {
|
|
107
|
-
const { stdout } = await pexec("snmpwalk", ["-v", t.version || "2c", "-c", t.community || "public", "-
|
|
107
|
+
const { stdout } = await pexec("snmpwalk", ["-v", t.version || "2c", "-c", t.community || "public", "-Oeqv", "-t", "2", "-r", "1", t.ip, oid], { timeout });
|
|
108
108
|
return stdout.split("\n").map((l) => decodeSnmp(l.trim().replace(/^"|"$/g, ""))).filter(Boolean);
|
|
109
109
|
}
|
|
110
110
|
catch {
|
|
@@ -168,20 +168,38 @@ async function collectDevice(t) {
|
|
|
168
168
|
snmpGet(t, SYS.descr),
|
|
169
169
|
snmpGet(t, SYS.name),
|
|
170
170
|
snmpGet(t, SYS.uptime),
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
snmpWalkIndexed(t, SYS.ifOper),
|
|
172
|
+
snmpWalkIndexed(t, SYS.ifAdmin),
|
|
173
173
|
]);
|
|
174
174
|
if (descr == null && name == null && !oper.length) {
|
|
175
175
|
return { name: t.name, ip: t.ip, kind: t.kind || "device", reachable: false };
|
|
176
176
|
}
|
|
177
|
+
// Index the link-state walks by ifIndex so each interface can carry its own
|
|
178
|
+
// up/down (positional zipping breaks whenever the two walks differ in length).
|
|
179
|
+
const byIndex = (rows) => {
|
|
180
|
+
const m = {};
|
|
181
|
+
for (const r of rows)
|
|
182
|
+
m[r.idx] = r.val;
|
|
183
|
+
return m;
|
|
184
|
+
};
|
|
185
|
+
const operByIdx = byIndex(oper);
|
|
186
|
+
const adminByIdx = byIndex(admin);
|
|
187
|
+
// Values arrive numeric (-Oe), but tolerate an enum rendering like "up(1)"
|
|
188
|
+
// from any agent/MIB combination that slips one through.
|
|
189
|
+
const enumNum = (v) => {
|
|
190
|
+
if (v == null)
|
|
191
|
+
return undefined;
|
|
192
|
+
const m = /\((\d+)\)\s*$/.exec(v) || /^\s*(-?\d+)\s*$/.exec(v);
|
|
193
|
+
return m ? Number(m[1]) : undefined;
|
|
194
|
+
};
|
|
177
195
|
// Only count ADMIN-enabled ports; an enabled port that's operationally down is
|
|
178
196
|
// a real link-down (ignore the many disabled ports on a big switch).
|
|
179
197
|
let portsTotal = 0;
|
|
180
198
|
let portsUp = 0;
|
|
181
|
-
for (
|
|
182
|
-
if (
|
|
199
|
+
for (const idx of Object.keys(adminByIdx)) {
|
|
200
|
+
if (enumNum(adminByIdx[idx]) === 1) {
|
|
183
201
|
portsTotal++;
|
|
184
|
-
if (
|
|
202
|
+
if (enumNum(operByIdx[idx]) === 1)
|
|
185
203
|
portsUp++;
|
|
186
204
|
}
|
|
187
205
|
}
|
|
@@ -231,15 +249,9 @@ async function collectDevice(t) {
|
|
|
231
249
|
// "internet traffic". Without one, the headline is left undefined rather than
|
|
232
250
|
// reporting a number we know to be wrong.
|
|
233
251
|
const PSEUDO = /^(lo|imq\d*|itf\d*|ifb\d*|sit\d*|gre\d*|teql\d*|tunl\d*)$/i;
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
m[r.idx] = r.val;
|
|
238
|
-
return m;
|
|
239
|
-
};
|
|
240
|
-
const nameByIdx = idxOf(ifNames);
|
|
241
|
-
const inByIdx = idxOf(hcInIdx);
|
|
242
|
-
const outByIdx = idxOf(hcOutIdx);
|
|
252
|
+
const nameByIdx = byIndex(ifNames);
|
|
253
|
+
const inByIdx = byIndex(hcInIdx);
|
|
254
|
+
const outByIdx = byIndex(hcOutIdx);
|
|
243
255
|
const now = Date.now();
|
|
244
256
|
const prevIf = netPrevIf[t.ip] || {};
|
|
245
257
|
const nextIf = {};
|
|
@@ -261,7 +273,11 @@ async function collectDevice(t) {
|
|
|
261
273
|
outBps = Math.round((cout - p.out) / dt);
|
|
262
274
|
}
|
|
263
275
|
}
|
|
264
|
-
|
|
276
|
+
// ifOperStatus 1=up, ifAdminStatus 1=enabled. A link that's admin-enabled but
|
|
277
|
+
// operationally down is a real fault; an admin-disabled port is just off.
|
|
278
|
+
const adminUp = adminByIdx[idx] != null ? enumNum(adminByIdx[idx]) === 1 : undefined;
|
|
279
|
+
const linkUp = operByIdx[idx] != null ? enumNum(operByIdx[idx]) === 1 : undefined;
|
|
280
|
+
interfaces.push({ name, inBps, outBps, up: linkUp, adminUp });
|
|
265
281
|
}
|
|
266
282
|
netPrevIf[t.ip] = nextIf;
|
|
267
283
|
// Headline = the WAN link when the target names one.
|
|
@@ -298,7 +314,7 @@ async function collectDevice(t) {
|
|
|
298
314
|
// hrStorage table entries for the data volumes.
|
|
299
315
|
async function snmpWalkIndexed(t, oid, timeout = 10000) {
|
|
300
316
|
try {
|
|
301
|
-
const { stdout } = await pexec("snmpwalk", ["-v", t.version || "2c", "-c", t.community || "public", "-
|
|
317
|
+
const { stdout } = await pexec("snmpwalk", ["-v", t.version || "2c", "-c", t.community || "public", "-Oen", "-t", "2", "-r", "1", t.ip, oid], { timeout });
|
|
302
318
|
return stdout.split("\n").map((l) => {
|
|
303
319
|
const m = /^(\S+)\s*=\s*[^:]+:\s*(.*)$/.exec(l.trim());
|
|
304
320
|
if (!m)
|