File size: 7,650 Bytes
765065a
 
 
 
 
 
 
 
 
 
 
c7576e1
765065a
c7576e1
 
 
765065a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/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()