YueGuobin db164e9d41 feat(copilot): add multi-vendor device support with custom Huawei driver
Add comprehensive multi-vendor support for GNS3 network automation,
   including a custom Netmiko driver for Huawei CloudEngine devices.

   Features:
   - Custom HuaweiTelnetCE driver for GNS3 emulation (no authentication)
   - Auto-commit before exit to prevent [Y/N/C] prompts
   - Dynamic device type detection from GNS3 node tags
   - Support for both Cisco IOS and Huawei devices
   - Proper VRP command handling (system-view, return confirmation)

   Implementation:
   - New package: utils/custom_netmiko/
     - huawei_ce.py: Huawei CloudEngine driver
     - tests/test_huawei_ce.py: Unit tests (9/9 passing)
     - README.md: Driver development guide
   - Updated tools for multi-vendor support:
     - display_tools_nornir.py: Dynamic group generation
     - config_tools_nornir.py: Multi-vendor config commands
     - get_gns3_device_port.py: Device port extraction
   - Documentation: multi-vendor-device-support.md

   Limitations:
   - huawei_telnet_ce driver requires devices without authentication
   - For devices with username/password, use standard huawei_telnet driver

   Co-Authored-By: Yue Guobin <yueguobin@outlook.com>"
2026-03-12 16:44:32 +08:00

4.4 KiB

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
├── README.md                # This file
└── tests/                   # Unit tests
    ├── __init__.py
    └── test_huawei_ce.py    # Huawei CE driver tests

Supported Drivers

Huawei (huawei_ce.py)

Driver Name: HuaweiTelnetCE

Device Types:

  • huawei_telnet_ce - Primary type
  • huawei_ce - Alias

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": "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