YueGuobin e2e2e23cf7 feat(copilot): add VPCS Telnet driver with Netmiko and ANSI code stripping
Implement custom VPCS driver and unified tool architecture:

   - Add VPCSTelnet custom driver (vpcs_telnet.py)
     - No authentication (direct console access like VPCS behavior)
     - Simple prompt pattern matching (PC\d+>)
     - Automatic ANSI escape code stripping for clean output
     - Config mode methods return empty (VPCS has no config modes)

   - Replace vpcs_tools_telnetlib3.py with vpcs_tools_netmiko.py
     - Migrate from telnetlib3 to Netmiko + Nornir architecture
     - Unified tool architecture matching config/display tools
     - Improved code consistency and maintainability

   - Add comprehensive test coverage (test_vpcs_telnet.py)
     - 30 unit tests covering all VPCS driver functionality
     - Tests for ANSI code stripping, telnet_login, send_command
     - Tests for device registration and initialization

   - Update VPCS built-in template (services/templates.py)
     - Add platform:vpcs and device_type:gns3_vpcs_telnet tags
     - Automatic driver selection without manual configuration

   - Update documentation (docs/)
     - multi-vendor-device-support.md: VPCS driver documentation
     - netmiko_devices.md: Add VPCS to supported devices list
     - README.md: Update multi-vendor support description
2026-03-14 14:25:37 +08:00
..

Custom Netmiko Drivers

Custom Netmiko drivers for GNS3-emulated network devices.

Overview

This package contains Netmiko drivers optimized for GNS3 emulation environments where devices may have non-standard authentication or behavior patterns.

Directory Structure

custom_netmiko/
├── __init__.py              # Package initialization, auto-registers all drivers
├── huawei_ce.py             # Huawei CloudEngine custom driver (GNS3HuaweiTelnetCE)
├── ruijie_telnet.py         # Ruijie OS custom driver (RuijieTelnetEnhanced)
├── README.md                # This file
├── scripts/                 # Utility scripts
│   └── list_netmiko_telnet_devices.py
└── tests/                   # Unit tests
    ├── __init__.py
    └── test_huawei_ce.py    # Huawei CE driver tests

Supported Drivers

Huawei (huawei_ce.py)

Driver Name: GNS3HuaweiTelnetCE

Device Types:

  • gns3_huawei_telnet_ce - Primary type (GNS3 custom driver)
  • huawei_telnet - Standard Netmiko type (for devices with authentication)

Features:

  • Skip authentication (for GNS3 devices without username/password)
  • VRP prompt recognition (<HUAWEI>, [HUAWEI])
  • Auto-commit before exit (prevents [Y/N/C] prompts)
  • Proper output collection using read_channel_timing()

Limitations:

  • Does not support username/password authentication
  • If your device requires authentication, use standard huawei_telnet driver

Usage

Direct Usage

from netmiko import ConnectHandler
from gns3server.agent.gns3_copilot.utils import custom_netmiko

device = {
    "device_type": "gns3_huawei_telnet_ce",
    "host": "127.0.0.1",
    "port": 5000,
}

with ConnectHandler(**device) as conn:
    output = conn.send_command("display version")
    config = ["interface GE1/0/1", "description Test"]
    output = conn.send_config_set(config)

In GNS3 Copilot Tools

The drivers are auto-registered when the tools are imported:

from gns3server.agent.gns3_copilot.tools_v2 import DisplayToolNornir

tool = DisplayToolNornir()
result = tool._run(json.dumps({
    "device_names": ["huawei-sw1"],
    "commands": ["display version"],
    "project_id": "project-uuid"
}))

Running Tests

# Run all tests
source venv/bin/activate
python -m unittest discover -s gns3server/agent/gns3_copilot/utils/custom_netmiko/tests

# Run Huawei CE tests only
python gns3server/agent/gns3_copilot/utils/custom_netmiko/tests/test_huawei_ce.py

Adding New Drivers

1. Create Driver File

Create a new file in custom_netmiko/ (e.g., cisco.py):

# cisco.py
from netmiko.cisco.cisco_ios import CiscoIosTelnet

class CustomCiscoDriver(CiscoIosTelnet):
    """Custom Cisco driver for GNS3."""

    def telnet_login(self, ...):
        # Override login logic
        pass

def register_custom_device_type() -> None:
    """Register this driver with Netmiko."""
    import importlib
    sd = importlib.import_module("netmiko.ssh_dispatcher")

    sd.CLASS_MAPPER["cisco_custom"] = CustomCiscoDriver
    sd.CLASS_MAPPER_BASE["cisco_custom"] = CustomCiscoDriver

    # Rebuild static lists
    sd.platforms = list(sd.CLASS_MAPPER.keys())
    sd.platforms.sort()

# Auto-register on import
try:
    register_custom_device_type()
except Exception as e:
    import logging
    logging.getLogger(__name__).warning(f"Failed to register: {e}")

2. Update __init__.py

Add import to __init__.py:

try:
    from . import cisco  # noqa: F401
except Exception as e:
    logger.warning(f"Failed to import Cisco driver: {e}", exc_info=True)

__all__ = ["huawei_ce", "cisco"]

3. Create Tests

Create tests/test_cisco.py:

import unittest
from gns3server.agent.gns3_copilot.utils.custom_netmiko import cisco

class TestCustomCiscoDriver(unittest.TestCase):
    def test_device_type_registered(self):
        from netmiko.ssh_dispatcher import CLASS_MAPPER
        self.assertIn("cisco_custom", CLASS_MAPPER)

if __name__ == "__main__":
    unittest.main()

Troubleshooting

Driver Not Found Error

ValueError: Unsupported 'device_type'

Solution: Ensure the custom_netmiko package is imported before using the device:

from gns3server.agent.gns3_copilot.utils import custom_netmiko
# Now use the device

Import Errors

If you get import errors, check:

  1. Virtual environment is activated
  2. Python path includes project root
  3. Dependencies are installed (pip install netmiko nornir nornir-netmiko)

Last updated: 2026-03-12