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