--- testbed: name: Network_Testbed credentials: default: username: cisco password: cisco devices: R1: os: ios type: router connections: cli: protocol: ssh ip: 10.0.0.103 port: 22 R2: os: ios type: router connections: cli: protocol: ssh ip: 10.0.0.104 port: 22 R3: os: ios type: router connections: cli: protocol: ssh ip: 10.0.0.105 port: 22 import csv import sys from collections import defaultdict from genie.testbed import load def load_csv(path): """Load expected interfaces from CSV: {device: {interface: {ip, description}}}""" result = defaultdict(dict) with open(path) as f: for row in csv.DictReader(f): result[row['device']][row['interface']] = { 'ip': row['ip_address'].split('/')[0], 'description': row.get('description', '') } return dict(result) def get_actual_state(device): """Get current IPs and descriptions from device.""" ip_brief = device.parse('show ip interface brief').get('interface', {}) ips = {name: data.get('ip_address') for name, data in ip_brief.items() if data.get('ip_address', 'unassigned') != 'unassigned'} desc_output = device.parse('show interfaces description').get('interfaces', {}) descriptions = {name: data.get('description', '') for name, data in desc_output.items()} return ips, descriptions def check_interfaces(device_name, expected, actual_ips, actual_descriptions): """Compare expected vs actual interfaces. Returns True if all match.""" ok = True for interface, expected_values in expected.items(): if interface not in actual_ips: print(f" [FAIL] {device_name}: {interface} not found") ok = False continue if actual_ips[interface] != expected_values['ip']: print(f" [FAIL] {device_name}: {interface} IP {actual_ips[interface]} != {expected_values['ip']}") ok = False else: print(f" [OK] {device_name}: {interface} - {expected_values['ip']}") if expected_values['description'] and actual_descriptions.get(interface, '') != expected_values['description']: print(f" [FAIL] {device_name}: {interface} description '{actual_descriptions.get(interface, '')}' != '{expected_values['description']}'") ok = False elif expected_values['description']: print(f" [OK] {device_name}: {interface} - description '{expected_values['description']}'") return ok def ping(device, target): """Ping target from device. Returns True on success.""" try: result = str(device.ping(target)) return '!' in result or ('Success rate' in result and 'is 0' not in result) except Exception as e: print(f" Ping error: {e}") return False def main(): # Parse command line arguments if len(sys.argv) < 3: sys.exit("Usage: python verify_interfaces_connectivity.py ") print("=" * 60) # Load expected configuration from CSV print(f"Loading CSV: {sys.argv[1]}...") expected = load_csv(sys.argv[1]) print(f"Loaded: {', '.join(f'{device}: {len(interfaces)} interfaces' for device, interfaces in expected.items())}") print("=" * 60) # Load testbed file print(f"Loading testbed: {sys.argv[2]}...") testbed = load(sys.argv[2]) print("Testbed loaded.") print("=" * 60) print("Checking interfaces...") # Compare configuration and source of truth all_ok = True connected = [] for device_name, interfaces in expected.items(): if device_name not in testbed.devices: print(f"\n[ERROR] {device_name} not in testbed") all_ok = False continue device = testbed.devices[device_name] print(f"\nConnecting to {device_name}...") try: device.connect(log_stdout=False) connected.append(device) except Exception as e: print(f" [ERROR] Connection failed: {e}") all_ok = False continue ips, descriptions = get_actual_state(device) if not check_interfaces(device_name, interfaces, ips, descriptions): all_ok = False # Test connectivity to critical infrastructure PING_TARGET_IP = "10.0.0.1" print("=" * 60) ping_ok = True if all_ok: print(f"All interfaces OK! Pinging {PING_TARGET_IP}...") for device in connected: status = "[OK]" if ping(device, PING_TARGET_IP) else "[FAIL]" if status == "[FAIL]": ping_ok = False print(f" {status} {device.name} -> {PING_TARGET_IP}") else: print("Interface check FAILED - skipping ping test") if not all_ok: sys.exit("ERROR: Interface validation failed") if not ping_ok: sys.exit("ERROR: Connectivity check failed") print("\nAll checks passed.") if __name__ == "__main__": main()