feat(build): configure project tooling and update dependencies
- Replace placeholder deps with click, pygnmi, and rich for CLI functionality - Add fabric-orch CLI entry point via project.scripts - Configure hatchling as build backend with wheel/sdist targets - Add ruff linter configuration for code quality - Add dev dependency group with ruff - Alphabetize yang module imports
This commit is contained in:
183
src/gnmi/README.md
Normal file
183
src/gnmi/README.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# gNMI Client Module
|
||||
|
||||
This module provides a high-level gNMI client wrapper for interacting with Arista devices using pygnmi.
|
||||
|
||||
## Features
|
||||
|
||||
- Connection management with context manager support
|
||||
- Get capabilities (list supported YANG models)
|
||||
- Get configuration and state data at any YANG path
|
||||
- Set configuration with dry-run support
|
||||
- Subscribe to path updates (on-change, sample modes)
|
||||
- Error handling with meaningful exceptions
|
||||
|
||||
## Installation
|
||||
|
||||
Ensure you have the required dependencies:
|
||||
|
||||
```bash
|
||||
uv add pygnmi click rich
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Connection
|
||||
|
||||
```python
|
||||
from gnmi import GNMIClient
|
||||
|
||||
# Using context manager (recommended)
|
||||
with GNMIClient(
|
||||
host="172.16.0.50",
|
||||
port=6030,
|
||||
username="admin",
|
||||
password="admin",
|
||||
insecure=True
|
||||
) as client:
|
||||
# Use the client
|
||||
caps = client.capabilities()
|
||||
print(caps)
|
||||
```
|
||||
|
||||
### Get Capabilities
|
||||
|
||||
```python
|
||||
with GNMIClient(host="172.16.0.50", port=6030) as client:
|
||||
# Get raw capabilities
|
||||
caps = client.capabilities()
|
||||
print(f"gNMI Version: {caps['gnmi_version']}")
|
||||
|
||||
# Get parsed models
|
||||
models = client.get_models()
|
||||
for model in models:
|
||||
print(f" {model.name} ({model.organization}) v{model.version}")
|
||||
```
|
||||
|
||||
### Get Data
|
||||
|
||||
```python
|
||||
with GNMIClient(host="172.16.0.50", port=6030) as client:
|
||||
# Get all data (config + state)
|
||||
result = client.get("/interfaces/interface[name=Ethernet1]")
|
||||
|
||||
# Get config only
|
||||
result = client.get(
|
||||
"/interfaces/interface[name=Ethernet1]",
|
||||
data_type="config"
|
||||
)
|
||||
|
||||
# Get state only
|
||||
result = client.get(
|
||||
"/interfaces/interface[name=Ethernet1]/state",
|
||||
data_type="state"
|
||||
)
|
||||
|
||||
# Get multiple paths
|
||||
result = client.get([
|
||||
"/interfaces/interface[name=Ethernet1]/state",
|
||||
"/interfaces/interface[name=Ethernet2]/state",
|
||||
])
|
||||
```
|
||||
|
||||
### Set Configuration
|
||||
|
||||
```python
|
||||
with GNMIClient(host="172.16.0.50", port=6030) as client:
|
||||
# Dry-run (default) - shows what would be set
|
||||
result = client.set(
|
||||
path="/interfaces/interface[name=Ethernet1]/config/description",
|
||||
value="Uplink to Spine",
|
||||
dry_run=True
|
||||
)
|
||||
|
||||
# Actually apply the change
|
||||
result = client.set(
|
||||
path="/interfaces/interface[name=Ethernet1]/config/description",
|
||||
value="Uplink to Spine",
|
||||
dry_run=False
|
||||
)
|
||||
|
||||
# Replace operation
|
||||
result = client.set(
|
||||
path="/interfaces/interface[name=Ethernet1]/config",
|
||||
value={"description": "New config", "enabled": True},
|
||||
operation="replace",
|
||||
dry_run=False
|
||||
)
|
||||
|
||||
# Delete operation
|
||||
result = client.set(
|
||||
path="/interfaces/interface[name=Ethernet1]/config/description",
|
||||
value=None,
|
||||
operation="delete",
|
||||
dry_run=False
|
||||
)
|
||||
```
|
||||
|
||||
### Subscribe to Updates
|
||||
|
||||
```python
|
||||
with GNMIClient(host="172.16.0.50", port=6030) as client:
|
||||
# Subscribe to interface state changes
|
||||
subscription = client.subscribe(
|
||||
paths="/interfaces/interface/state/oper-status",
|
||||
mode="stream",
|
||||
stream_mode="on-change"
|
||||
)
|
||||
|
||||
# Process updates
|
||||
for update in subscription:
|
||||
print(update)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The module provides specific exceptions for different error types:
|
||||
|
||||
```python
|
||||
from gnmi import GNMIClient, GNMIError, GNMIConnectionError, GNMIPathError
|
||||
|
||||
try:
|
||||
with GNMIClient(host="172.16.0.50", port=6030) as client:
|
||||
result = client.get("/invalid/path")
|
||||
except GNMIConnectionError as e:
|
||||
print(f"Connection failed: {e}")
|
||||
except GNMIPathError as e:
|
||||
print(f"Invalid path: {e}")
|
||||
except GNMIError as e:
|
||||
print(f"gNMI error: {e}")
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The CLI supports these environment variables for defaults:
|
||||
|
||||
- `GNMI_TARGET` - Target device (host:port)
|
||||
- `GNMI_USERNAME` - Username for authentication
|
||||
- `GNMI_PASSWORD` - Password for authentication
|
||||
|
||||
## Path Format Notes
|
||||
|
||||
For Arista EOS, use native paths **without** module prefixes for subscriptions:
|
||||
|
||||
```python
|
||||
# ✅ Correct - native path
|
||||
"/interfaces/interface[name=Ethernet1]/state"
|
||||
|
||||
# ❌ Incorrect - with module prefix (may fail for subscriptions)
|
||||
"/openconfig-interfaces:interfaces/interface[name=Ethernet1]/state"
|
||||
```
|
||||
|
||||
## Validated Paths
|
||||
|
||||
These paths have been validated against Arista cEOS 4.35.0F:
|
||||
|
||||
| Category | Path | Notes |
|
||||
|----------|------|-------|
|
||||
| Interfaces | `/interfaces/interface[name=Ethernet1]/state` | Full state |
|
||||
| BGP | `/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor/state` | All neighbors |
|
||||
| VXLAN | `/interfaces/interface[name=Vxlan1]/arista-vxlan/vlan-to-vnis` | VNI mappings |
|
||||
| MLAG | `/arista/eos/mlag/config` | Config only |
|
||||
| EVPN | `/arista/eos/evpn` | Config only |
|
||||
|
||||
See `docs/yang-paths.md` for complete path documentation.
|
||||
Reference in New Issue
Block a user