From 8b0ddea0af1f894b483ba1e5bec0942b1630a7cd Mon Sep 17 00:00:00 2001 From: Stephen Stack Date: Sat, 12 Sep 2026 18:33:13 +0100 Subject: [PATCH] feat(ciena): add tl1MaxConnections and a Ciena vendor README Every RNE behind a Ciena GNE opens its own TL1 session to that gateway, so a nightly run over a gateway fronting a hundred RNEs attempts a hundred logins as fast as the queue can issue them. A node that refuses connections past its own cap fails whichever collections lose that race. rConfig now caps concurrent sessions per gateway, configured with connect.tl1MaxConnections on the GNE's template and defaulting to 20. Both Ciena templates carry it, and the key is documented in the legend with its clamping behaviour: values outside 1 to 500 are clamped and anything non-numeric falls back to the default, so a typo cannot stop a gateway collecting. The validator's allowlist gains the key too, otherwise these templates would fail their own CI. Key counts in README, CONTRIBUTING, EDITIONS and the legend move from 46 to 47, and the Pro-only count from 13 to 14. The CHANGELOG's count is left alone, being a record of a past release. Ciena had no vendor README while most other vendors do. Added one covering what makes TL1 different from a CLI, the GNE/RNE and dual-homing model, and how to choose a connection limit. Refs RCO-1449 Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 2 +- ciena/README.md | 67 +++++++++++++++++++++++++++++++++ ciena/ciena-6500-tl1-ssh.yml | 1 + ciena/ciena-6500-tl1-telnet.yml | 1 + docs/CONTRIBUTING.md | 2 +- docs/EDITIONS.md | 4 +- docs/TEMPLATES.md | 3 +- scripts/validate_templates.py | 4 +- 8 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 ciena/README.md diff --git a/README.md b/README.md index 342fe7e..c515888 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ hardware model belongs in the filename and when it does not. ## Template keys This README carries no key documentation. The full reference lives in -[docs/TEMPLATES.md](docs/TEMPLATES.md): 46 keys across 7 sections, each with its type, accepted +[docs/TEMPLATES.md](docs/TEMPLATES.md): 47 keys across 7 sections, each with its type, accepted values, default, and which protocols read it. If your device needs behaviour no existing key can express, open a diff --git a/ciena/README.md b/ciena/README.md new file mode 100644 index 0000000..f0c4f25 --- /dev/null +++ b/ciena/README.md @@ -0,0 +1,67 @@ +# Ciena + +Covers Ciena 6500 optical nodes, managed over TL1 rather than a conventional CLI. + +| Template | Use for | +| --- | --- | +| `ciena-6500-tl1-ssh.yml` | 6500 nodes reached over SSH, TL1 carried on the SSH channel | +| `ciena-6500-tl1-telnet.yml` | 6500 nodes reached over raw TCP on a TL1 port, typically 3082/3083 | + +Typical retrieval commands to attach in an rConfig Command Group: + +```text +RTRV-EQPT::ALL:100; +RTRV-ALM-ALL::ALL:101; +RTRV-SW-VER:::102; +``` + +## TL1 is not a CLI + +There is no enable mode, no pager to turn off, and no configuration save step, so these templates +leave all three empty. Login is in-band: the node opens on a bare `<` prompt and waits for an +`ACT-USER` command, which rConfig sends itself. Every command is terminated by `;` and correlated +by a CTAG that the node echoes back. + +Passwords are always sent quoted. A 6500 rejects a complex password sent bare, and quoting also +keeps a password containing `:` — the TL1 field separator — from mis-framing the command. + +## Gateway and remote NEs + +Optical networks are reached through a **Gateway NE (GNE)**, the node you actually connect to, +which fronts **Remote NEs (RNEs)** that have no management access of their own. Set +`tl1Gateway: "on"` on the GNE's template and rConfig runs `tl1NeighbourCmd` after collecting it, +discovers the RNEs behind it, and creates a device record for each one. RNEs are then collected +by addressing their TID in-band over a session to the GNE. + +An RNE can be **dual-homed** — reachable through two or more GNEs. rConfig identifies an RNE by +its TID, so an RNE reported by a second gateway gains a second path rather than a duplicate device +record. One gateway is the primary; if a session through it cannot be established, the collection +falls over to another. + +## Connection limits + +Every RNE collection opens its **own** session to the gateway. A GNE fronting a hundred RNEs would +otherwise see a hundred sessions attempted as fast as the queue can run them, and a node that +refuses connections past its own cap fails whichever collections lose that race. + +`tl1MaxConnections` caps how many sessions rConfig opens to one gateway at a time. It defaults to +`20` and belongs on the **GNE's** template — RNEs inherit their gateway's limit rather than +carrying one of their own. + +```yaml +connect: + tl1Gateway: "on" + tl1MaxConnections: 20 +``` + +A collection that finds no free slot is not a failure: nothing was dialled, so the device is not +marked unreachable and no failure notification is sent. It waits and retries, giving up after an +hour. A dual-homed RNE whose primary gateway is at capacity will use its other gateway instead of +waiting. + +Set it to what the node itself will accept. Too high and the node refuses connections; too low and +a large gateway takes longer to work through its RNEs. Values outside 1 to 500 are clamped, and +anything non-numeric falls back to the default, so a typo cannot stop a gateway collecting. + +See [docs/TEMPLATES.md](../docs/TEMPLATES.md) for what each key means and +[docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md) before submitting a change. diff --git a/ciena/ciena-6500-tl1-ssh.yml b/ciena/ciena-6500-tl1-ssh.yml index 7519789..01ac1ad 100644 --- a/ciena/ciena-6500-tl1-ssh.yml +++ b/ciena/ciena-6500-tl1-ssh.yml @@ -18,3 +18,4 @@ connect: sshAuth: password # SSH transport auth: 'password' (SSH+TL1) or 'none' (TL1-only) tl1Gateway: "on" # GNE only: discover RNEs behind this node via RTRV-NBR ('on'/'off') tl1NeighbourCmd: "RTRV-NBR:ALL" # Neighbour-discovery command (TID/AID composable) + tl1MaxConnections: 20 # GNE only: max concurrent TL1 sessions rConfig opens to this node diff --git a/ciena/ciena-6500-tl1-telnet.yml b/ciena/ciena-6500-tl1-telnet.yml index 7ffd39d..08d7165 100644 --- a/ciena/ciena-6500-tl1-telnet.yml +++ b/ciena/ciena-6500-tl1-telnet.yml @@ -19,3 +19,4 @@ connect: sshAuth: none # Ignored when tl1Transport: telnet (no transport auth) tl1Gateway: "on" # GNE only: discover RNEs behind this node via RTRV-NBR ('on'/'off') tl1NeighbourCmd: "RTRV-NBR:ALL" # Neighbour-discovery command (TID/AID composable) + tl1MaxConnections: 20 # GNE only: max concurrent TL1 sessions rConfig opens to this node diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 395f007..b95161f 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -132,7 +132,7 @@ rather than the file. **No deprecated keys.** `pagerPrompt` and `pagerPromptCmd` are ignored by rConfig and must not appear. The validator treats them as errors. -**Only keys in the legend.** [TEMPLATES.md](TEMPLATES.md) lists all 46 keys across 7 sections. +**Only keys in the legend.** [TEMPLATES.md](TEMPLATES.md) lists all 47 keys across 7 sections. Anything else is an error, because a key rConfig does not read does nothing except mislead the next reader. If your device needs behaviour no existing key expresses, use the [new key request form](../.github/ISSUE_TEMPLATE/new-key-request.yml). That is a change to diff --git a/docs/EDITIONS.md b/docs/EDITIONS.md index cd334ff..1458bb5 100644 --- a/docs/EDITIONS.md +++ b/docs/EDITIONS.md @@ -34,11 +34,11 @@ because they are Ciena device templates, but TL1 itself is Pro only. ## The 13 Pro-only keys -Of the 46 keys in [TEMPLATES.md](TEMPLATES.md), 13 are read only by Pro. +Of the 47 keys in [TEMPLATES.md](TEMPLATES.md), 14 are read only by Pro. | Section | Keys | | --- | --- | -| `connect`, TL1 | `sshAuth`, `tl1Transport`, `tl1Gateway`, `tl1NeighbourCmd` | +| `connect`, TL1 | `sshAuth`, `tl1Transport`, `tl1Gateway`, `tl1NeighbourCmd`, `tl1MaxConnections` | | `connect`, fallback | `fallbackProtocol`, `fallbackPort`, `probeTimeout` | | `connect`, script | `idletimeout` | | `config`, prompt sync | `syncToPromptOnLogin`, `promptSyncTimeout` | diff --git a/docs/TEMPLATES.md b/docs/TEMPLATES.md index a2e97e7..0cea793 100644 --- a/docs/TEMPLATES.md +++ b/docs/TEMPLATES.md @@ -152,6 +152,7 @@ Script templates never build a connection object, so neither key is read for `pr | `tl1Transport` | string | `telnet`, or anything else for ssh | Optional, default `ssh` | tl1 | **Pro only** | Anything that is not literally `telnet` falls back to SSH. `TL1/Connect.php:71`, `Transport/Tl1TransportFactory.php:15-20` | | `tl1Gateway` | boolean or string | `true`, `on`, `1`, `yes` | Optional, default `false` | tl1 | **Pro only** | The one key that accepts both a YAML boolean and the string forms, case-insensitively. Enables neighbour discovery. `TL1/Connect.php:93-95` | | `tl1NeighbourCmd` | string | a TL1 command | Optional, default `RTRV-NBR:ALL` | tl1 | **Pro only** | Only used when `tl1Gateway` is on. `TL1/Connect.php:97` | +| `tl1MaxConnections` | int | clamped to 1 to 500 | Optional, default `20` | tl1 | **Pro only** | Caps how many TL1 sessions rConfig opens to this gateway at once. Every RNE behind a GNE opens its own session, so without a cap a nightly run can open as many at one node as there are queue workers, and a node that refuses connections past its own limit fails the ones that lose the race. Collections that find no free slot wait and retry rather than failing, giving up after an hour. Values outside 1 to 500 are clamped, and anything non-numeric falls back to the default, so a typo cannot stop a gateway collecting. Set it on the GNE's template; RNEs inherit the gateway's limit. `TL1/Connect.php:108`, `TL1/Tl1GatewayConnections.php`, `TL1/Tl1ConnectionManager.php:38` | | `fallbackProtocol` | string | `ssh`, `telnet` | Optional, default none | dispatcher | **Pro only** | Undocumented before this legend. Set it to the other protocol and rConfig resolves which one the device actually answers on, caches the result, then dispatches normally. Only activates when it differs from `protocol` and both are ssh or telnet. `ProtocolFallbackConnectionManager.php:28,50-55,64` | | `fallbackPort` | int | 1 to 65535 | Optional, defaults to 22 for ssh or 23 for telnet | dispatcher | **Pro only** | Undocumented before this legend. Port used for the fallback attempt. A device port override still wins. `ProtocolFallbackConnectionManager.php:30,70-91` | | `probeTimeout` | int | clamped to 1 to 10 | Optional, falls back to `timeout`, then `5` | dispatcher | **Pro only** | Undocumented before this legend. Seconds to wait when testing whether a port is open. Values outside 1 to 10 are clamped. `ProtocolFallbackConnectionManager.php:190-196` | @@ -367,7 +368,7 @@ This legend was compiled from a full read of the rConfig connection stack in bot | YAML parser | `symfony/yaml` v8.1.2 | | Evidence file | `legend-evidence.md` | -Coverage: 46 keys across 7 top-level sections. Core reads 33 of them, set out row by row in +Coverage: 47 keys across 7 top-level sections. Core reads 33 of them, set out row by row in [EDITIONS.md](EDITIONS.md). The 13 that are Pro only are the four TL1 keys, the three fallback keys, `idletimeout`, `sshAuth`, `syncToPromptOnLogin`, `promptSyncTimeout`, and the three `failure_criteria` keys. diff --git a/scripts/validate_templates.py b/scripts/validate_templates.py index 39f4911..4e25e52 100644 --- a/scripts/validate_templates.py +++ b/scripts/validate_templates.py @@ -51,14 +51,14 @@ class RConfigLoader(yaml.SafeLoader): NEW_KEY_PROCESS = "see 'Requesting a new key' in " + LEGEND # --------------------------------------------------------------------------- -# The legend: 46 keys across 7 sections, from docs/TEMPLATES.md +# The legend: 47 keys across 7 sections, from docs/TEMPLATES.md # --------------------------------------------------------------------------- ALLOWED = { "main": {"name", "desc"}, "connect": { "protocol", "port", "timeout", "isNonInteractiveMode", "idletimeout", - "sshAuth", "tl1Transport", "tl1Gateway", "tl1NeighbourCmd", + "sshAuth", "tl1Transport", "tl1Gateway", "tl1NeighbourCmd", "tl1MaxConnections", "fallbackProtocol", "fallbackPort", "probeTimeout", }, "auth": {