# gnmi-eos gNMI CLI tool and Python library for Arista EOS devices. Interact with Arista EOS devices via gNMI/YANG: get configuration and state, push changes, subscribe to counters and events. ## Features - **CLI** — usable via `uvx gnmi-eos` or installed globally - **Library** — importable as `from gnmi_eos import GNMIClient` - **Validated YANG paths** for EOS 4.35.0F (OpenConfig + Arista experimental models) ## Installation ```bash # As a CLI tool with uvx (no install needed) uvx --from git+https://gitea.arnodo.fr/Damien/gnmi-eos gnmi-eos --help # Or install permanently uv tool install git+https://gitea.arnodo.fr/Damien/gnmi-eos ``` ## Shell Alias To use `gnmi-eos` directly without installing it, add this alias to your shell config (`~/.bashrc`, `~/.zshrc`, etc.): ```bash alias gnmi-eos='uvx --from git+https://gitea.arnodo.fr/Damien/gnmi-eos gnmi-eos' ``` Then reload your shell: ```bash source ~/.zshrc # or ~/.bashrc ``` You can now use `gnmi-eos` as if it were installed: ```bash gnmi-eos --help gnmi-eos capabilities --target leaf1:6030 gnmi-eos subscribe --target leaf1:6030 --path "/interfaces/interface/state/counters" --mode sample ``` ## CLI Usage Credentials can be passed as options or via environment variables: ```bash export GNMI_TARGET=leaf1:6030 export GNMI_USERNAME=admin export GNMI_PASSWORD=admin ``` ### Get capabilities ```bash gnmi-eos capabilities --target leaf1:6030 ``` ### Get data ```bash # Get interface state gnmi-eos get --target leaf1:6030 --path "/interfaces/interface[name=Ethernet1]/state" # Get config only gnmi-eos get --target leaf1:6030 --path "/interfaces" --type config # Output as raw JSON or save to file gnmi-eos get --target leaf1:6030 --path "/" --output json gnmi-eos get --target leaf1:6030 --path "/" --output file:dump.json ``` ### Subscribe ```bash # Subscribe to interface state changes (on-change) gnmi-eos subscribe --target leaf1:6030 \ --path "/interfaces/interface/state/oper-status" \ --mode on-change # Sample interface counters every 10s gnmi-eos subscribe --target leaf1:6030 \ --path "/interfaces/interface[name=Ethernet1]/state/counters" \ --mode sample --interval 10 # Multiple paths, stop after 5 updates gnmi-eos subscribe --target leaf1:6030 \ --path "/interfaces/interface/state/oper-status" \ --path "/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor/state/session-state" \ --count 5 ``` ### Set configuration ```bash # Dry-run (default — safe) gnmi-eos set --target leaf1:6030 \ --path "/interfaces/interface[name=Ethernet1]/config/description" \ --value "Uplink to Spine" # Actually apply gnmi-eos set --target leaf1:6030 \ --path "/interfaces/interface[name=Ethernet1]/config/description" \ --value "Uplink to Spine" \ --no-dry-run ``` ### Show known YANG paths ```bash gnmi-eos paths ``` ## Library Usage ```python from gnmi_eos import GNMIClient from gnmi_eos.yang.paths import Interfaces, BGP, FabricSubscriptions with GNMIClient(host="leaf1", port=6030, username="admin", password="admin") as client: # Get capabilities caps = client.capabilities() # Get interface counters counters = client.get(Interfaces.counters("Ethernet1")) # Get BGP neighbor state state = client.get(BGP.neighbor_state("10.0.0.1")) # Subscribe to interface changes for update in client.subscribe( paths=[str(FabricSubscriptions.INTERFACE_STATE)], stream_mode="on-change", ): print(update) ``` ## YANG Models Validated against **Arista EOS 4.35.0F** with ContainerLab (cEOS). | Category | Model | |----------|-------| | Interfaces, VLANs, BGP | `openconfig-*` | | VXLAN | `arista-exp-eos-vxlan` | | MLAG | `arista-exp-eos-mlag` | | EVPN | `arista-exp-eos-evpn` | > **Note:** MLAG and EVPN state (peer status, learned routes) is not exposed via gNMI — use eAPI for operational state. ## Subscription Notes For Arista EOS, use native paths **without** module prefixes for `ON_CHANGE` subscriptions: ``` ✅ /interfaces/interface[name=Ethernet1]/state ❌ /openconfig-interfaces:interfaces/... ```