obmp-docker/gnmi/gnmi_grpc_config.py
sam dcebf15bb3 Add Phase 4: gNMI streaming telemetry and traffic generator
- gNMI integration: NETCONF script to enable gRPC on all 9 routers,
  Telegraf container with gnmi input plugin, InfluxDB for time-series
  storage, 3 Grafana telemetry dashboards (utilization, errors, combined)
- Traffic generator: Scapy-based dual-mode container (sender/responder)
  with Flask API, RFC 2544 test suite (throughput, latency, frame-loss,
  back-to-back), Vue 3 web UI with flow builder, test runner, real-time
  stats monitor, and results export
- docker-compose.yml updated with influxdb, telegraf, traffic-gen,
  traffic-gen-ui services
- Full documentation in DOCS.md sections 15-16

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:29:44 -07:00

139 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""
gNMI gRPC Configuration Script
===============================
Enables gRPC dial-in telemetry on all 9 IOS-XR routers so that
Telegraf (or any gNMI collector) can subscribe to streaming
telemetry data.
What this script applies per router:
- gRPC server on port 57400 with TLS disabled
- YANG model: Cisco-IOS-XR-man-ems-cfg
Router targets:
CORE-01 (10.100.0.100)
CORE-02 (10.100.0.200)
R9K-01 (10.100.0.1) through R9K-07 (10.100.0.7)
"""
from ncclient import manager
import sys
GRPC_NS = 'http://cisco.com/ns/yang/Cisco-IOS-XR-man-ems-cfg'
ROUTERS = [
('10.100.0.100', 'CORE-01'),
('10.100.0.200', 'CORE-02'),
('10.100.0.1', 'R9K-01'),
('10.100.0.2', 'R9K-02'),
('10.100.0.3', 'R9K-03'),
('10.100.0.4', 'R9K-04'),
('10.100.0.5', 'R9K-05'),
('10.100.0.6', 'R9K-06'),
('10.100.0.7', 'R9K-07'),
]
GRPC_CONFIG_XML = """
<config>
<grpc xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-man-ems-cfg">
<port>57400</port>
<no-tls/>
</grpc>
</config>
"""
def configure_router(mgmt_ip, label):
"""Apply gRPC configuration via NETCONF edit-config + commit."""
print(f"\n{''*60}")
print(f" Configuring {label} ({mgmt_ip})")
print(f"{''*60}")
print(f" Applying: gRPC port=57400 no-tls")
try:
with manager.connect(
host=mgmt_ip,
port=830,
username='webui',
password='cisco',
hostkey_verify=False,
device_params={'name': 'iosxr'},
timeout=20,
) as m:
print(" → Applying gRPC configuration...")
m.edit_config(target='candidate', config=GRPC_CONFIG_XML)
print(" → Committing...")
m.commit()
print(f"{label} done.")
return True
except Exception as e:
print(f" ✗ ERROR on {label}: {e}")
return False
def verify_router(mgmt_ip, label):
"""Re-read running config to confirm the grpc block is present."""
try:
with manager.connect(
host=mgmt_ip, port=830, username='webui', password='cisco',
hostkey_verify=False, device_params={'name': 'iosxr'}, timeout=10
) as m:
filt_grpc = """<filter>
<grpc xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-man-ems-cfg">
<port/>
<no-tls/>
</grpc>
</filter>"""
r_grpc = m.get_config(source='running', filter=filt_grpc)
has_grpc = '<port>57400</port>' in str(r_grpc)
has_notls = '<no-tls' in str(r_grpc)
g = '' if has_grpc else ''
t = '' if has_notls else ''
status = 'OK' if (has_grpc and has_notls) else 'INCOMPLETE'
print(f" {label:8s} grpc-port={g} no-tls={t} [{status}]")
except Exception as e:
print(f" {label:8s} verify error: {e}")
def main():
print("gNMI gRPC Configuration Script")
print("================================")
print(f"Targets: all {len(ROUTERS)} routers")
print()
results = []
for mgmt_ip, label in ROUTERS:
ok = configure_router(mgmt_ip, label)
results.append((mgmt_ip, label, ok))
# Summary
print(f"\n{'='*60}")
print("Post-apply verification")
print('='*60)
print(f" {'Router':8s} {'gRPC Port':9s} {'No-TLS':6s} Status")
for mgmt_ip, label, ok in results:
if ok:
verify_router(mgmt_ip, label)
else:
print(f" {label:8s} skipped (apply failed)")
failed = [label for _, label, ok in results if not ok]
print()
if failed:
print(f"FAILED: {', '.join(failed)}")
sys.exit(1)
else:
print("All routers configured successfully.")
print()
print("gRPC is now listening on port 57400 (no TLS) on all routers.")
print("Next: start Telegraf with gNMI input plugin to begin collecting telemetry.")
if __name__ == '__main__':
main()