fix(gre): не подменять неизвестные флаги состоянием туннеля
This commit is contained in:
1 parent
9c4a0992d7
commit
51a579d370
18 files changed
+877
-17
No files matched your search
@@ -5,7 +5,7 @@ import { MikrotikClient } from "./mikrotik.js"
|
||||
import type { servers } from "../db/schema.js"
|
||||
|
||||
const server = { id: 1, name: "CHR", enabled: true } as typeof servers.$inferSelect
|
||||
const raw = [{ ".id": "*g", name: "own-gre", "remote-address": "192.0.2.1", running: "true" }]
|
||||
const raw = [{ ".id": "*g", name: "own-gre", "remote-address": "192.0.2.1", running: "true", disabled: "false" }]
|
||||
const rows = [
|
||||
{ ".id": "*1", interface: "own-gre", address: "10.1.0.1/30" },
|
||||
{ ".id": "*1", interface: "own-gre", address: "fd00:151::1/64", advertise: "yes" },
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
type GreSnapshot,
|
||||
} from "./entity-snapshots.js"
|
||||
import { captureAndAppendRevision } from "./config-revisions.js"
|
||||
import { readGreObservedState } from "./gre-observed-state.js"
|
||||
|
||||
type ServerRow = typeof servers.$inferSelect
|
||||
|
||||
@@ -142,8 +143,7 @@ export function mapGreLive(
|
||||
ifaceAddrs.sort((a, b) => Number(Boolean(a.disabled)) - Number(Boolean(b.disabled)) || a.address.localeCompare(b.address))
|
||||
const localInnerIp = ifaceAddrs[0]?.address || fromComment.localInnerIp
|
||||
const secret = (g["ipsec-secret"] ?? "").trim()
|
||||
const disabled = rosDisabled(g.disabled)
|
||||
const running = g.running === "true" || g.running === "yes"
|
||||
const { disabled, status } = readGreObservedState(g, name)
|
||||
|
||||
gre.push({
|
||||
name,
|
||||
@@ -183,7 +183,7 @@ export function mapGreLive(
|
||||
allowFastPath: g["allow-fast-path"] !== "false" && g["allow-fast-path"] !== "no",
|
||||
comment: readGreComment(g.comment).comment,
|
||||
enabled: !disabled,
|
||||
status: disabled ? "down" : running ? "up" : "degraded",
|
||||
status,
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { observedBoolean } from "./ospf-observed-values.js"
|
||||
|
||||
/** Disabled is authoritative; an enabled interface also needs a known running flag. */
|
||||
export function readGreObservedState(flags: { running?: string; disabled?: string }, name: string) {
|
||||
const disabled = observedBoolean(flags.disabled)
|
||||
const running = observedBoolean(flags.running)
|
||||
if (disabled === null || (disabled === false && running === null)) {
|
||||
throw new Error(`Не подтверждено состояние GRE ${name}`)
|
||||
}
|
||||
const status: "up" | "down" | "degraded" = disabled ? "down" : running ? "up" : "degraded"
|
||||
return { disabled, status }
|
||||
}
|
||||
@@ -12,3 +12,13 @@ for(const phase of ['populated','empty','partial','failed','disabled','sync-fail
|
||||
if(phase==='disabled')assert.equal(calls,0)
|
||||
}
|
||||
console.log('GRE alert source: populated/empty/partial/all-failed/disabled/sync error; BGP control preserved, per-device errors retained')
|
||||
import {mapGreLive} from './gre-live.js'
|
||||
import {mapGreAlertRow} from './gre-tunnels-live.js'
|
||||
let combinations=0
|
||||
for(const disabled of ['true','yes','false','no',undefined,'','junk'])for(const running of ['true','yes','false','no',undefined,'','junk']){
|
||||
const row={'.id':'*1',name:'own-flags',disabled,running},off=['true','yes'].includes(disabled??''),on=['false','no'].includes(disabled??''),runningKnown=['true','yes','false','no'].includes(running??'')
|
||||
if(off||on&&runningKnown){const expected=off?'down':['true','yes'].includes(running??'')?'up':'degraded';assert.equal(mapGreAlertRow(devices[0],row).status,expected);assert.equal(mapGreLive(devices[0],[row],[]).tunnels[0].status,expected)}
|
||||
else {assert.throws(()=>mapGreAlertRow(devices[0],row),/Не подтверждено состояние GRE/);assert.throws(()=>mapGreLive(devices[0],[row],[]),/Не подтверждено состояние GRE/)}
|
||||
combinations++
|
||||
}
|
||||
console.log('GRE flags: '+combinations+' combinations; true/false/yes/no, absent/blank/invalid, disabled state independent of running')
|
||||
@@ -3,6 +3,7 @@ import { db } from "../db/index.js"
|
||||
import { servers } from "../db/schema.js"
|
||||
import { MikrotikClient } from "./mikrotik.js"
|
||||
import { readInternetPathRows } from "./internet-path-snapshot.js"
|
||||
import { readGreObservedState } from "./gre-observed-state.js"
|
||||
|
||||
type ServerRow = typeof servers.$inferSelect
|
||||
|
||||
@@ -29,10 +30,8 @@ export type GreTunnelLiveRow = {
|
||||
status: GreTunnelLiveStatus
|
||||
}
|
||||
|
||||
function mapGreRow(server: ServerRow, g: RosGre, idx: number): GreTunnelLiveRow {
|
||||
const running = g.running === "true"
|
||||
const disabled = g.disabled === "true"
|
||||
const status: GreTunnelLiveStatus = disabled ? "down" : running ? "up" : "degraded"
|
||||
export function mapGreAlertRow(server: ServerRow, g: RosGre, idx = 0): GreTunnelLiveRow {
|
||||
const { status } = readGreObservedState(g, g.name ?? g[".id"] ?? "")
|
||||
const sn = String(server.name ?? "").trim() || String(server.host ?? "").trim() || String(server.id)
|
||||
const tn = (String(g.name ?? "").trim() || String(g[".id"] ?? "").trim() || `gre-${idx + 1}`).trim()
|
||||
const label = `${tn} / ${sn}`.trim()
|
||||
@@ -43,7 +42,7 @@ async function fetchGreForServer(server: ServerRow): Promise<GreTunnelLiveRow[]>
|
||||
const client = MikrotikClient.fromServer(server)
|
||||
const greRaw = readInternetPathRows(await client.get<unknown>("/interface/gre"), "GRE alert source", [".id", "name"])
|
||||
if (new Set(greRaw.map(row => row[".id"])).size !== greRaw.length) throw new Error("Повторяющиеся ID GRE")
|
||||
return greRaw.map((g, idx) => mapGreRow(server, g, idx))
|
||||
return greRaw.map((g, idx) => mapGreAlertRow(server, g, idx))
|
||||
}
|
||||
|
||||
interface GreAlertDependencies {
|
||||
|
||||
Reference in new issue
Block a user