#!/usr/bin/env python3 """ Rebuild CCNA topology with: - Proper switch icons - Single trunk links (no redundancy) - Clean hierarchical layout - Simple access-core-access design """ import requests import json import os GNS3_SERVER = os.getenv("GNS3_SERVER", "http://localhost:3080") GNS3_API = f"{GNS3_SERVER}/v2" PROJECT_NAME = os.getenv("GNS3_PROJECT_NAME", "overgrowth") IOSVL2_TEMPLATE_ID = "25dd7340-2e92-4e45-83de-f88077a24ceb" def get_project_id(name): resp = requests.get(f"{GNS3_API}/projects") projects = resp.json() project = next((p for p in projects if p['name'] == name), None) return project['project_id'] if project else None def delete_all_nodes(project_id): resp = requests.get(f"{GNS3_API}/projects/{project_id}/nodes") nodes = resp.json() print(f"šŸ—‘ļø Cleaning up {len(nodes)} existing nodes...") for node in nodes: requests.delete(f"{GNS3_API}/projects/{project_id}/nodes/{node['node_id']}") def create_switch(project_id, name, x, y): """Create Cisco IOSvL2 switch with PROPER ICON""" data = { "name": name, "node_type": "qemu", "compute_id": "local", "template_id": IOSVL2_TEMPLATE_ID, "properties": { "qemu_path": "/usr/bin/qemu-system-x86_64", "platform": "x86_64", "adapters": 16, "ram": 1024, "hda_disk_image": "vios_l2-adventerprisek9-m.03.2017.qcow2" }, "symbol": ":/symbols/multilayer_switch.svg", # PROPER SWITCH ICON! "x": x, "y": y } resp = requests.post(f"{GNS3_API}/projects/{project_id}/nodes", json=data) return resp.json() if resp.status_code in [200, 201] else None def create_pc(project_id, name, x, y): """Create VPCS with proper computer icon""" data = { "name": name, "node_type": "vpcs", "compute_id": "local", "symbol": ":/symbols/vpcs_guest.svg", # Better PC icon "x": x, "y": y } resp = requests.post(f"{GNS3_API}/projects/{project_id}/nodes", json=data) return resp.json() if resp.status_code in [200, 201] else None def create_link(project_id, node1_id, adapter1, port1, node2_id, adapter2, port2, desc=""): data = { "nodes": [ {"node_id": node1_id, "adapter_number": adapter1, "port_number": port1}, {"node_id": node2_id, "adapter_number": adapter2, "port_number": port2} ] } resp = requests.post(f"{GNS3_API}/projects/{project_id}/links", json=data) if resp.status_code in [200, 201]: print(f" āœ“ {desc}") return True else: print(f" āœ— {desc} - {resp.status_code}") return False def main(): project_id = get_project_id(PROJECT_NAME) if not project_id: print(f"Project '{PROJECT_NAME}' not found!") return print("="*70) print("REBUILDING CLEAN CCNA TOPOLOGY") print("="*70) print() delete_all_nodes(project_id) print("šŸ“ Creating topology with hierarchical layout...\n") # Clean hierarchical layout: # Top row: SW2-Core (center, top) # Middle row: SW1-Access (left) and SW3-Access (right) # Bottom rows: PCs under each switch nodes = {} # CORE SWITCH (top center) print("Creating Core Switch...") nodes['SW2'] = create_switch(project_id, "SW2-Core", 0, -150) if nodes['SW2']: print(" āœ“ SW2-Core (Distribution/Core)") # ACCESS SWITCHES (middle tier) print("\nCreating Access Switches...") nodes['SW1'] = create_switch(project_id, "SW1-Sales", -350, 0) if nodes['SW1']: print(" āœ“ SW1-Sales (Access, VLAN 10)") nodes['SW3'] = create_switch(project_id, "SW3-Eng", 350, 0) if nodes['SW3']: print(" āœ“ SW3-Eng (Access, VLAN 20)") # PCs (bottom tier, under their access switches) print("\nCreating Virtual PCs...") nodes['PC1'] = create_pc(project_id, "PC1-Sales", -450, 150) if nodes['PC1']: print(" āœ“ PC1-Sales (10.1.10.10)") nodes['PC2'] = create_pc(project_id, "PC2-Sales", -250, 150) if nodes['PC2']: print(" āœ“ PC2-Sales (10.1.10.11)") nodes['PC3'] = create_pc(project_id, "PC3-Eng", 250, 150) if nodes['PC3']: print(" āœ“ PC3-Eng (10.1.20.10)") nodes['PC4'] = create_pc(project_id, "PC4-Eng", 450, 150) if nodes['PC4']: print(" āœ“ PC4-Eng (10.1.20.11)") # Wait for nodes to be ready import time print("\nā±ļø Waiting 2 seconds for nodes to initialize...") time.sleep(2) # Refresh node data resp = requests.get(f"{GNS3_API}/projects/{project_id}/nodes") all_nodes = {n['name']: n for n in resp.json()} for name in nodes.keys(): if name in ['SW1', 'SW2', 'SW3']: node_name = nodes[name]['name'] else: node_name = nodes[name]['name'] if node_name in all_nodes: nodes[name] = all_nodes[node_name] print("\nšŸ”— Creating Links...") links = 0 # PC1 → SW1 if nodes.get('PC1') and nodes.get('SW1'): if create_link(project_id, nodes['PC1']['node_id'], 0, 0, nodes['SW1']['node_id'], 0, 0, "PC1-Sales → SW1-Sales e0"): links += 1 # PC2 → SW1 if nodes.get('PC2') and nodes.get('SW1'): if create_link(project_id, nodes['PC2']['node_id'], 0, 0, nodes['SW1']['node_id'], 1, 0, "PC2-Sales → SW1-Sales e1"): links += 1 # SW1 → SW2 (SINGLE trunk - access to core) if nodes.get('SW1') and nodes.get('SW2'): if create_link(project_id, nodes['SW1']['node_id'], 15, 0, nodes['SW2']['node_id'], 0, 0, "SW1-Sales e15 ↔ SW2-Core e0 (TRUNK)"): links += 1 # SW3 → SW2 (SINGLE trunk - access to core) if nodes.get('SW3') and nodes.get('SW2'): if create_link(project_id, nodes['SW3']['node_id'], 15, 0, nodes['SW2']['node_id'], 1, 0, "SW3-Eng e15 ↔ SW2-Core e1 (TRUNK)"): links += 1 # PC3 → SW3 if nodes.get('PC3') and nodes.get('SW3'): if create_link(project_id, nodes['PC3']['node_id'], 0, 0, nodes['SW3']['node_id'], 0, 0, "PC3-Eng → SW3-Eng e0"): links += 1 # PC4 → SW3 if nodes.get('PC4') and nodes.get('SW3'): if create_link(project_id, nodes['PC4']['node_id'], 0, 0, nodes['SW3']['node_id'], 1, 0, "PC4-Eng → SW3-Eng e1"): links += 1 print("\n" + "="*70) print("āœ… CLEAN CCNA TOPOLOGY COMPLETE!") print("="*70) print(f"\nšŸ“Š Devices: {len([n for n in nodes.values() if n])}") print(f" - 3x Cisco IOSvL2 switches (with proper icons! šŸŽÆ)") print(f" - 4x VPCS (Virtual PCs)") print(f"šŸ”— Links: {links} (NO redundant port-channels)") print("\nšŸ“ Topology Design:") print("```") print(" SW2-Core") print(" / \\") print(" SW1-Sales SW3-Eng") print(" / \\ / \\") print(" PC1 PC2 PC3 PC4") print(" (Sales) (Engineering)") print("```") print("\nšŸŽ“ VLAN Design:") print(" • SW1-Sales: VLAN 10 (10.1.10.0/24)") print(" • SW3-Eng: VLAN 20 (10.1.20.0/24)") print(" • Trunk ports: e15 on access, e0/e1 on core") print("\n✨ Open GNS3 GUI to see the clean topology with proper icons!") print("="*70) if __name__ == "__main__": main()