From a06778a6f11a89b12eaad9fd7133006f0c285953 Mon Sep 17 00:00:00 2001 From: "yalene.yang" Date: Mon, 22 Jan 2024 18:23:06 +0800 Subject: [PATCH] SSH Support for FS devices --- netmiko/fs/__init__.py | 3 ++ netmiko/fs/fs_os.py | 39 ++++++++++++++++++++++++++ netmiko/ssh_dispatcher.py | 58 ++++++--------------------------------- 3 files changed, 51 insertions(+), 49 deletions(-) create mode 100644 netmiko/fs/__init__.py create mode 100644 netmiko/fs/fs_os.py diff --git a/netmiko/fs/__init__.py b/netmiko/fs/__init__.py new file mode 100644 index 000000000..782799813 --- /dev/null +++ b/netmiko/fs/__init__.py @@ -0,0 +1,3 @@ +from netmiko.fs.fs_os import FSOSSSH, FSOSTelnet + +__all__ = ["FSOSSSH", "FSOSTelnet"] diff --git a/netmiko/fs/fs_os.py b/netmiko/fs/fs_os.py new file mode 100644 index 000000000..1281d3684 --- /dev/null +++ b/netmiko/fs/fs_os.py @@ -0,0 +1,39 @@ +"""FS Support""" +import time +from typing import Any + +from netmiko.cisco_base_connection import CiscoBaseConnection + + +class FSOSBase(CiscoBaseConnection): + def session_preparation(self) -> None: + """Prepare the session after the connection has been established.""" + self._test_channel_read(pattern=r"[>#]") + self.set_base_prompt() + """FS OS requires enable mode to set terminal width""" + self.enable() + self.set_terminal_width(command="terminal width 256", pattern="terminal") + self.disable_paging(command="terminal length 0") + # Clear the read buffer + time.sleep(0.3 * self.global_delay_factor) + self.clear_buffer() + + def save_config( + self, cmd: str = "write", confirm: bool = False, confirm_response: str = "" + ) -> str: + """Save config: write""" + return super().save_config( + cmd=cmd, confirm=confirm, confirm_response=confirm_response + ) + + +class FSOSSSH(FSOSBase): + + pass + + +class FSOSTelnet(FSOSBase): + def __init__(self, *args: Any, **kwargs: Any) -> None: + default_enter = kwargs.get("default_enter") + kwargs["default_enter"] = "\r\n" if default_enter is None else default_enter + super().__init__(*args, **kwargs) diff --git a/netmiko/ssh_dispatcher.py b/netmiko/ssh_dispatcher.py index 0005a9918..71ee7df59 100755 --- a/netmiko/ssh_dispatcher.py +++ b/netmiko/ssh_dispatcher.py @@ -1,18 +1,15 @@ """Controls selection of proper class based on the device type.""" from typing import Any, Type, Optional from typing import TYPE_CHECKING -import re from netmiko.exceptions import ConnectionException from netmiko.exceptions import NetmikoTimeoutException, NetmikoAuthenticationException from netmiko.a10 import A10SSH from netmiko.accedian import AccedianSSH from netmiko.adtran import AdtranOSSSH, AdtranOSTelnet -from netmiko.adva import AdvaAosFsp150F3SSH, AdvaAosFsp150F2SSH from netmiko.alcatel import AlcatelAosSSH from netmiko.allied_telesis import AlliedTelesisAwplusSSH from netmiko.arista import AristaSSH, AristaTelnet from netmiko.arista import AristaFileTransfer -from netmiko.arris import ArrisCERSSH from netmiko.apresia import ApresiaAeosSSH, ApresiaAeosTelnet from netmiko.aruba import ArubaSSH from netmiko.audiocode import ( @@ -26,7 +23,6 @@ from netmiko.brocade import BrocadeFOSSSH from netmiko.broadcom import BroadcomIcosSSH from netmiko.calix import CalixB6SSH, CalixB6Telnet -from netmiko.casa import CasaCMTSSSH from netmiko.cdot import CdotCrosSSH from netmiko.centec import CentecOSSSH, CentecOSTelnet from netmiko.checkpoint import CheckPointGaiaSSH @@ -40,7 +36,6 @@ CiscoIosSerial, ) from netmiko.cisco import CiscoNxosSSH, CiscoNxosFileTransfer -from netmiko.cisco import CiscoS200SSH, CiscoS200Telnet from netmiko.cisco import CiscoS300SSH, CiscoS300Telnet from netmiko.cisco import CiscoTpTcCeSSH from netmiko.cisco import CiscoViptelaSSH @@ -61,11 +56,7 @@ from netmiko.eltex import EltexSSH, EltexEsrSSH from netmiko.endace import EndaceSSH from netmiko.enterasys import EnterasysSSH -from netmiko.ericsson import ( - EricssonIposSSH, - EricssonMinilink63SSH, - EricssonMinilink66SSH, -) +from netmiko.ericsson import EricssonIposSSH from netmiko.extreme import ExtremeErsSSH from netmiko.extreme import ExtremeExosSSH, ExtremeExosFileTransfer from netmiko.extreme import ExtremeExosTelnet @@ -78,7 +69,6 @@ from netmiko.extreme import ExtremeWingSSH from netmiko.f5 import F5TmshSSH from netmiko.f5 import F5LinuxSSH -from netmiko.fiberstore import FiberstoreFsosSSH from netmiko.flexvnf import FlexvnfSSH from netmiko.fortinet import FortinetSSH from netmiko.hp import HPProcurveSSH, HPProcurveTelnet, HPComwareSSH, HPComwareTelnet @@ -115,13 +105,15 @@ from netmiko.ruckus import RuckusFastironSSH from netmiko.ruckus import RuckusFastironTelnet from netmiko.ruijie import RuijieOSSSH, RuijieOSTelnet + +from netmiko.fs import FSOSSSH, FSOSTelnet + from netmiko.sixwind import SixwindOSSSH from netmiko.sophos import SophosSfosSSH -from netmiko.teldat import TeldatCITSSH, TeldatCITTelnet from netmiko.terminal_server import TerminalServerSSH from netmiko.terminal_server import TerminalServerTelnet from netmiko.tplink import TPLinkJetStreamSSH, TPLinkJetStreamTelnet -from netmiko.ubiquiti import UbiquitiEdgeRouterSSH, UbiquitiEdgeRouterFileTransfer +from netmiko.ubiquiti import UbiquitiEdgeRouterSSH from netmiko.ubiquiti import UbiquitiEdgeSSH from netmiko.ubiquiti import UbiquitiUnifiSwitchSSH from netmiko.vyos import VyOSSSH @@ -133,7 +125,6 @@ from netmiko.supermicro import SmciSwitchSmisSSH from netmiko.supermicro import SmciSwitchSmisTelnet from netmiko.zyxel import ZyxelSSH -from netmiko.hillstone import HillstoneStoneosSSH if TYPE_CHECKING: from netmiko.base_connection import BaseConnection @@ -147,14 +138,11 @@ "a10": A10SSH, "accedian": AccedianSSH, "adtran_os": AdtranOSSSH, - "adva_fsp150f2": AdvaAosFsp150F2SSH, - "adva_fsp150f3": AdvaAosFsp150F3SSH, "alcatel_aos": AlcatelAosSSH, "alcatel_sros": NokiaSrosSSH, "allied_telesis_awplus": AlliedTelesisAwplusSSH, "apresia_aeos": ApresiaAeosSSH, "arista_eos": AristaSSH, - "arris_cer": ArrisCERSSH, "aruba_os": ArubaSSH, "aruba_osswitch": HPProcurveSSH, "aruba_procurve": HPProcurveSSH, @@ -172,7 +160,6 @@ "brocade_vyos": VyOSSSH, "checkpoint_gaia": CheckPointGaiaSSH, "calix_b6": CalixB6SSH, - "casa_cmts": CasaCMTSSSH, "cdot_cros": CdotCrosSSH, "centec_os": CentecOSSSH, "ciena_saos": CienaSaosSSH, @@ -180,7 +167,6 @@ "cisco_ftd": CiscoFtdSSH, "cisco_ios": CiscoIosSSH, "cisco_nxos": CiscoNxosSSH, - "cisco_s200": CiscoS200SSH, "cisco_s300": CiscoS300SSH, "cisco_tp": CiscoTpTcCeSSH, "cisco_viptela": CiscoViptelaSSH, @@ -203,8 +189,6 @@ "eltex_esr": EltexEsrSSH, "enterasys": EnterasysSSH, "ericsson_ipos": EricssonIposSSH, - "ericsson_mltn63": EricssonMinilink63SSH, - "ericsson_mltn66": EricssonMinilink66SSH, "extreme": ExtremeExosSSH, "extreme_ers": ExtremeErsSSH, "extreme_exos": ExtremeExosSSH, @@ -218,18 +202,15 @@ "f5_ltm": F5TmshSSH, "f5_tmsh": F5TmshSSH, "f5_linux": F5LinuxSSH, - "fiberstore_fsos": FiberstoreFsosSSH, "flexvnf": FlexvnfSSH, "fortinet": FortinetSSH, "generic": GenericSSH, "generic_termserver": TerminalServerSSH, - "hillstone_stoneos": HillstoneStoneosSSH, "hp_comware": HPComwareSSH, "hp_procurve": HPProcurveSSH, "huawei": HuaweiSSH, "huawei_smartax": HuaweiSmartAXSSH, "huawei_olt": HuaweiSmartAXSSH, - "huawei_vrp": HuaweiSSH, "huawei_vrpv8": HuaweiVrpv8SSH, "ipinfusion_ocnos": IpInfusionOcNOSSSH, "juniper": JuniperSSH, @@ -258,12 +239,13 @@ "raisecom_roap": RaisecomRoapSSH, "ruckus_fastiron": RuckusFastironSSH, "ruijie_os": RuijieOSSSH, + + "fs_os":FSOSSSH, + "sixwind_os": SixwindOSSSH, "sophos_sfos": SophosSfosSSH, "supermicro_smis": SmciSwitchSmisSSH, - "teldat_cit": TeldatCITSSH, "tplink_jetstream": TPLinkJetStreamSSH, - # ubiquiti_airos - Placeholder agreed to with NTC (if this driver is created in future) "ubiquiti_edge": UbiquitiEdgeSSH, "ubiquiti_edgerouter": UbiquitiEdgeRouterSSH, "ubiquiti_edgeswitch": UbiquitiEdgeSSH, @@ -290,7 +272,6 @@ "linux": LinuxFileTransfer, "nokia_sros": NokiaSrosFileTransfer, "mikrotik_routeros": MikrotikRouterOsFileTransfer, - "ubiquiti_edgerouter": UbiquitiEdgeRouterFileTransfer, } # Also support keys that end in _ssh @@ -323,7 +304,6 @@ CLASS_MAPPER["ciena_saos_telnet"] = CienaSaosTelnet CLASS_MAPPER["cisco_ios_telnet"] = CiscoIosTelnet CLASS_MAPPER["cisco_xr_telnet"] = CiscoXrTelnet -CLASS_MAPPER["cisco_s200_telnet"] = CiscoS200Telnet CLASS_MAPPER["cisco_s300_telnet"] = CiscoS300Telnet CLASS_MAPPER["dell_dnos6_telnet"] = DellDNOS6Telnet CLASS_MAPPER["dell_powerconnect_telnet"] = DellPowerConnectTelnet @@ -347,7 +327,6 @@ CLASS_MAPPER["ruckus_fastiron_telnet"] = RuckusFastironTelnet CLASS_MAPPER["ruijie_os_telnet"] = RuijieOSTelnet CLASS_MAPPER["supermicro_smis_telnet"] = SmciSwitchSmisTelnet -CLASS_MAPPER["teldat_cit_telnet"] = TeldatCITTelnet CLASS_MAPPER["tplink_jetstream_telnet"] = TPLinkJetStreamTelnet CLASS_MAPPER["yamaha_telnet"] = YamahaTelnet CLASS_MAPPER["zte_zxros_telnet"] = ZteZxrosTelnet @@ -392,24 +371,6 @@ def ConnectHandler(*args: Any, **kwargs: Any) -> "BaseConnection": return ConnectionClass(*args, **kwargs) -def TelnetFallback(*args: Any, **kwargs: Any) -> "BaseConnection": - """If an SSH connection fails, try to fallback to Telnet.""" - try: - return ConnectHandler(*args, **kwargs) - except (NetmikoTimeoutException, ConnectionRefusedError): - device_type = kwargs["device_type"] - # platforms_str is the base form (i.e. does not have the '_ssh' suffix) - if device_type in platforms_str: - alternative_device = f"{device_type}_telnet" - elif "_ssh" in device_type: - alternative_device = re.sub("_ssh", "_telnet", device_type) - - if alternative_device in platforms: - kwargs["device_type"] = alternative_device - return ConnectHandler(*args, **kwargs) - raise - - def ConnLogOnly( log_file: str = "netmiko.log", log_level: Optional[int] = None, @@ -456,8 +417,6 @@ def ConnLogOnly( elif "TCP connection to device failed" in str(e): msg = f"Netmiko was unable to reach the provided host and port: {hostname}:{port}" msg += f"\n\n{str(e)}" - else: - msg = f"An unknown NetmikoTimeoutException occurred:\n\n{str(e)}" logger.error(msg) return None except Exception as e: @@ -469,6 +428,7 @@ def ConnLogOnly( def ConnUnify( **kwargs: Any, ) -> "BaseConnection": + try: kwargs["auto_connect"] = False net_connect = ConnectHandler(**kwargs)