Merge pull request #4 from outis1one/claude/avaya-switch-manager-DxZs5
Update switch_backend.py for ERS 59100GTS-PWR+ (96+4 port)
This commit is contained in:
@@ -6,6 +6,20 @@ Compatible with: ERS 5928, ERS 5948, ERS 5952, ERS 5952-PWR+, ERS 59100GTS-PWR+
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
**Management computer OS: Linux** (Ubuntu / Debian recommended — Raspberry Pi OS works perfectly)
|
||||
|
||||
The setup script uses `apt`, `systemd`, `picocom`, and Docker. It will not run on Mac or Windows. The management computer does not need a monitor — a headless Raspberry Pi or thin client is ideal. Once running, the web UI is accessible from any browser on any device on your network.
|
||||
|
||||
The switch UI itself (the browser interface) works from any OS — phone, tablet, Mac, Windows, Linux.
|
||||
|
||||
**Switch OS: BOSS (Baystack Operating System Software) v7.9.6**
|
||||
|
||||
BOSS is the firmware that runs on Avaya / Extreme ERS switches. This project is written and tested against BOSS v7.9.6 on the ERS 59100GTS-PWR+. It is not Cisco IOS or any other vendor's CLI — commands are different. BOSS firmware is pre-installed on the switch and does not need to be downloaded or installed.
|
||||
|
||||
---
|
||||
|
||||
## Physical Setup — First Time Out of the Box
|
||||
|
||||
Everything here happens before you run any software. You need a console cable and a laptop.
|
||||
@@ -34,7 +48,7 @@ Search **"RJ45 to USB console cable Cisco compatible"** — around $8. This is t
|
||||
|
||||
### Step 3 — Connect and Open a Terminal
|
||||
|
||||
Plug the RJ-45 end into the switch console port. Plug USB into your laptop.
|
||||
**Important:** Plug the console cable in — both the RJ-45 end into the switch and the USB end into your laptop — **before** powering on the switch. If you plug in after power-on, `screen` and `picocom` may not detect the device correctly.
|
||||
|
||||
**Settings:** `9600 baud · 8 data bits · No parity · 1 stop bit · No flow control`
|
||||
|
||||
@@ -51,6 +65,8 @@ To find your COM/device name if unsure:
|
||||
- Mac: `ls /dev/tty.usb*` before and after plugging in
|
||||
- Windows: Device Manager → Ports (COM & LPT)
|
||||
|
||||
> **Console vs SSH:** The console cable gives you direct CLI access to type commands on the switch. It is only needed for initial setup. Once SSH is configured, the management script connects over Ethernet (port 22) and you never need the console cable again — unless you lock yourself out.
|
||||
|
||||
---
|
||||
|
||||
### Step 4 — Power On and Read the Boot Screen
|
||||
@@ -107,17 +123,28 @@ vlan pvid 1 99
|
||||
ip ssh
|
||||
username admin password YourPassword
|
||||
end
|
||||
copy running-config nvram:config.cfg
|
||||
save config
|
||||
```
|
||||
|
||||
Replace `1` with the port number your management computer will plug into. Replace `YourPassword` with a strong password (8–32 characters; allowed special characters: `! @ # $ % ^ & * - _ = + [ ] ; : , . /` — no spaces, no quotes).
|
||||
|
||||
**ERS 59100 note:** Port numbering on the 59100 is `1/1` through `1/96` for copper and `1/97` through `1/100` for SFP+ uplinks. Substitute accordingly:
|
||||
**Port numbering:** On both the ERS 5952 and ERS 59100, use bare port numbers (`1`, `2`, `48`…). There is no slot prefix.
|
||||
|
||||
```
|
||||
vlan members add 99 1/1
|
||||
vlan pvid 1/1 99
|
||||
```
|
||||
> **What about the switch's existing IP?**
|
||||
> Out of the box the switch has `192.168.1.1` on VLAN 1. If your router is also `192.168.1.1`, they will conflict — two devices with the same IP on the same network causes ARP fights and makes both unreliable.
|
||||
>
|
||||
> This setup deliberately avoids that by putting management traffic on a **separate VLAN (99) with its own subnet (192.168.99.x)**. Your management computer gets a static IP on that subnet and talks to the switch there. The switch's original VLAN 1 address is irrelevant once VLAN 99 is up.
|
||||
>
|
||||
> If you ever need to change the switch's VLAN 1 IP (e.g. to remove the conflict before VLAN 99 is configured):
|
||||
> ```
|
||||
> config terminal
|
||||
> interface vlan 1
|
||||
> ip address 192.168.1.2 255.255.255.0
|
||||
> exit
|
||||
> ip default-gateway 192.168.1.1
|
||||
> exit
|
||||
> save config
|
||||
> ```
|
||||
|
||||
After the last command the switch confirms with `CP1 [07/04/15 12:00:00.000:INFO]: Operation Success` or similar.
|
||||
|
||||
@@ -465,6 +492,107 @@ The switch is never being polled when nobody is looking at the dashboard.
|
||||
|
||||
---
|
||||
|
||||
## Firmware Upgrade
|
||||
|
||||
The switch runs two software components that must both be upgraded:
|
||||
- **Diagnostic image** (diag) — upgraded first
|
||||
- **Agent image** (BOSS firmware) — upgraded second
|
||||
|
||||
**Important rules:**
|
||||
- Upgrade one version at a time — cannot skip releases
|
||||
- Always upgrade the diagnostic image before the agent image
|
||||
- USB files must not be marked read-only or the transfer fails
|
||||
- Firmware downloads require an active support contract at the [Extreme Networks portal](https://extreme-networks.my.site.com)
|
||||
- Check the [ERS Announcements page](https://community.extremenetworks.com/t5/ers-announcements/bg-p/ERS_Announcements) to find the latest version
|
||||
|
||||
Your switch currently runs: **BOSS v7.9.6.015 / Diagnostics 7.5.0.4**
|
||||
|
||||
---
|
||||
|
||||
### Method 1 — USB (no network needed, easiest)
|
||||
|
||||
1. Download the diagnostic `.bin` and agent `.img` files from the Extreme portal
|
||||
2. Copy both files to a USB stick — ensure they are **not read-only**
|
||||
3. Insert the USB stick into the front panel USB port on the switch
|
||||
4. Via console or SSH (in enable mode):
|
||||
|
||||
```
|
||||
download usb diag ers5900diag_7x_x_x_x.bin
|
||||
```
|
||||
Wait for it to complete and confirm, then:
|
||||
```
|
||||
download usb image ers5900_7x_x_x_x.img
|
||||
```
|
||||
The switch will reboot automatically after the agent upgrade.
|
||||
|
||||
Alternatively, from the **boot menu** (option 4 — "Download Agent/Diag") you can trigger a USB download without logging in first.
|
||||
|
||||
---
|
||||
|
||||
### Method 2 — SFTP over SSH (requires network)
|
||||
|
||||
From enable mode on the switch, with an SFTP server running on your management computer:
|
||||
|
||||
```
|
||||
copy sftp address 192.168.99.50 filename ers5900diag_7x_x_x_x.bin
|
||||
```
|
||||
Wait for completion, then:
|
||||
```
|
||||
copy sftp address 192.168.99.50 filename ers5900_7x_x_x_x.img
|
||||
```
|
||||
The switch reboots after the agent upgrade.
|
||||
|
||||
---
|
||||
|
||||
### Method 3 — TFTP from a laptop (no dedicated server needed)
|
||||
|
||||
Your laptop can act as a temporary TFTP server. The switch has a default IP of **`192.168.1.1/24`** on VLAN 1 out of the box (or after a factory reset) — so on a fresh switch you can skip console IP configuration entirely. Just plug in Ethernet and go.
|
||||
|
||||
Plug both the console cable **and** an Ethernet cable from the laptop into the switch at the same time.
|
||||
|
||||
On the laptop:
|
||||
```bash
|
||||
sudo apt install tftpd-hpa
|
||||
sudo cp ers5900diag_*.bin ers5900_*.img /srv/tftp/
|
||||
sudo ip addr add 192.168.1.50/24 dev eth0 # must be on same /24 as switch default (192.168.1.x)
|
||||
sudo systemctl start tftpd-hpa
|
||||
```
|
||||
|
||||
Then on the switch via console (or via SSH to `192.168.1.1` if SSH is already enabled):
|
||||
```
|
||||
enable
|
||||
copy tftp address 192.168.1.50 filename ers5900diag_7x_x_x_x.bin
|
||||
```
|
||||
Then:
|
||||
```
|
||||
copy tftp address 192.168.1.50 filename ers5900_7x_x_x_x.img
|
||||
```
|
||||
|
||||
Stop the server when done:
|
||||
```bash
|
||||
sudo systemctl stop tftpd-hpa
|
||||
```
|
||||
|
||||
> **No console needed on a factory switch:** The switch answers at `192.168.1.1` immediately after boot. As long as your laptop is on `192.168.1.x/24`, the TFTP transfer works without touching the console at all — useful if you only have an Ethernet cable and no console cable handy.
|
||||
|
||||
---
|
||||
|
||||
### Method 4 — XMODEM over console cable (last resort, no network required)
|
||||
|
||||
If the USB port is broken and you have no Ethernet available at all, boot menu option 4 ("Download Agent/Diag") supports XMODEM file transfer directly over the serial console cable. No network required.
|
||||
|
||||
**Warning:** At 9600 baud, a 10 MB firmware file takes approximately 3 hours. Only use this if nothing else is possible.
|
||||
|
||||
In `screen`, after selecting option 4 from the boot menu, send the file with:
|
||||
|
||||
```
|
||||
Ctrl-A then :exec !! sx -b /path/to/ers5900_7x_x_x_x.img
|
||||
```
|
||||
|
||||
(`sx` is part of the `lrzsz` package: `sudo apt install lrzsz`)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Connection banner stuck on "Connecting..."**
|
||||
@@ -482,6 +610,48 @@ Read the error text — the switch says exactly what was wrong. Fix the configur
|
||||
**Host key rejection after switch reset**
|
||||
Re-pin: `ssh-keyscan -H 192.168.99.1 > /etc/switch-manager/known_hosts`
|
||||
|
||||
**Factory reset — wiping a previously configured switch**
|
||||
|
||||
> When to wipe: if the switch has unknown previous configuration, unknown passwords, or you want a guaranteed clean slate. If the switch already responds to `admin` with no password and has no unexpected VLANs or ACLs, a wipe is not required — you can configure over the existing state.
|
||||
|
||||
**Method 1 — Boot menu (easiest, works even if you don't know the password)**
|
||||
|
||||
The console cable must be plugged in before power-on. During boot a diagnostic menu appears briefly:
|
||||
|
||||
```
|
||||
DIAGNOSTIC BREAK MENU
|
||||
59100 GTS-PWR+ Diagnostics 7.5.0.4
|
||||
1 - Launch Primary Agent-1 Vers: 7.9.6.015
|
||||
2 - Launch Secondary Agent-2 Vers: 7.6.2.019
|
||||
3 - Toggle Primary Agent Selection
|
||||
4 - Download Agent/ Diag
|
||||
5 - Reinitialize Agent Configuration Files
|
||||
6 - Display Error Log
|
||||
7 - Display System Information
|
||||
8 - Continue Boot Sequence
|
||||
9 - Reset
|
||||
A - Power-Cycle
|
||||
B - Toggle Do-POST Selection [ ENABLED ]
|
||||
C - Run POST tests
|
||||
Select:
|
||||
Booting Agent in 60 seconds...
|
||||
```
|
||||
|
||||
Press **5** — "Reinitialize Agent Configuration Files". The switch wipes its config and reboots into factory defaults. You have 60 seconds before it boots automatically.
|
||||
|
||||
Other useful options: **1/2** switch between primary (v7.9.6) and secondary (v7.6.2) firmware. **6** shows the error log. **7** shows system info. **8** continues normal boot if you entered the menu by accident. **9** resets (reboots). **A** power-cycles. **B** toggles POST (hardware self-test) on/off. **C** runs POST tests manually.
|
||||
|
||||
**Method 2 — CLI (requires working login)**
|
||||
|
||||
```
|
||||
enable
|
||||
boot config flags factory
|
||||
save config
|
||||
boot
|
||||
```
|
||||
|
||||
After either method the switch comes up with blank config, default credentials (`admin` / no password), and management IP `192.168.1.1` on VLAN 1. Continue from Step 5.
|
||||
|
||||
**ctrld not filtering DNS**
|
||||
Check DHCP option 6 is set to the ctrld machine's IP on each VLAN pool. Check ctrld is running: `ctrld status`. Check the switch is handing out the right DNS: from a device, run `nslookup example.com` and verify the server IP matches.
|
||||
|
||||
@@ -500,6 +670,77 @@ docker compose ps
|
||||
|
||||
---
|
||||
|
||||
## Command Reference — Tested Status
|
||||
|
||||
Commands the script sends to the switch, with known test status. Use this as a guide when debugging unexpected behaviour — untested commands may behave differently on your firmware version.
|
||||
|
||||
### Read commands
|
||||
|
||||
| Command | Status | Notes |
|
||||
|---|---|---|
|
||||
| `show interfaces` | confirmed | |
|
||||
| `show poe-main-status` | confirmed | |
|
||||
| `show vlan` | confirmed | |
|
||||
| `show sys-info` | confirmed | |
|
||||
| `show arp` | confirmed | |
|
||||
| `show config` | confirmed | Returns table output |
|
||||
| `show ip helper-address` | not tested | |
|
||||
| `show ip route default` | not tested | |
|
||||
| `show dhcp-server leases` | invalid on this firmware | Script handles gracefully — returns empty |
|
||||
| `show dhcp-server static-binding` | invalid on this firmware | Script handles gracefully — returns empty |
|
||||
| `show dhcp-server` | invalid on this firmware | Script handles gracefully — returns empty |
|
||||
|
||||
### Config / push commands
|
||||
|
||||
| Command | Status | Notes |
|
||||
|---|---|---|
|
||||
| `enable` | confirmed | |
|
||||
| `configure terminal` | confirmed | |
|
||||
| `terminal length 0` | not tested | Disables pagination — sent before reads |
|
||||
| `interface FastEthernet {port}` | confirmed | |
|
||||
| `vlan members add {vid} {port}` | confirmed | |
|
||||
| `vlan pvid {port} {vid}` | not tested | Sets native/untagged VLAN on a port |
|
||||
| `vlan tagging {tagged-set} {port}` | not tested | Adds trunk tagging |
|
||||
| `vlan create {vid} name "x" type port` | not tested | |
|
||||
| `no vlan {vid}` | not tested | |
|
||||
| `name "{description}"` (under interface) | not tested | Sets port description |
|
||||
| `shutdown` (under interface) | not tested | Disables a port |
|
||||
| `poe enable` / `no poe enable` | not tested | |
|
||||
| `poe poe-limit {milliwatts}` | not tested | |
|
||||
| `interface vlan {vid}` (in config mode) | not tested | |
|
||||
| `ip access-list extended {name}` | not tested | |
|
||||
| `ip access-group {name} in/out` | not tested | |
|
||||
| `end` | not tested | Returns to enable mode |
|
||||
| `save config` | confirmed | **Caused a reboot on first run** — watch the first time you push this |
|
||||
|
||||
> **`save config` reboot note:** On at least one switch, issuing `save config` triggered a reboot. This may be firmware-version-specific or a one-time behaviour after certain config states. Subsequent saves have not reproduced it. Be aware when pushing config changes in a live environment.
|
||||
|
||||
---
|
||||
|
||||
## Scrollback in `screen` (console cable sessions)
|
||||
|
||||
By default `screen` does not let you scroll up through output. Enable it with copy mode:
|
||||
|
||||
| Action | Keys |
|
||||
|---|---|
|
||||
| Enter scrollback mode | `Ctrl-A` then `[` |
|
||||
| Scroll up / down | Arrow keys or `PgUp` / `PgDn` |
|
||||
| Exit scrollback mode | `Esc` or `q` |
|
||||
|
||||
To increase the scrollback buffer for a session (default is only 100 lines):
|
||||
```
|
||||
Ctrl-A then :scrollback 10000
|
||||
```
|
||||
|
||||
To set it permanently, add this to `~/.screenrc`:
|
||||
```
|
||||
defscrollback 10000
|
||||
```
|
||||
|
||||
Useful when reviewing long `show config` or `show interfaces` output during console sessions.
|
||||
|
||||
---
|
||||
|
||||
## What This Tool Does Not Do
|
||||
|
||||
- Does not manage OPNsense, pfSense, or any other device directly (OPNsense integration is read/sync only)
|
||||
|
||||
+50
-29
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
ERS 5952 Switch Manager — Backend v3
|
||||
ERS 59100GTS-PWR+ Switch Manager — Backend v3
|
||||
────────────────────────────────────────────────────────────────────────
|
||||
Changes from v2:
|
||||
- Connection pool (30s lifetime, liveness check, auto-invalidate)
|
||||
@@ -40,7 +40,7 @@ log = logging.getLogger("switch-manager")
|
||||
SWITCH_HOST = "192.168.99.1"
|
||||
SWITCH_PORT = 22
|
||||
SWITCH_USER = "admin"
|
||||
KEY_PATH = "/etc/switch-manager/ers5952_key"
|
||||
KEY_PATH = "/etc/switch-manager/ers59100_key"
|
||||
KNOWN_HOSTS = "/etc/switch-manager/known_hosts"
|
||||
TOTP_FILE = "/etc/switch-manager/totp_secret"
|
||||
STATIC_DIR = "./frontend/dist"
|
||||
@@ -71,9 +71,9 @@ def get_or_create_totp_secret() -> str:
|
||||
def setup_totp():
|
||||
secret = get_or_create_totp_secret()
|
||||
uri = pyotp.TOTP(secret).provisioning_uri(
|
||||
name="ERS5952", issuer_name="SwitchManager")
|
||||
name="ERS59100", issuer_name="SwitchManager")
|
||||
print("\n══════════════════════════════════════════════════")
|
||||
print(" ERS 5952 Switch Manager — TOTP Setup")
|
||||
print(" ERS 59100GTS-PWR+ Switch Manager — TOTP Setup")
|
||||
print("══════════════════════════════════════════════════")
|
||||
print(f"\n Manual entry secret:\n {secret}")
|
||||
print(f"\n Provisioning URI (paste into authenticator app):\n {uri}")
|
||||
@@ -217,16 +217,16 @@ def san_vid(v, field="vlan_id") -> int:
|
||||
return vid
|
||||
|
||||
def san_port(v) -> int:
|
||||
"""Validate and return a port number (1–52 for the ERS 5952)."""
|
||||
"""Validate and return a port number (1–100 for the ERS 59100GTS-PWR+)."""
|
||||
p = int(v)
|
||||
if not 1 <= p <= 52:
|
||||
raise ValueError("port: must be 1–52")
|
||||
if not 1 <= p <= 100:
|
||||
raise ValueError("port: must be 1–100")
|
||||
return p
|
||||
|
||||
_ALLOWED_CMD_RE = [
|
||||
re.compile(r'^vlan\s+(create|members|tagging|pvid)\s'),
|
||||
re.compile(r'^no\s+vlan\s+\d+$'),
|
||||
re.compile(r'^interface\s+(FastEthernet|GigabitEthernet|vlan)\s'),
|
||||
re.compile(r'^interface\s+(GigabitEthernet\s+1/\d+|vlan\s+\d+)$'),
|
||||
re.compile(r'^\s+(name|no\s+shutdown|poe|speed|duplex|ip\s+access-group|shutdown)\b'),
|
||||
re.compile(r'^hostname\s+\S+$'),
|
||||
re.compile(r'^ip\s+access-list\s+extended\s'),
|
||||
@@ -314,11 +314,32 @@ def _open_connection() -> paramiko.SSHClient:
|
||||
|
||||
|
||||
def read_cmd(cmd: str) -> str:
|
||||
"""Run a read-only command via the pool. Invalidates pool on error."""
|
||||
"""Run a read-only command in enable mode via interactive shell channel."""
|
||||
try:
|
||||
conn = _pool.get()
|
||||
_, stdout, _ = conn.exec_command(cmd, timeout=10)
|
||||
return stdout.read().decode("utf-8", errors="replace")
|
||||
ch = conn.invoke_shell()
|
||||
ch.settimeout(10)
|
||||
time.sleep(0.4)
|
||||
if ch.recv_ready():
|
||||
ch.recv(4096) # drain login banner
|
||||
for setup in ["terminal length 0", "enable"]:
|
||||
ch.send(setup + "\n")
|
||||
time.sleep(0.3)
|
||||
if ch.recv_ready():
|
||||
ch.recv(4096) # drain prompt output
|
||||
ch.send(cmd + "\n")
|
||||
out = ""
|
||||
deadline = time.time() + 8
|
||||
while time.time() < deadline:
|
||||
if ch.recv_ready():
|
||||
out += ch.recv(4096).decode("utf-8", errors="replace")
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
if out:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
ch.close()
|
||||
return out
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
@@ -368,7 +389,7 @@ def push_one_by_one(commands: list[str]) -> dict:
|
||||
if ch.recv_ready():
|
||||
ch.recv(4096) # drain banner
|
||||
|
||||
for setup in ["enable", "configure terminal"]:
|
||||
for setup in ["terminal length 0", "enable", "configure terminal"]:
|
||||
out, err = _run_one(ch, setup)
|
||||
if err:
|
||||
return {"success": False, "saved": False,
|
||||
@@ -393,7 +414,7 @@ def push_one_by_one(commands: list[str]) -> dict:
|
||||
_run_one(ch, "end")
|
||||
saved = False
|
||||
if stopped_at is None:
|
||||
_, save_err = _run_one(ch, "copy running-config nvram:config.cfg")
|
||||
_, save_err = _run_one(ch, "save config")
|
||||
saved = not save_err
|
||||
if saved:
|
||||
log.info("Config saved to NVRAM")
|
||||
@@ -476,8 +497,8 @@ def _poll_loop():
|
||||
try:
|
||||
data = {
|
||||
"port_status": read_cmd("show interfaces"),
|
||||
"poe_status": read_cmd("show poe-port-status"),
|
||||
"vlan_members": read_cmd("show vlan members"),
|
||||
"poe_status": read_cmd("show poe-main-status"),
|
||||
"vlan_members": read_cmd("show vlan"),
|
||||
"sys_info": read_cmd("show sys-info"),
|
||||
}
|
||||
with _cache_lock:
|
||||
@@ -600,14 +621,14 @@ class PortConfig(BaseModel):
|
||||
|
||||
def build_port(cfg: PortConfig) -> list[str]:
|
||||
"""
|
||||
Generate ERS 5952 CLI commands for a port configuration change.
|
||||
Generate ERS 59100GTS-PWR+ CLI commands for a port configuration change.
|
||||
|
||||
Port 1–48 are FastEthernet; ports 49–52 are GigabitEthernet SFP uplinks.
|
||||
PoE is only available on ports 1–48.
|
||||
Ports 1–96 are GigabitEthernet copper (PoE capable); ports 97–100 are SFP+ uplinks (no PoE).
|
||||
All interfaces use slot/port notation: GigabitEthernet 1/{p}.
|
||||
Returns a list of CLI command strings ready for push_one_by_one().
|
||||
"""
|
||||
p = cfg.port
|
||||
iface = f"FastEthernet {p}" if p <= 48 else f"GigabitEthernet {p}"
|
||||
iface = f"FastEthernet {p}"
|
||||
cmds = []
|
||||
if cfg.description:
|
||||
cmds += [f"interface {iface}", f' name "{cfg.description}"']
|
||||
@@ -623,7 +644,7 @@ def build_port(cfg: PortConfig) -> list[str]:
|
||||
ts = ",".join(str(v) for v in tagged)
|
||||
cmds += [f"vlan members add {ts} {p}", f"vlan tagging {ts} {p}"]
|
||||
cmds.append(f"vlan pvid {p} {native}")
|
||||
if p <= 48:
|
||||
if p <= 96:
|
||||
cmds += [f"interface {iface}",
|
||||
" poe enable" if cfg.poe else " no poe enable"]
|
||||
if cfg.poe:
|
||||
@@ -632,7 +653,7 @@ def build_port(cfg: PortConfig) -> list[str]:
|
||||
|
||||
def build_acl(acl: AclCreate) -> list[str]:
|
||||
"""
|
||||
Generate ERS 5952 CLI commands to create an extended IP ACL and apply it to a VLAN interface.
|
||||
Generate ERS 59100GTS-PWR+ CLI commands to create an extended IP ACL and apply it to a VLAN interface.
|
||||
|
||||
Rules are numbered sequentially starting from 1.
|
||||
The ACL is applied to the VLAN's Layer 3 interface in the specified direction (in/out).
|
||||
@@ -657,7 +678,7 @@ def build_acl(acl: AclCreate) -> list[str]:
|
||||
# APP
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
app = FastAPI(title="ERS 5952 Switch Manager", version="3.0.0",
|
||||
app = FastAPI(title="ERS 59100GTS-PWR+ Switch Manager", version="3.0.0",
|
||||
docs_url="/api/docs", redoc_url=None)
|
||||
|
||||
app.add_middleware(CORSMiddleware, allow_origins=ALLOWED_ORIGINS,
|
||||
@@ -757,7 +778,7 @@ def live():
|
||||
@app.get("/api/switch/config")
|
||||
def running_config():
|
||||
"""Fetch and return the full switch running config (read-only, no auth)."""
|
||||
out = read_cmd("show running-config")
|
||||
out = read_cmd("show config")
|
||||
return {"config": out, "lines": len(out.splitlines())}
|
||||
|
||||
# ── Danger pre-flight (no auth — check before prompting TOTP) ─────────
|
||||
@@ -868,7 +889,7 @@ def _save_devices(devices: list):
|
||||
DEVICES_FILE.write_text(_json.dumps(devices, indent=2))
|
||||
|
||||
def _parse_dhcp_leases(raw: str) -> list:
|
||||
"""Parse ERS 5952 'show dhcp-server leases' output."""
|
||||
"""Parse ERS 59100GTS-PWR+ 'show dhcp-server leases' output."""
|
||||
import re
|
||||
leases = []
|
||||
for line in raw.splitlines():
|
||||
@@ -931,7 +952,7 @@ class PinholeRequest(BaseModel):
|
||||
allow: bool = True
|
||||
|
||||
def _build_dhcp_reservation_cmds(device: DeviceEntry) -> list:
|
||||
"""Generate ERS 5952 CLI for DHCP reservation (static binding)."""
|
||||
"""Generate ERS 59100GTS-PWR+ CLI for DHCP reservation (static binding)."""
|
||||
mac_clean = device.mac.replace(':','-').upper()
|
||||
return [
|
||||
f"ip dhcp-server static-binding {device.ip}",
|
||||
@@ -1317,7 +1338,7 @@ def _get_opnsense_leases(cfg: dict) -> list:
|
||||
return []
|
||||
|
||||
def _get_switch_reservations() -> list:
|
||||
"""Fetch DHCP static bindings from ERS 5952."""
|
||||
"""Fetch DHCP static bindings from ERS 59100GTS-PWR+."""
|
||||
import re as _re
|
||||
try:
|
||||
raw = read_cmd("show dhcp-server static-binding")
|
||||
@@ -1369,7 +1390,7 @@ def _get_relay_status() -> dict:
|
||||
return {"vlans": {}, "ok": False}
|
||||
|
||||
def _build_relay_cmds(opnsense_ip: str, vlan_ids: list) -> list:
|
||||
"""Generate ERS 5952 CLI to set ip helper-address on the specified VLANs."""
|
||||
"""Generate ERS 59100GTS-PWR+ CLI to set ip helper-address on the specified VLANs."""
|
||||
cmds = []
|
||||
for vid in vlan_ids:
|
||||
cmds += [
|
||||
@@ -1706,7 +1727,7 @@ def _build_ctrld_toml(vlan_profiles: list, local_domain: str = "lan",
|
||||
active = [vp for vp in vlan_profiles if vp.get("resolver_id", "").strip()]
|
||||
|
||||
lines = [
|
||||
"# ctrld configuration — generated by Avaya 5952 Switch Manager",
|
||||
"# ctrld configuration — generated by Avaya 59100GTS-PWR+ Switch Manager",
|
||||
"# Documentation: https://docs.controld.com/docs/ctrld",
|
||||
"",
|
||||
"[service]",
|
||||
@@ -2212,7 +2233,7 @@ def _generate_dnsmasq_conf(entries: list, mgmt_ip: str = "192.168.99.50") -> str
|
||||
|
||||
lines = [
|
||||
"# dnsmasq — local .lan hostname resolution",
|
||||
"# Generated by Avaya 5952 Switch Manager",
|
||||
"# Generated by Avaya 59100GTS-PWR+ Switch Manager",
|
||||
"# Listens on port 5353 (mapped from Docker container port 53)",
|
||||
"# ctrld forwards *.lan and *.local here",
|
||||
"",
|
||||
|
||||
Reference in New Issue
Block a user