diff --git a/gns3server/agent/gns3_copilot/tools_v2/vpcs_tools_netmiko.py b/gns3server/agent/gns3_copilot/tools_v2/vpcs_tools_netmiko.py index 221bf9bed..4eda2d3fd 100644 --- a/gns3server/agent/gns3_copilot/tools_v2/vpcs_tools_netmiko.py +++ b/gns3server/agent/gns3_copilot/tools_v2/vpcs_tools_netmiko.py @@ -461,6 +461,25 @@ class VPCSCommands(BaseTool): port = device_ports[device_name]["port"] + node_type = device_ports[device_name].get("node_type") + if node_type != "vpcs": + # VPCS syntax typed into another node's CLI is silently + # discarded (e.g. IOS answers "% Invalid input"), so reject + # mismatched devices before a console session is opened + logger.error( + "Device '%s' is a %s node, not a VPCS node", + device_name, + node_type or "unknown-type", + ) + hosts_data[device_name] = { + "error": ( + f"Device '{device_name}' is a {node_type or 'unknown-type'} node, " + "not a VPCS node; use device_config_send / device_show_run " + "for network devices" + ) + } + continue + # VPCS devices use gns3_vpcs_telnet device type hosts_data[device_name] = { "port": port, diff --git a/gns3server/agent/gns3_copilot/utils/get_gns3_device_port.py b/gns3server/agent/gns3_copilot/utils/get_gns3_device_port.py index 3ef331157..b3127574e 100644 --- a/gns3server/agent/gns3_copilot/utils/get_gns3_device_port.py +++ b/gns3server/agent/gns3_copilot/utils/get_gns3_device_port.py @@ -59,6 +59,7 @@ def get_device_ports_from_topology( "device_name": { "port": console_port, "platform": "huawei", # Extracted from tags + "node_type": "vpcs", # GNS3 node type from the topology "groups": ["network_devices"], # For inheriting shared settings "connection_options": { "netmiko": { @@ -160,9 +161,14 @@ def get_device_ports_from_topology( # This is the Nornir best practice - each host has its own # connection configuration (device_type), while sharing common # settings (hostname, timeout) via group inheritance. + # node_type (the GNS3 node type, e.g. vpcs/iou/docker) lets callers + # reject mismatched devices before opening a console connection; + # DictInventory ignores keys it does not know, so carrying it here + # is safe for entries fed straight into Nornir. host_entry = { "port": node_info["console_port"], "platform": platform, + "node_type": node_info.get("type"), "groups": ["network_devices"], # For inheriting hostname, timeout, etc. "connection_options": { "netmiko": { diff --git a/gns3server/agent/mcp/__init__.py b/gns3server/agent/mcp/__init__.py index 2d9e39a89..780c05e62 100644 --- a/gns3server/agent/mcp/__init__.py +++ b/gns3server/agent/mcp/__init__.py @@ -1517,6 +1517,9 @@ async def vpcs_config_set( ) -> list[dict[str, Any]]: """Configure VPCS devices (set IP addresses, gateway, etc.). + Only VPCS nodes are accepted: any other node type in device_configs fails + with a per-device error instead of typing VPCS syntax into its CLI. + VPCS-specific configuration commands: - ip
/