FASTPATH CLI¶
The switch’s own command line, as an ordinary backend: show commands for
reads, configuration-mode sequences for writes.
Switches that speak it¶
Model |
Product |
Class |
Ports |
Reached over |
|---|---|---|---|---|
M4300-24X (XSM4324CS) |
fully managed |
28 |
|
|
M4300-16X (XSM4316) |
fully managed |
16 |
|
|
GSM7252PS |
fully managed |
52 |
|
|
GSM7228PS (S3300) |
smart managed pro |
52 |
|
The transport column is not uniform: three of these offer SSH, and the S3300 is telnet only, on a non-standard port.
What it can do, per switch¶
Operation |
m4300-24x |
m4300-16x |
gsm7252ps |
gsm7228ps |
|---|---|---|---|---|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
— [CLI-1] |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
— [CLI-2] |
— [CLI-2] |
— [CLI-2] |
— [CLI-2] |
|
✓ |
✓ |
✓ |
✓ |
|
— [CLI-1] |
✓ |
✓ |
✓ |
|
— [CLI-1] |
✓ |
✓ |
✓ |
|
— [CLI-1] |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
|
— [CLI-3] |
— [CLI-3] |
— [CLI-3] |
— [CLI-3] |
|
✓ |
✓ |
✓ |
— [CLI-4] |
Three transports, one command surface¶
Transport |
Class |
Notes |
|---|---|---|
SSH |
The default for a model that has it. Needs paramiko from the
|
|
Telnet |
Used automatically for a model with telnet but no SSH. The port comes from the model’s spec. |
|
Serial console |
The same CLI over a serial line, via pyserial. Never selected
automatically — it needs a device path, not a host — so construct it and
pass it as |
All three satisfy the CliSession protocol, so CliReader and CliWriter
work unchanged across them, and equally against the mock CLI face.
Note
Backend.CONSOLE is therefore not registered on any model: it names a
transport for the CLI backend, not a network-reachable backend of its own.
Asking for it via backend= raises, and the support tables say why.
Two transport facts learned the hard way¶
The S3300 listens on telnet port 60000, not 23, and runs no SSH listener on
any port — its own tcpConnTable shows only 80, 443 and 60000. Its CLI
backend is telnet only, and the transport dials the port from its spec rather
than the default.
Old FASTPATH needs legacy SSH algorithms. The GSM7252PS and M4300 offer only
diffie-hellman-group14-sha1 key exchange and an ssh-rsa (SHA-1) host key,
both dropped from paramiko 3.0’s defaults. The dependency is pinned below 3.0
and the transport re-inserts those algorithms explicitly.
Commands per model¶
Every command is a field on a CliModelSpec — the show command for each
read, the configuration sequence for each write, and the interface-name template
(1/0/{port}, with a separate template for uplink ports where a model needs
one). A model that words a command differently is supported by overriding that
one field, with no fork of the reader.
Reads map to show commands: port status, VLAN brief and per-VLAN detail,
PVIDs, MAC address table, LLDP remote devices, PoE port info, environment, and
network. Writes drive the real configuration sequences — vlan database,
configure / interface / vlan participation / vlan tagging /
vlan pvid, poe and no poe, shutdown and no shutdown.
Warning
get_stats costs one round trip per port: FASTPATH has no “all ports”
counter command, so counters come from a per-port
show interface ethernet 1/0/<n>. On a 52-port switch that is 52 commands.
Prefer SNMP for statistics where the model has it.
The port list is taken from the switch’s own show port all, not from the
registry’s port_count — which is a nominal value that can exceed the
physical port count. Iterating the nominal range issued doomed queries for
ports that do not exist and fabricated empty counters for them.
Verification gates¶
CliModelSpec.reads_verified and writes_verified gate live dispatch
exactly as the HTTP flags do. writes_verified requires reads_verified,
and not incidentally: every CLI write confirms itself by reading back through
CliReader, so a model whose CLI reads are not trusted cannot honestly verify a
CLI write either.
The readers themselves are not gated — they can always be constructed directly, which is what the mock tests do. Only the facade refuses.
Certificate deployment¶
The Fully Managed FASTPATH line takes an HTTPS certificate over SCP rather than
an HTTP form. upload_certificate_scp runs the real sequence:
disable HTTPS, copy scp://<source> nvram:sslpem-server, optionally the root
chain, re-enable HTTPS to load it, save the configuration. No reboot.
The certificate files must be staged on the SCP source first; the switch pulls them. See Changing a switch.
Using the CLI backend¶
from netgear_switch import Backend, SyncSwitch, get_model
switch = SyncSwitch(
get_model("gsm7252ps"), host="10.1.5.22", http_password="...",
)
vlans = switch.get_vlans(backend=Backend.SSH)
# There is no async CLI backend. All three CLI transports are
# synchronous, so AsyncSwitch refuses SSH/TELNET/CONSOLE outright:
#
# UnsupportedCapabilityError: model 'gsm7252ps' CLI reads are not
# available via the async facade (CLI is synchronous ...)
#
# Use SyncSwitch for the CLI backend, or run it in an executor:
import asyncio
from netgear_switch import Backend, SyncSwitch, get_model
switch = SyncSwitch(
get_model("gsm7252ps"), host="10.1.5.22", http_password="...",
)
vlans = await asyncio.to_thread(switch.get_vlans, backend=Backend.SSH)
The CLI password defaults to the web-admin password and the username to
admin. The session is lazy: nothing is opened until a command needs it,
so an operation the reader refuses outright — PoE on a switch with no PSE
ports — raises UnsupportedCapabilityError without ever dialling, rather
than a spurious CredentialError for a password it was never going to use.
Pass your own session with cli_client= to use the serial console, to reuse a
connection, or to point at the mock:
from netgear_switch.virtual.server import VirtualSwitch
with VirtualSwitch(model="gsm7252ps") as mock:
switch = SyncSwitch(
get_model("gsm7252ps"), host="127.0.0.1",
cli_client=mock.cli_session(),
)
print(switch.get_vlans(backend=Backend.SSH))
from netgear_switch.virtual.server import VirtualSwitch
with VirtualSwitch(model="gsm7252ps") as mock:
switch = AsyncSwitch(
get_model("gsm7252ps"), host="127.0.0.1",
cli_client=mock.cli_session(),
)
try:
print(await switch.get_vlans(backend=Backend.SSH))
finally:
await switch.aclose()
API¶
netgear_switch.cli_write—CliWriterand the SCP certificate flow.netgear_switch.protocols.cli.commands— the per-model command specs.netgear_switch.protocols.cli.parse— pure parsers over command output.netgear_switch.transport.cli.session— theCliSessionprotocol.