""" Generate network topology diagrams from GNS3 topology data """ from typing import Dict, List, Optional import json def generate_ascii_diagram(topology: Dict) -> str: """ Generate a simple ASCII diagram from topology data Args: topology: Topology dict with nodes and links Returns: ASCII art string representing the network """ nodes = topology.get('nodes', []) links = topology.get('links', []) if not nodes: return "No nodes in topology" # Simple representation lines = [] lines.append(f"{'='*60}") lines.append(f"Network Topology: {topology.get('project', 'Unknown')}") lines.append(f"Status: {topology.get('status', 'unknown')}") lines.append(f"{'='*60}") lines.append("") # Group nodes by type by_type = {} for node in nodes: node_type = node.get('node_type', 'unknown') if node_type not in by_type: by_type[node_type] = [] by_type[node_type].append(node) # Display nodes by type for node_type, type_nodes in by_type.items(): lines.append(f"\n{node_type.upper()} Devices ({len(type_nodes)}):") lines.append("-" * 60) for node in type_nodes: status = node.get('status', 'unknown') console = node.get('console', 'N/A') status_icon = "🟢" if status == "started" else "🔴" if status == "stopped" else "⚪" lines.append(f" {status_icon} {node['name']:<30} Console: {console}") # Display link count lines.append(f"\n\nTotal Links: {len(links)}") return "\n".join(lines) def generate_mermaid_diagram(topology: Dict) -> str: """ Generate a Mermaid diagram from topology data Args: topology: Topology dict with nodes and links Returns: Mermaid diagram code """ nodes = topology.get('nodes', []) links = topology.get('links', []) if not nodes: return "graph TD\n A[No Topology Data]" lines = [] lines.append("graph TD") # Create node definitions with icons based on type node_map = {} for i, node in enumerate(nodes): node_id = f"N{i}" node_map[node['name']] = node_id node_type = node.get('node_type', 'unknown') # Choose icon based on type if node_type == 'qemu' or 'SW' in node['name']: icon = "🔀" # Switch elif node_type == 'vpcs' or 'PC' in node['name'] or 'POS' in node['name']: icon = "💻" # PC elif node_type == 'cloud': icon = "☁️" # Cloud else: icon = "📦" status = node.get('status', 'unknown') if status == "started": lines.append(f' {node_id}["{icon} {node["name"]}
🟢 Running"]') elif status == "stopped": lines.append(f' {node_id}["{icon} {node["name"]}
🔴 Stopped"]') else: lines.append(f' {node_id}["{icon} {node["name"]}"]') # Add links (simplified - just show connections exist) # Note: GNS3 link format is complex, this is a simplified version if links: lines.append("\n %% Network Links") # For now, just note that links exist lines.append(f" %% {len(links)} links configured") return "\n".join(lines) def generate_topology_summary(topology: Dict) -> str: """ Generate a text summary of the topology Args: topology: Topology dict with nodes and links Returns: Markdown-formatted summary """ nodes = topology.get('nodes', []) links = topology.get('links', []) project = topology.get('project', 'Unknown') status = topology.get('status', 'unknown') # Count nodes by type and status by_type = {} by_status = {'started': 0, 'stopped': 0, 'unknown': 0} for node in nodes: node_type = node.get('node_type', 'unknown') by_type[node_type] = by_type.get(node_type, 0) + 1 node_status = node.get('status', 'unknown') by_status[node_status] = by_status.get(node_status, 0) + 1 summary = [] summary.append(f"## Network Topology: {project}") summary.append(f"**Project Status:** {status}") summary.append("") summary.append(f"### Devices ({len(nodes)} total)") for node_type, count in sorted(by_type.items()): summary.append(f"- **{node_type}**: {count} device(s)") summary.append("") summary.append(f"### Device Status") summary.append(f"- 🟢 Running: {by_status.get('started', 0)}") summary.append(f"- 🔴 Stopped: {by_status.get('stopped', 0)}") summary.append(f"- ⚪ Unknown: {by_status.get('unknown', 0)}") summary.append("") summary.append(f"### Connectivity") summary.append(f"- **Links**: {len(links)} connection(s)") # List console ports for access summary.append("") summary.append("### Device Access") console_devices = [n for n in nodes if n.get('console')] if console_devices: summary.append("Devices with console access:") for node in console_devices[:10]: # Limit to first 10 console = node.get('console') console_type = node.get('console_type', 'telnet') summary.append(f"- **{node['name']}**: {console_type}://localhost:{console}") return "\n".join(summary)