Spaces:
Sleeping
Sleeping
| #!/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) | |