Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Build a REAL WORLD network topology - Multi-Store Retail Chain | |
| Scenario: "GreenLeaf Coffee" - 3 coffee shop locations + HQ | |
| Network Design: | |
| - HQ (Headquarters): Has servers, office PCs, core network | |
| - Store-West: Customer WiFi, POS terminals, store office | |
| - Store-East: Customer WiFi, POS terminals, store office | |
| - WAN Router: Connects all locations (simulates Internet/MPLS) | |
| Visual Layout: | |
| ┌─────────────────────────────────────────────────────────────┐ | |
| │ HEADQUARTERS │ | |
| │ [Server] [Office-PC] │ | |
| │ \ / │ | |
| │ [SW-HQ-Core] │ | |
| │ | │ | |
| └─────────────────|─────────────────────────────────────────────┘ | |
| | | |
| [WAN-Router] ← Internet/MPLS Cloud | |
| | | |
| ┌─────────┴─────────┐ | |
| | | | |
| ┌───────|───────┐ ┌───────|────────┐ | |
| │ STORE-WEST │ │ STORE-EAST │ | |
| │ [SW-West] │ │ [SW-East] │ | |
| │ / \ │ │ / \ │ | |
| │ POS1 WiFi │ │ POS1 WiFi │ | |
| └───────────────┘ └────────────────┘ | |
| """ | |
| import requests | |
| import time | |
| import os | |
| # Support both local dev and deployed environments | |
| 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']}") | |
| time.sleep(1) | |
| def create_switch(project_id, name, x, y): | |
| """Create Cisco IOSvL2 switch""" | |
| 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", | |
| "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_cloud(project_id, name, x, y, label=""): | |
| """Create a cloud/rectangle to represent business area""" | |
| data = { | |
| "name": name, | |
| "node_type": "cloud", | |
| "compute_id": "local", | |
| "symbol": ":/symbols/cloud.svg", | |
| "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, symbol=":/symbols/vpcs_guest.svg"): | |
| """Create VPCS with specific icon""" | |
| data = { | |
| "name": name, | |
| "node_type": "vpcs", | |
| "compute_id": "local", | |
| "symbol": symbol, | |
| "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}") | |
| 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("🌿 GREENLEAF COFFEE - MULTI-STORE NETWORK") | |
| print("="*70) | |
| print("\n📍 Scenario: 3 coffee shop locations + headquarters") | |
| print(" Real-world business network with WAN connectivity\n") | |
| delete_all_nodes(project_id) | |
| nodes = {} | |
| # ═══════════════════════════════════════════════════════════ | |
| # HEADQUARTERS (Top Section) | |
| # ═══════════════════════════════════════════════════════════ | |
| print("🏢 Building HEADQUARTERS...") | |
| # HQ Area marker | |
| nodes['HQ-Area'] = create_cloud(project_id, "🏢-HQ-Building", 0, -450) | |
| if nodes['HQ-Area']: print(" ✓ HQ Building (Cloud represents physical location)") | |
| # Core switch at HQ | |
| nodes['HQ-Core'] = create_switch(project_id, "SW-HQ-Core", 0, -300) | |
| if nodes['HQ-Core']: print(" ✓ SW-HQ-Core (Main datacenter switch)") | |
| # HQ Devices | |
| nodes['HQ-Server'] = create_pc(project_id, "Server-DB", -150, -200, ":/symbols/server.svg") | |
| if nodes['HQ-Server']: print(" ✓ Server-DB (Customer database, inventory)") | |
| nodes['HQ-PC'] = create_pc(project_id, "Office-Manager", 150, -200, ":/symbols/computer.svg") | |
| if nodes['HQ-PC']: print(" ✓ Office-Manager (HQ staff computer)") | |
| # ═══════════════════════════════════════════════════════════ | |
| # WAN / INTERNET (Middle - connecting all locations) | |
| # ═══════════════════════════════════════════════════════════ | |
| print("\n🌐 Building WAN CONNECTION...") | |
| nodes['Internet'] = create_cloud(project_id, "☁️-Internet-MPLS", 0, -50) | |
| if nodes['Internet']: print(" ✓ Internet/MPLS Cloud (WAN connecting all stores)") | |
| # ═══════════════════════════════════════════════════════════ | |
| # STORE WEST (Left Bottom Section) | |
| # ═══════════════════════════════════════════════════════════ | |
| print("\n☕ Building STORE-WEST (Downtown Location)...") | |
| nodes['West-Area'] = create_cloud(project_id, "☕-Store-West", -400, 200) | |
| if nodes['West-Area']: print(" ✓ Store-West Building") | |
| nodes['SW-West'] = create_switch(project_id, "SW-West", -400, 100) | |
| if nodes['SW-West']: print(" ✓ SW-West (Store network switch)") | |
| nodes['West-POS'] = create_pc(project_id, "POS-West", -500, 200, ":/symbols/atm.svg") | |
| if nodes['West-POS']: print(" ✓ POS-West (Point of Sale terminal)") | |
| nodes['West-WiFi'] = create_pc(project_id, "WiFi-West", -300, 200, ":/symbols/wifi_antenna.svg") | |
| if nodes['West-WiFi']: print(" ✓ WiFi-West (Customer WiFi access point)") | |
| # ═══════════════════════════════════════════════════════════ | |
| # STORE EAST (Right Bottom Section) | |
| # ═══════════════════════════════════════════════════════════ | |
| print("\n☕ Building STORE-EAST (Suburb Location)...") | |
| nodes['East-Area'] = create_cloud(project_id, "☕-Store-East", 400, 200) | |
| if nodes['East-Area']: print(" ✓ Store-East Building") | |
| nodes['SW-East'] = create_switch(project_id, "SW-East", 400, 100) | |
| if nodes['SW-East']: print(" ✓ SW-East (Store network switch)") | |
| nodes['East-POS'] = create_pc(project_id, "POS-East", 300, 200, ":/symbols/atm.svg") | |
| if nodes['East-POS']: print(" ✓ POS-East (Point of Sale terminal)") | |
| nodes['East-WiFi'] = create_pc(project_id, "WiFi-East", 500, 200, ":/symbols/wifi_antenna.svg") | |
| if nodes['East-WiFi']: print(" ✓ WiFi-East (Customer WiFi access point)") | |
| # Wait for nodes to initialize | |
| print("\n⏱️ Waiting for devices to initialize...") | |
| time.sleep(3) | |
| # Refresh node data | |
| resp = requests.get(f"{GNS3_API}/projects/{project_id}/nodes") | |
| all_nodes = {n['name']: n for n in resp.json()} | |
| for key, node in nodes.items(): | |
| if node and node['name'] in all_nodes: | |
| nodes[key] = all_nodes[node['name']] | |
| # ═══════════════════════════════════════════════════════════ | |
| # CREATE NETWORK CONNECTIONS | |
| # ═══════════════════════════════════════════════════════════ | |
| print("\n🔗 Connecting the network...") | |
| links = 0 | |
| # HQ: Server → HQ-Core | |
| if nodes.get('HQ-Server') and nodes.get('HQ-Core'): | |
| if create_link(project_id, nodes['HQ-Server']['node_id'], 0, 0, | |
| nodes['HQ-Core']['node_id'], 0, 0, | |
| "Server-DB → SW-HQ-Core (Database connection)"): | |
| links += 1 | |
| # HQ: Office PC → HQ-Core | |
| if nodes.get('HQ-PC') and nodes.get('HQ-Core'): | |
| if create_link(project_id, nodes['HQ-PC']['node_id'], 0, 0, | |
| nodes['HQ-Core']['node_id'], 1, 0, | |
| "Office-Manager → SW-HQ-Core (Management PC)"): | |
| links += 1 | |
| # HQ-Core → Internet (WAN uplink) | |
| if nodes.get('HQ-Core') and nodes.get('Internet'): | |
| if create_link(project_id, nodes['HQ-Core']['node_id'], 15, 0, | |
| nodes['Internet']['node_id'], 0, 0, | |
| "SW-HQ-Core → Internet (HQ WAN uplink)"): | |
| links += 1 | |
| # Store-West: Internet → SW-West (WAN) | |
| if nodes.get('Internet') and nodes.get('SW-West'): | |
| if create_link(project_id, nodes['Internet']['node_id'], 1, 0, | |
| nodes['SW-West']['node_id'], 15, 0, | |
| "Internet → SW-West (Store-West WAN)"): | |
| links += 1 | |
| # Store-West: POS → SW-West | |
| if nodes.get('West-POS') and nodes.get('SW-West'): | |
| if create_link(project_id, nodes['West-POS']['node_id'], 0, 0, | |
| nodes['SW-West']['node_id'], 0, 0, | |
| "POS-West → SW-West (Sales terminal)"): | |
| links += 1 | |
| # Store-West: WiFi → SW-West | |
| if nodes.get('West-WiFi') and nodes.get('SW-West'): | |
| if create_link(project_id, nodes['West-WiFi']['node_id'], 0, 0, | |
| nodes['SW-West']['node_id'], 1, 0, | |
| "WiFi-West → SW-West (Customer WiFi)"): | |
| links += 1 | |
| # Store-East: Internet → SW-East (WAN) | |
| if nodes.get('Internet') and nodes.get('SW-East'): | |
| if create_link(project_id, nodes['Internet']['node_id'], 2, 0, | |
| nodes['SW-East']['node_id'], 15, 0, | |
| "Internet → SW-East (Store-East WAN)"): | |
| links += 1 | |
| # Store-East: POS → SW-East | |
| if nodes.get('East-POS') and nodes.get('SW-East'): | |
| if create_link(project_id, nodes['East-POS']['node_id'], 0, 0, | |
| nodes['SW-East']['node_id'], 0, 0, | |
| "POS-East → SW-East (Sales terminal)"): | |
| links += 1 | |
| # Store-East: WiFi → SW-East | |
| if nodes.get('East-WiFi') and nodes.get('SW-East'): | |
| if create_link(project_id, nodes['East-WiFi']['node_id'], 0, 0, | |
| nodes['SW-East']['node_id'], 1, 0, | |
| "WiFi-East → SW-East (Customer WiFi)"): | |
| links += 1 | |
| print("\n" + "="*70) | |
| print("✅ GREENLEAF COFFEE NETWORK COMPLETE!") | |
| print("="*70) | |
| print(f"\n📊 Network Summary:") | |
| print(f" • 3 Switches (HQ-Core, SW-West, SW-East)") | |
| print(f" • 1 Database Server (HQ)") | |
| print(f" • 1 Office PC (HQ Manager)") | |
| print(f" • 2 POS Terminals (one per store)") | |
| print(f" • 2 WiFi Access Points (customer WiFi)") | |
| print(f" • 3 Cloud icons (HQ building, Store buildings, Internet)") | |
| print(f" • {links} Network Links") | |
| print("\n🌍 Real-World Scenario:") | |
| print(" 📍 Headquarters: Database server + office management") | |
| print(" 📍 Store-West (Downtown): POS + Customer WiFi") | |
| print(" 📍 Store-East (Suburb): POS + Customer WiFi") | |
| print(" 📍 All locations connected via Internet/MPLS WAN") | |
| print("\n💡 Network Functions:") | |
| print(" • POS terminals process credit card transactions") | |
| print(" • WiFi APs provide customer internet access") | |
| print(" • HQ server stores sales data from all locations") | |
| print(" • Manager PC monitors all stores remotely") | |
| print(" • WAN links allow real-time inventory sync") | |
| print("\n🎓 CCNA Concepts Demonstrated:") | |
| print(" ✓ WAN connectivity (simulated Internet/MPLS)") | |
| print(" ✓ Branch office networking") | |
| print(" ✓ Server/client architecture") | |
| print(" ✓ Wireless access points") | |
| print(" ✓ POS/retail device integration") | |
| print(" ✓ Multi-site management") | |
| print("\n✨ Open GNS3 to see your real-world retail network!") | |
| print("="*70) | |
| if __name__ == "__main__": | |
| main() | |