overgrowth / mcp-server /create_topology.py
Graham Paasch
Fix: Use environment variables for GNS3 server URL
c7576e1
#!/usr/bin/env python3
"""
Create a simple CCNA-level topology in the overgrowth GNS3 project
Topology: 2 routers connected to 1 switch
"""
import requests
import json
import time
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")
def get_project_id(name):
"""Get project ID by 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 get_appliances():
"""Get available appliances"""
resp = requests.get(f"{GNS3_API}/appliances")
return resp.json()
def create_node(project_id, name, node_type, x, y, template_id=None):
"""Create a node in the project"""
data = {
"name": name,
"node_type": node_type,
"compute_id": "local",
"x": x,
"y": y
}
if template_id:
data["template_id"] = template_id
resp = requests.post(
f"{GNS3_API}/projects/{project_id}/nodes",
json=data
)
if resp.status_code != 201:
print(f" Error creating node: {resp.status_code}")
print(f" Response: {resp.text}")
return None
return resp.json()
def get_templates():
"""Get available templates"""
resp = requests.get(f"{GNS3_API}/templates")
return resp.json()
def create_link(project_id, node1_id, port1, node2_id, port2):
"""Create a link between two nodes"""
data = {
"nodes": [
{
"node_id": node1_id,
"adapter_number": port1,
"port_number": 0
},
{
"node_id": node2_id,
"adapter_number": port2,
"port_number": 0
}
]
}
resp = requests.post(
f"{GNS3_API}/projects/{project_id}/links",
json=data
)
return resp.json()
def main():
# Get project
project_id = get_project_id(PROJECT_NAME)
if not project_id:
print(f"Project '{PROJECT_NAME}' not found!")
return
print(f"Working with project: {PROJECT_NAME} ({project_id})")
# Get available templates
print("\nFetching templates...")
templates = get_templates()
# Find Cisco IOS router and switch templates
router_template = None
switch_template = None
for t in templates:
name = t.get('name', '').lower()
if 'router' in name or 'ios' in name or 'c7200' in name or 'c3725' in name:
router_template = t
print(f" Found router template: {t['name']}")
if 'switch' in name or 'l2-ios' in name or 'iosvl2' in name:
switch_template = t
print(f" Found switch template: {t['name']}")
if not router_template:
# Try to use Ethernet switch as fallback
print("\n No router template found - will use Ethernet devices")
print(" Available templates:")
for t in templates[:20]:
print(f" - {t['name']} ({t.get('category', 'unknown')})")
# Create simple ethernet topology instead
print("\nCreating simple ethernet topology...")
# Create 3 ethernet switches
sw1 = create_node(project_id, "Switch-1", "ethernet_switch", -100, 0)
print(f" Created {sw1['name']}")
time.sleep(0.5)
sw2 = create_node(project_id, "Switch-2", "ethernet_switch", 100, -100)
print(f" Created {sw2['name']}")
time.sleep(0.5)
sw3 = create_node(project_id, "Switch-3", "ethernet_switch", 100, 100)
print(f" Created {sw3['name']}")
time.sleep(0.5)
# Create links
print("\nCreating links...")
link1 = create_link(project_id, sw1['node_id'], 0, sw2['node_id'], 0)
print(f" Linked {sw1['name']} <-> {sw2['name']}")
link2 = create_link(project_id, sw1['node_id'], 1, sw3['node_id'], 0)
print(f" Linked {sw1['name']} <-> {sw3['name']}")
print("\n✓ Simple topology created!")
print(" Note: This is a basic ethernet topology.")
print(" To use routers/switches, you'll need to add Cisco IOS templates to GNS3.")
else:
print("\nCreating CCNA topology...")
# Use IOSv which is qemu-based, not dynamips
# Create 2 routers
r1 = create_node(project_id, "Router-1", "qemu", -150, -100, router_template['template_id'])
if r1:
print(f" Created {r1['name']}")
time.sleep(0.5)
else:
print(" Failed to create Router-1")
return
r2 = create_node(project_id, "Router-2", "qemu", 150, -100, router_template['template_id'])
if r2:
print(f" Created {r2['name']}")
time.sleep(0.5)
else:
print(" Failed to create Router-2")
return
# Create 1 switch using ethernet_switch (simple and always works)
sw1 = create_node(project_id, "Switch-1", "ethernet_switch", 0, 100)
if sw1:
print(f" Created {sw1['name']}")
time.sleep(0.5)
else:
print(" Failed to create Switch-1")
return
# Create links
print("\nCreating links...")
link1 = create_link(project_id, r1['node_id'], 0, sw1['node_id'], 0)
print(f" Linked {r1['name']} <-> {sw1['name']}")
link2 = create_link(project_id, r2['node_id'], 0, sw1['node_id'], 1)
print(f" Linked {r2['name']} <-> {sw1['name']}")
print("\n✓ CCNA topology created!")
if __name__ == "__main__":
main()