mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
Remove Scrapli
This commit is contained in:
@@ -76,17 +76,6 @@ SCRAPE_HELPERS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DRIVER_MAP = {
|
DRIVER_MAP = {
|
||||||
# TODO: Troubleshoot Arista with Scrapli, broken after upgrading to 2021.1.30.
|
|
||||||
# "arista_eos": "scrapli", # noqa: E800
|
|
||||||
"bird": "scrapli",
|
|
||||||
"cisco_ios": "scrapli",
|
|
||||||
"cisco_xe": "scrapli",
|
|
||||||
"cisco_xr": "scrapli",
|
|
||||||
"cisco_nxos": "scrapli",
|
|
||||||
# TODO: Troubleshoot Juniper with Scrapli, broken after upgrading to 2021.7.30.
|
|
||||||
# "juniper": "scrapli", # noqa: E800
|
|
||||||
"tnsr": "scrapli",
|
|
||||||
"frr": "scrapli",
|
|
||||||
"frr_legacy": "hyperglass_agent",
|
"frr_legacy": "hyperglass_agent",
|
||||||
"bird_legacy": "hyperglass_agent",
|
"bird_legacy": "hyperglass_agent",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,9 @@
|
|||||||
from .agent import AgentConnection
|
from .agent import AgentConnection
|
||||||
from ._common import Connection
|
from ._common import Connection
|
||||||
from .ssh_netmiko import NetmikoConnection
|
from .ssh_netmiko import NetmikoConnection
|
||||||
from .ssh_scrapli import ScrapliConnection
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"AgentConnection",
|
"AgentConnection",
|
||||||
"Connection",
|
"Connection",
|
||||||
"NetmikoConnection",
|
"NetmikoConnection",
|
||||||
"ScrapliConnection",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
"""Scrapli-Specific Classes & Utilities.
|
|
||||||
|
|
||||||
https://github.com/carlmontanari/scrapli
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Standard Library
|
|
||||||
import math
|
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
# Third Party
|
|
||||||
from scrapli.driver import AsyncGenericDriver
|
|
||||||
from scrapli.exceptions import (
|
|
||||||
ScrapliTimeout,
|
|
||||||
ScrapliException,
|
|
||||||
ScrapliAuthenticationFailed,
|
|
||||||
)
|
|
||||||
from scrapli.driver.core import (
|
|
||||||
AsyncEOSDriver,
|
|
||||||
AsyncNXOSDriver,
|
|
||||||
AsyncIOSXEDriver,
|
|
||||||
AsyncIOSXRDriver,
|
|
||||||
AsyncJunosDriver,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Project
|
|
||||||
from hyperglass.log import log
|
|
||||||
from hyperglass.state import use_state
|
|
||||||
from hyperglass.exceptions.public import (
|
|
||||||
AuthError,
|
|
||||||
ScrapeError,
|
|
||||||
DeviceTimeout,
|
|
||||||
ResponseEmpty,
|
|
||||||
)
|
|
||||||
from hyperglass.exceptions.private import UnsupportedDevice
|
|
||||||
|
|
||||||
# Local
|
|
||||||
from .ssh import SSHConnection
|
|
||||||
|
|
||||||
SCRAPLI_DRIVER_MAP = {
|
|
||||||
"arista_eos": AsyncEOSDriver,
|
|
||||||
"bird": AsyncGenericDriver,
|
|
||||||
"cisco_ios": AsyncIOSXEDriver,
|
|
||||||
"cisco_nxos": AsyncNXOSDriver,
|
|
||||||
"cisco_xr": AsyncIOSXRDriver,
|
|
||||||
"frr": AsyncGenericDriver,
|
|
||||||
"juniper": AsyncJunosDriver,
|
|
||||||
"tnsr": AsyncGenericDriver,
|
|
||||||
}
|
|
||||||
|
|
||||||
driver_global_args = {
|
|
||||||
# Per-NOS driver keyword arguments
|
|
||||||
"tnsr": {"comms_prompt_pattern": r"\S+\s\S+[\#\>]"},
|
|
||||||
"frr": {"comms_ansi": True},
|
|
||||||
"bird": {"comms_ansi": True},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _map_driver(_type: str) -> AsyncGenericDriver:
|
|
||||||
driver = SCRAPLI_DRIVER_MAP.get(_type)
|
|
||||||
if driver is None:
|
|
||||||
raise UnsupportedDevice(_type)
|
|
||||||
return driver
|
|
||||||
|
|
||||||
|
|
||||||
class ScrapliConnection(SSHConnection):
|
|
||||||
"""Handle a device connection via Scrapli."""
|
|
||||||
|
|
||||||
async def collect(self, host: str = None, port: int = None) -> Tuple[str, ...]:
|
|
||||||
"""Connect directly to a device.
|
|
||||||
|
|
||||||
Directly connects to the router via Netmiko library, returns the
|
|
||||||
command output.
|
|
||||||
"""
|
|
||||||
params = use_state("params")
|
|
||||||
driver = _map_driver(self.device.platform)
|
|
||||||
|
|
||||||
if host is not None:
|
|
||||||
log.debug(
|
|
||||||
"Connecting to {} via proxy {} [{}]",
|
|
||||||
self.device.name,
|
|
||||||
self.device.proxy.name,
|
|
||||||
f"{host}:{port}",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
log.debug("Connecting directly to {}", self.device.name)
|
|
||||||
|
|
||||||
global_args = driver_global_args.get(self.device.platform, {})
|
|
||||||
|
|
||||||
driver_kwargs = {
|
|
||||||
"host": host or self.device._target,
|
|
||||||
"port": port or self.device.port,
|
|
||||||
"auth_username": self.device.credential.username,
|
|
||||||
"timeout_ops": math.floor(params.request_timeout * 1.25),
|
|
||||||
"transport": "asyncssh",
|
|
||||||
"auth_strict_key": False,
|
|
||||||
"ssh_known_hosts_file": False,
|
|
||||||
**global_args,
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.device.credential._method == "password":
|
|
||||||
# Use password auth if no key is defined.
|
|
||||||
driver_kwargs["auth_password"] = self.device.credential.password.get_secret_value()
|
|
||||||
else:
|
|
||||||
# Otherwise, use key auth.
|
|
||||||
driver_kwargs["auth_private_key"] = self.device.credential.key.as_posix()
|
|
||||||
if self.device.credential._method == "encrypted_key":
|
|
||||||
# If the key is encrypted, use the password field as the
|
|
||||||
# private key password.
|
|
||||||
driver_kwargs[
|
|
||||||
"auth_private_key_passphrase"
|
|
||||||
] = self.device.credential.password.get_secret_value()
|
|
||||||
|
|
||||||
driver = driver(**driver_kwargs)
|
|
||||||
driver.logger = log.bind(logger_name=f"scrapli.{driver.host}:{driver.port}-driver")
|
|
||||||
try:
|
|
||||||
responses = ()
|
|
||||||
async with driver as connection:
|
|
||||||
await connection.get_prompt()
|
|
||||||
for query in self.query:
|
|
||||||
raw = await connection.send_command(query)
|
|
||||||
responses += (raw.result,)
|
|
||||||
log.debug(f'Raw response for command "{query}":\n{raw.result}')
|
|
||||||
|
|
||||||
except ScrapliTimeout as err:
|
|
||||||
raise DeviceTimeout(error=err, device=self.device)
|
|
||||||
|
|
||||||
except ScrapliAuthenticationFailed as err:
|
|
||||||
raise AuthError(error=err, device=self.device)
|
|
||||||
|
|
||||||
except ScrapliException as err:
|
|
||||||
raise ScrapeError(error=err, device=self.device)
|
|
||||||
|
|
||||||
if not responses:
|
|
||||||
raise ResponseEmpty(query=self.query_data)
|
|
||||||
|
|
||||||
return responses
|
|
||||||
@@ -22,16 +22,13 @@ if TYPE_CHECKING:
|
|||||||
from hyperglass.models.data import OutputDataModel
|
from hyperglass.models.data import OutputDataModel
|
||||||
|
|
||||||
# Local
|
# Local
|
||||||
from .drivers import AgentConnection, NetmikoConnection, ScrapliConnection
|
from .drivers import AgentConnection, NetmikoConnection
|
||||||
|
|
||||||
|
|
||||||
def map_driver(driver_name: str) -> "Connection":
|
def map_driver(driver_name: str) -> "Connection":
|
||||||
"""Get the correct driver class based on the driver name."""
|
"""Get the correct driver class based on the driver name."""
|
||||||
|
|
||||||
if driver_name == "scrapli":
|
if driver_name == "hyperglass_agent":
|
||||||
return ScrapliConnection
|
|
||||||
|
|
||||||
elif driver_name == "hyperglass_agent":
|
|
||||||
return AgentConnection
|
return AgentConnection
|
||||||
|
|
||||||
return NetmikoConnection
|
return NetmikoConnection
|
||||||
|
|||||||
@@ -118,7 +118,6 @@ def setup_lib_logging(log_level: str) -> None:
|
|||||||
"uvicorn.asgi",
|
"uvicorn.asgi",
|
||||||
"netmiko",
|
"netmiko",
|
||||||
"paramiko",
|
"paramiko",
|
||||||
"scrapli",
|
|
||||||
"httpx",
|
"httpx",
|
||||||
]:
|
]:
|
||||||
if name not in seen:
|
if name not in seen:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from pydantic import StrictInt, StrictFloat
|
|||||||
|
|
||||||
IntFloat = t.TypeVar("IntFloat", StrictInt, StrictFloat)
|
IntFloat = t.TypeVar("IntFloat", StrictInt, StrictFloat)
|
||||||
|
|
||||||
SupportedDriver = t.Literal["scrapli", "netmiko", "hyperglass_agent"]
|
SupportedDriver = t.Literal["netmiko", "hyperglass_agent"]
|
||||||
HttpAuthMode = t.Literal["basic", "api_key"]
|
HttpAuthMode = t.Literal["basic", "api_key"]
|
||||||
HttpProvider = t.Literal["msteams", "slack", "generic"]
|
HttpProvider = t.Literal["msteams", "slack", "generic"]
|
||||||
LogFormat = t.Literal["text", "json"]
|
LogFormat = t.Literal["text", "json"]
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ pydantic = {extras = ["dotenv"], version = "^1.8.2"}
|
|||||||
python = ">=3.8.1,<4.0"
|
python = ">=3.8.1,<4.0"
|
||||||
redis = "^3.5.3"
|
redis = "^3.5.3"
|
||||||
rich = "^10.11.0"
|
rich = "^10.11.0"
|
||||||
scrapli = {version = "2021.07.30", extras = ["asyncssh"]}
|
|
||||||
typer = "^0.4.0"
|
typer = "^0.4.0"
|
||||||
typing-extensions = "^3.7.4"
|
typing-extensions = "^3.7.4"
|
||||||
uvicorn = {extras = ["standard"], version = "^0.13.4"}
|
uvicorn = {extras = ["standard"], version = "^0.13.4"}
|
||||||
|
|||||||
Reference in New Issue
Block a user