Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Deploy to GNS3 lab via CONSOLE (telnet) - no SSH required! | |
| This version deploys directly via console/telnet, | |
| which works immediately without network configuration. | |
| """ | |
| import sys | |
| import telnetlib | |
| import time | |
| from pathlib import Path | |
| # Console port mapping (from GNS3 API) | |
| DEVICES = [ | |
| { | |
| 'name': 'SW-HQ-Core', | |
| 'console_port': 5046, | |
| 'config': """ | |
| enable | |
| configure terminal | |
| hostname SW-HQ-Core | |
| ! | |
| vlan 10 | |
| name Data | |
| vlan 20 | |
| name Voice | |
| ! | |
| interface GigabitEthernet0/1 | |
| description Uplink | |
| switchport mode trunk | |
| no shutdown | |
| ! | |
| end | |
| write memory | |
| """ | |
| }, | |
| { | |
| 'name': 'SW-West', | |
| 'console_port': 5059, | |
| 'config': """ | |
| enable | |
| configure terminal | |
| hostname SW-West | |
| ! | |
| vlan 10 | |
| name Data | |
| vlan 20 | |
| name Voice | |
| vlan 30 | |
| name Guest | |
| ! | |
| interface GigabitEthernet0/1 | |
| description Uplink | |
| switchport mode trunk | |
| no shutdown | |
| ! | |
| interface GigabitEthernet0/2 | |
| description Access-Port | |
| switchport mode access | |
| switchport access vlan 10 | |
| no shutdown | |
| ! | |
| end | |
| write memory | |
| """ | |
| }, | |
| { | |
| 'name': 'SW-East', | |
| 'console_port': 5069, | |
| 'config': """ | |
| enable | |
| configure terminal | |
| hostname SW-East | |
| ! | |
| vlan 10 | |
| name Data | |
| vlan 20 | |
| name Voice | |
| vlan 40 | |
| name Management | |
| ! | |
| interface GigabitEthernet0/1 | |
| description Uplink | |
| switchport mode trunk | |
| no shutdown | |
| ! | |
| interface GigabitEthernet0/2 | |
| description Access-Port | |
| switchport mode access | |
| switchport access vlan 10 | |
| no shutdown | |
| ! | |
| interface Vlan40 | |
| description Management | |
| ip address 10.0.40.1 255.255.255.0 | |
| no shutdown | |
| ! | |
| end | |
| write memory | |
| """ | |
| }, | |
| ] | |
| def deploy_to_device(device): | |
| """Deploy config via console""" | |
| print(f"\n{'='*70}") | |
| print(f"Deploying to {device['name']} (console port {device['console_port']})") | |
| print(f"{'='*70}\n") | |
| try: | |
| # Connect via telnet | |
| tn = telnetlib.Telnet('localhost', device['console_port'], timeout=10) | |
| # Wake up device | |
| tn.write(b"\r\n\r\n") | |
| time.sleep(1) | |
| # Send config | |
| lines = device['config'].strip().split('\n') | |
| total_lines = len([l for l in lines if l.strip()]) | |
| print(f"Sending {total_lines} configuration commands...") | |
| for i, line in enumerate(lines, 1): | |
| if line.strip(): | |
| # Show progress every 5 lines | |
| if i % 5 == 0: | |
| print(f" Progress: {i}/{total_lines} commands sent...") | |
| tn.write(line.encode('ascii') + b"\r\n") | |
| time.sleep(0.2) | |
| # Final newline and wait | |
| tn.write(b"\r\n") | |
| time.sleep(2) | |
| # Get response | |
| output = tn.read_very_eager().decode('ascii', errors='ignore') | |
| tn.close() | |
| # Check for errors | |
| if '%' in output or 'Invalid' in output: | |
| print(f"\n⚠️ Warning: Possible errors in output") | |
| print("Last 20 lines of output:") | |
| print('\n'.join(output.split('\n')[-20:])) | |
| else: | |
| print(f"✅ Successfully deployed to {device['name']}") | |
| return True | |
| except Exception as e: | |
| print(f"❌ Error: {e}") | |
| return False | |
| def verify_deployment(device): | |
| """Verify config was applied""" | |
| print(f"\nVerifying {device['name']}...") | |
| try: | |
| tn = telnetlib.Telnet('localhost', device['console_port'], timeout=5) | |
| # Send show commands | |
| tn.write(b"\r\n") | |
| time.sleep(0.5) | |
| tn.write(b"show running-config | include hostname\r\n") | |
| time.sleep(1) | |
| tn.write(b"show vlan brief\r\n") | |
| time.sleep(1) | |
| output = tn.read_very_eager().decode('ascii', errors='ignore') | |
| tn.close() | |
| if device['name'] in output: | |
| print(f" ✓ Hostname configured correctly") | |
| if 'Vlan' in output or 'VLAN' in output: | |
| print(f" ✓ VLANs configured") | |
| return True | |
| except Exception as e: | |
| print(f" ⚠️ Verification failed: {e}") | |
| return False | |
| def main(): | |
| """Main entry point""" | |
| print("\n" + "="*70) | |
| print("GNS3 Lab Deployment - Console Mode (No SSH Required)") | |
| print("="*70) | |
| print("\nThis will deploy configurations to:") | |
| for dev in DEVICES: | |
| print(f" - {dev['name']:15s} (console port {dev['console_port']})") | |
| print("\nDeployment method: Direct console/telnet") | |
| print("Network access: NOT required") | |
| response = input("\nProceed? (yes/no): ") | |
| if response.lower() != 'yes': | |
| print("Aborted.") | |
| return 1 | |
| # Deploy to each device | |
| print("\n" + "="*70) | |
| print("Starting Deployment") | |
| print("="*70) | |
| results = {} | |
| for device in DEVICES: | |
| success = deploy_to_device(device) | |
| results[device['name']] = success | |
| time.sleep(2) | |
| # Verify deployments | |
| print("\n" + "="*70) | |
| print("Verifying Deployments") | |
| print("="*70) | |
| for device in DEVICES: | |
| verify_deployment(device) | |
| # Summary | |
| print("\n" + "="*70) | |
| print("Deployment Summary") | |
| print("="*70) | |
| success_count = sum(1 for v in results.values() if v) | |
| print(f"\n✅ Successfully deployed: {success_count}/{len(DEVICES)} devices") | |
| for name, success in results.items(): | |
| status = "✅ SUCCESS" if success else "❌ FAILED" | |
| print(f" {name:15s}: {status}") | |
| print("\n" + "="*70) | |
| print("🎉 Stage 6 Deployment Complete!") | |
| print("="*70) | |
| print("\nYou just deployed configurations to REAL GNS3 devices!") | |
| print("This demonstrates:") | |
| print(" ✓ Multi-device deployment") | |
| print(" ✓ Configuration templating") | |
| print(" ✓ Automated deployment workflow") | |
| print(" ✓ Verification checks") | |
| print("\nNext: You can now test SSH-based deployment if you configure") | |
| print(" network connectivity between host and GNS3 devices.\n") | |
| return 0 if success_count == len(DEVICES) else 1 | |
| if __name__ == '__main__': | |
| try: | |
| sys.exit(main()) | |
| except KeyboardInterrupt: | |
| print("\n\nAborted by user") | |
| sys.exit(1) | |
| except Exception as e: | |
| print(f"\n❌ Unexpected error: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| sys.exit(1) | |