#!/usr/bin/env python3 """ Deploy initial configuration to GNS3 lab devices to set up management IPs. This is a bootstrap script that configures management IPs on your GNS3 devices so they can be managed via SSH/NAPALM in the main deployment workflow. """ import sys import time from pathlib import Path # Add parent directory to path sys.path.insert(0, str(Path(__file__).parent.parent)) from agent.device_driver import DeviceType, DeviceCredentials from agent.deployment_engine import DeploymentEngine, DeploymentTask # Initial bootstrap configs - these set up management access BOOTSTRAP_CONFIGS = { 'SW-HQ-Core': """ enable configure terminal hostname SW-HQ-Core ! ip domain-name lab.grahampaasch.com ! interface Vlan1 ip address 192.168.122.10 255.255.255.0 no shutdown ! ip route 0.0.0.0 0.0.0.0 192.168.122.1 ! username admin privilege 15 password cisco enable secret cisco ! line vty 0 4 login local transport input ssh ! crypto key generate rsa modulus 2048 ! end write memory """, 'SW-West': """ enable configure terminal hostname SW-West ! ip domain-name lab.grahampaasch.com ! interface Vlan1 ip address 192.168.122.20 255.255.255.0 no shutdown ! ip route 0.0.0.0 0.0.0.0 192.168.122.1 ! username admin privilege 15 password cisco enable secret cisco ! line vty 0 4 login local transport input ssh ! crypto key generate rsa modulus 2048 ! end write memory """, 'SW-East': """ enable configure terminal hostname SW-East ! ip domain-name lab.grahampaasch.com ! interface Vlan1 ip address 192.168.122.30 255.255.255.0 no shutdown ! ip route 0.0.0.0 0.0.0.0 192.168.100.1 ! username admin privilege 15 password cisco enable secret cisco ! line vty 0 4 login local transport input ssh ! crypto key generate rsa modulus 2048 ! end write memory """ } # Console port mapping CONSOLE_PORTS = { 'SW-HQ-Core': 5046, 'SW-West': 5059, 'SW-East': 5069, } def deploy_via_console(device_name, config, console_port): """ Deploy config via console (telnet). For initial bootstrap when SSH isn't configured yet. """ import telnetlib print(f"\n{'='*70}") print(f"Deploying to {device_name} via console port {console_port}") print(f"{'='*70}") try: tn = telnetlib.Telnet('localhost', console_port, timeout=10) # Wait for prompt print(" Waiting for device prompt...") time.sleep(2) # Send enters to wake up tn.write(b"\r\n\r\n") time.sleep(1) # Send config line by line print(" Sending configuration...") for line in config.strip().split('\n'): if line.strip(): print(f" > {line}") tn.write(line.encode('ascii') + b"\r\n") time.sleep(0.3) # Final newline tn.write(b"\r\n") time.sleep(2) # Get output output = tn.read_very_eager().decode('ascii', errors='ignore') tn.close() print(f"\n ✅ Configuration deployed to {device_name}") print(f" Management IP should be configured") return True except Exception as e: print(f"\n ❌ Error deploying to {device_name}: {e}") return False def verify_ssh_access(hostname, username='admin', password='cisco'): """ Verify we can access device via SSH. """ print(f"\nVerifying SSH access to {hostname}...") from agent.device_driver import DeviceDriver driver = DeviceDriver(use_napalm=True) creds = DeviceCredentials( hostname=hostname, username=username, password=password, device_type=DeviceType.CISCO_IOS, timeout=10 ) conn = driver.connect(creds) if conn.status.value == 'connected': print(f" ✅ SSH access working!") driver.disconnect(hostname) return True else: print(f" ⚠️ SSH not available yet: {conn.last_error}") return False def main(): """Main entry point""" print("\n" + "="*70) print("GNS3 Lab Bootstrap Configuration") print("="*70) print("\nThis script will:") print(" 1. Deploy initial configs to devices via console (telnet)") print(" 2. Configure management IPs (192.168.100.x)") print(" 3. Enable SSH access for Stage 6 deployment") print("\nDevices:") for name, port in CONSOLE_PORTS.items(): print(f" - {name:15s} console port {port}") response = input("\nProceed with bootstrap? (yes/no): ") if response.lower() != 'yes': print("Aborted.") return 1 # Deploy to each device success_count = 0 for device_name in CONSOLE_PORTS.keys(): config = BOOTSTRAP_CONFIGS.get(device_name) port = CONSOLE_PORTS[device_name] if deploy_via_console(device_name, config, port): success_count += 1 print(f"\n{'='*70}") print(f"Bootstrap Summary: {success_count}/{len(CONSOLE_PORTS)} devices configured") print(f"{'='*70}") if success_count > 0: print("\n⏳ Waiting 30 seconds for devices to apply configs...") time.sleep(30) print("\nVerifying SSH access...") # Test SSH connectivity ssh_working = [] for device_name in CONSOLE_PORTS.keys(): ip = BOOTSTRAP_CONFIGS[device_name].split('ip address ')[1].split()[0] if verify_ssh_access(ip): ssh_working.append(device_name) print(f"\n{'='*70}") print("Next Steps:") print(f"{'='*70}") if ssh_working: print(f"\n✅ SSH working on {len(ssh_working)} devices!") print("\nYou can now use the main deployment script:") print(" python examples/deploy_to_gns3_lab.py --device SW-HQ-Core --dry-run") print("\nUpdate examples/deploy_to_gns3_lab.py with these IPs:") print("\nGNS3_DEVICES = [") configs = { 'SW-HQ-Core': '192.168.122.10', 'SW-West': '192.168.122.20', 'SW-East': '192.168.122.30', } for name, ip in configs.items(): print(f" {{'name': '{name}', 'hostname': '{ip}', ...}},") print("]") else: print("\n⚠️ SSH not yet available.") print("Wait a bit longer and verify manually:") print(" ssh admin@192.168.100.10 (password: cisco)") return 0 if __name__ == '__main__': try: sys.exit(main()) except KeyboardInterrupt: print("\n\nAborted by user") sys.exit(1)