Use topology/links and anynetlinks filters with eq/in operators so store WAN follow-ups return real peer tunnels instead of unscoped dumps. Co-authored-by: Cursor <cursoragent@cursor.com>
105 lines
3.1 KiB
JavaScript
105 lines
3.1 KiB
JavaScript
// src/services/voiceDiag/checks/wan/wanTunnels.js
|
|
//
|
|
// Overlay / VPN tunnel health. Complements wanLinkState (physical
|
|
// circuits): a store can have all WAN paths up while the SD-WAN
|
|
// mesh to the hub is down — voice then fails even though LQM looks
|
|
// fine.
|
|
//
|
|
// Data comes from collectSdwanForStore().tunnels (Prisma vpnlinks /
|
|
// topology links). When the tunnels fetch failed or returned empty,
|
|
// we skip rather than false-alarming.
|
|
|
|
import { maybeSkippedByKillSwitch } from './_helpers.js';
|
|
|
|
export const WAN_TUNNELS_STANDARDS = Object.freeze({
|
|
allUp: true,
|
|
});
|
|
|
|
export const wanTunnelsCheck = {
|
|
id: 'wanTunnels',
|
|
label: 'SD-WAN Overlay Tunnels',
|
|
requires: ['sdwanSite'],
|
|
scope: null,
|
|
standards: WAN_TUNNELS_STANDARDS,
|
|
|
|
async run(ctx) {
|
|
const skip = maybeSkippedByKillSwitch(wanTunnelsCheck);
|
|
if (skip) return skip;
|
|
|
|
const tunnels = Array.isArray(ctx.sdwanData?.tunnels) ? ctx.sdwanData.tunnels : [];
|
|
const tunnelFetchFailed = (ctx.sdwanData?.errors || [])
|
|
.some((e) => e.scope === 'tunnels');
|
|
|
|
if (tunnels.length === 0) {
|
|
return {
|
|
status: 'skipped',
|
|
message: tunnelFetchFailed
|
|
? 'Overlay tunnel status unavailable (Prisma fetch failed).'
|
|
: 'No overlay tunnels reported for this site.',
|
|
details: { total: 0, tunnelFetchFailed },
|
|
remediation: null,
|
|
};
|
|
}
|
|
|
|
const down = tunnels.filter((t) => t.up === false);
|
|
const unknown = tunnels.filter((t) => t.up == null);
|
|
const up = tunnels.filter((t) => t.up === true);
|
|
const alarmed = tunnels.filter((t) => t.recentAlarm);
|
|
|
|
const links = Array.isArray(ctx.sdwanData?.links) ? ctx.sdwanData.links : [];
|
|
const physicalAllUp = links.length > 0 && links.every((l) => l.up !== false);
|
|
|
|
const details = {
|
|
total: tunnels.length,
|
|
up: up.length,
|
|
down: down.length,
|
|
unknown: unknown.length,
|
|
alarmed: alarmed.length,
|
|
offenders: down.map((t) => t.peerLabel || t.id),
|
|
physicalAllUp,
|
|
};
|
|
|
|
if (down.length > 0) {
|
|
const hint = physicalAllUp
|
|
? ' Physical WAN paths look up — this is an overlay/VPN issue.'
|
|
: '';
|
|
return {
|
|
status: 'error',
|
|
message:
|
|
`${down.length} of ${tunnels.length} overlay tunnel(s) DOWN: ` +
|
|
down.map((t) => t.peerLabel || t.id).join(', ') +
|
|
`.${hint}`,
|
|
details,
|
|
remediation: null,
|
|
};
|
|
}
|
|
|
|
if (alarmed.length > 0) {
|
|
return {
|
|
status: 'warn',
|
|
message:
|
|
`${alarmed.length} overlay tunnel(s) have recent Prisma alarms ` +
|
|
`while currently reporting up.`,
|
|
details,
|
|
remediation: null,
|
|
};
|
|
}
|
|
|
|
if (unknown.length > 0 && up.length === 0) {
|
|
return {
|
|
status: 'warn',
|
|
message: `Overlay tunnel state unknown for all ${unknown.length} tunnel(s).`,
|
|
details,
|
|
remediation: null,
|
|
};
|
|
}
|
|
|
|
return {
|
|
status: 'ok',
|
|
message: `All ${up.length} overlay tunnel(s) up.` +
|
|
(unknown.length > 0 ? ` (${unknown.length} with unknown state.)` : ''),
|
|
details,
|
|
remediation: null,
|
|
};
|
|
},
|
|
};
|