overgrowth / mcp-server /build_retail_network.py
Graham Paasch
Fix: Use environment variables for GNS3 server URL
c7576e1
raw
history blame
14.6 kB
#!/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()