Add bulk OLT PON flooding-mode tool; restore README; docs

Adds a second bulk workflow alongside the firmware upgrader: changing
PON flooding mode (private<->auto) on OLT NNI services across many OLTs.

Flooding mode is encoded by the presence of the "PON FLOOD ID" key on
each OLT-CFG["NNI Networks"] entry (present = private, absent = auto).
private->auto deletes the key; auto->private sets it to 0. The rest of
the OLT-CFG is preserved (PUT-as-replace, same as ONU-CFG).

- src/mcms-api.js: listAllOltConfigs / getOltConfig / putOltConfig, plus
  pure helpers floodModeOfNni, summarizeOltNniNetworks, planFloodChange
  (planFloodChange clones and never mutates its input)
- main.js: api:listOlts + api:executeFloodChange IPC handlers
  (concurrency 3, GET->plan->PUT, streams olt-flood:progress)
- preload.js: expose both channels + onFloodProgress
- renderer: OLT inspector view (#view-olts), two-step APPLY confirm,
  auto-saved pon-olt-flood-*.csv result report
- Restore README.md (lost to a filesystem error) and document the new
  feature in README.md and CLAUDE.md (new section 14)

Verified: npm run check passes; pure helpers unit-tested for the
no-mutation, idempotency, and rollback invariants.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jon Vanvik 2026-06-23 12:54:06 +02:00
parent 0eb9b55717
commit 80fd7e8d37
7 changed files with 612 additions and 7 deletions

View file

@ -12,9 +12,15 @@ is the engineering counterpart.
## 1. What this app does
Electron desktop client for bulk ONU firmware upgrades against **Ciena
MCMS 6.2** PON Manager. Reference deployment: GNXS / Tibit MicroPlug ONUs
running Interos Everest (EV051xxR / EV052xxR firmware family).
Electron desktop client for two bulk operations against **Ciena
MCMS 6.2** PON Manager:
1. **Bulk ONU firmware upgrades** (the original purpose).
2. **Bulk OLT PON flooding-mode changes** (private↔auto on NNI services —
see §14).
Reference deployment: GNXS / Tibit MicroPlug ONUs running Interos Everest
(EV051xxR / EV052xxR firmware family) behind Tibit OLTs.
End-to-end operator workflow:
@ -116,6 +122,8 @@ stream progress events back to the renderer.
| `api:executeBulkTask` | Procedure 8 — single AUTO-TASK-CFG | — |
| `api:getTaskConfig` / `api:getUpgradeStatus` | poll helpers | — |
| `api:deleteOnus` | bulk delete (CFG + best-effort STATE) | `delete:progress` |
| `api:listOlts` | OLT-CFG list + per-OLT NNI flood-mode summary | — |
| `api:executeFloodChange` | bulk PON flooding-mode flip (GET→plan→PUT) | `olt-flood:progress` |
| `api:fetchFecHealth` | pre-flight FEC pre/post + optical | `fec:progress` |
| `api:savePlanCsv` | auto-save plan on Execute | — |
| `api:saveCsvFile` | generic CSV writer | — |
@ -645,4 +653,72 @@ Key procedure citations:
---
*Last updated: 2026-05-26.*
## 14. OLT PON flooding mode (bulk private↔auto)
Second bulk feature, added after the firmware upgrader. Lets an operator
flip the PON flooding mode of OLT NNI services across many OLTs at once.
### The mutation rule (the whole feature in one fact)
On Tibit OLTs, a service's flooding mode is encoded by the **presence or
absence of one key** on its `OLT-CFG["NNI Networks"][i]` entry:
- **`PON FLOOD ID` key present** (any value, including `0`) → **private**
- **`PON FLOOD ID` key absent** → **auto**
So private→auto is `delete entry['PON FLOOD ID']`; auto→private is
`entry['PON FLOOD ID'] = 0`. Everything else on the entry (`TAG MATCH`,
`Learning Limit`, …) and the rest of the OLT-CFG is preserved. This was
confirmed empirically by diffing two paste-backs of the same OLT
(`24:65:e1:cc:af:1e`, NNI `s0.c76.c0`) in private vs auto — the *only*
difference was that key.
The default action ships as: TAG MATCH = `s0.c76.c0`, mode `private`
`auto`. Both directions are wired so a change can be rolled back from the
same UI.
### Data flow
```
listOlts ─► McmsClient.listAllOltConfigs ─► summarizeOltNniNetworks (pure)
executeFloodChange ─► per-OLT: getOltConfig ─► planFloodChange (pure, no-mutate)
─► putOltConfig (full-doc PUT)
```
- **Pure helpers** live at the bottom of `src/mcms-api.js`:
`floodModeOfNni`, `summarizeOltNniNetworks`, `tagPatternToRegex`,
`planFloodChange`. `planFloodChange` clones the `NNI Networks` array and
never mutates its input — it returns `{ newDoc, changes, unchanged }`.
- **TAG MATCH pattern** supports exact strings, `*`/`""` (match all), and
`*` globs (e.g. `s0.c76.*`). `tagPatternToRegex` escapes regex metachars
then turns `*` into `.*`.
- **`fromMode` guard**: only entries currently in `fromMode` are flipped;
entries already in the target mode are recorded in `unchanged` (the
per-OLT `noop` case), so re-running is idempotent.
- **Concurrency 3** on the write path (vs 5 for ONU delete, 8 for state
fetch) — OLT writes carry far more blast radius.
- **PUT-as-replace**, same gotcha as ONU-CFG (§5.7): the handler GETs the
live doc immediately before each PUT to avoid stomping a concurrent
edit, then writes the whole document back.
### UI (OLT inspector view, `#view-olts`)
Reached from the fleet view's "Open OLT inspector…" button. Filters by TAG
pattern + current mode + OLT name; selecting an OLT queues every matching
service on it. Two-step confirm (summary `confirm` + typed `APPLY`) before
writing. Auto-saves a result CSV to `~/Downloads/pon-olt-flood-…csv` with
per-OLT result, change detail, and skip reasons — same `writeCsvFile`
helper and conventions as the upgrade/verify CSVs (§8).
### Testing the pure helpers
`floodModeOfNni` / `summarizeOltNniNetworks` / `planFloodChange` are
exported from `src/mcms-api.js` and have no DOM/Electron deps, so they're
directly `require`-able in a `node -e` fixture. The invariants worth
re-checking after any edit: (1) `planFloodChange` does **not** mutate its
input, (2) re-applying the same change is a no-op, (3) non-matching NNI
entries pass through untouched.
---
*Last updated: 2026-06-23.*