mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
Add scrapli driver for supported devices
This commit is contained in:
@@ -68,8 +68,12 @@ SCRAPE_HELPERS = {
|
||||
}
|
||||
|
||||
DRIVER_MAP = {
|
||||
"cisco_ios": "netmiko",
|
||||
"juniper": "netmiko",
|
||||
"arista_eos": "scrapli",
|
||||
"cisco_ios": "scrapli",
|
||||
"cisco_xe": "scrapli",
|
||||
"cisco_xr": "scrapli",
|
||||
"cisco_nxos": "scrapli",
|
||||
"juniper": "scrapli",
|
||||
"frr": "hyperglass_agent",
|
||||
"bird": "hyperglass_agent",
|
||||
}
|
||||
|
137
hyperglass/execution/drivers/ssh_scrapli.py
Normal file
137
hyperglass/execution/drivers/ssh_scrapli.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""Scrapli-Specific Classes & Utilities.
|
||||
|
||||
https://github.com/carlmontanari/scrapli
|
||||
"""
|
||||
|
||||
# Standard Library
|
||||
import math
|
||||
from typing import Iterable
|
||||
|
||||
# Third Party
|
||||
from scrapli.driver import AsyncGenericDriver
|
||||
from scrapli.exceptions import (
|
||||
ScrapliTimeout,
|
||||
ScrapliException,
|
||||
KeyVerificationFailed,
|
||||
ScrapliAuthenticationFailed,
|
||||
)
|
||||
from scrapli.driver.core import (
|
||||
AsyncEOSDriver,
|
||||
AsyncNXOSDriver,
|
||||
AsyncIOSXEDriver,
|
||||
AsyncIOSXRDriver,
|
||||
AsyncJunosDriver,
|
||||
)
|
||||
|
||||
# Project
|
||||
from hyperglass.log import log
|
||||
from hyperglass.exceptions import (
|
||||
AuthError,
|
||||
ScrapeError,
|
||||
DeviceTimeout,
|
||||
UnsupportedDevice,
|
||||
)
|
||||
from hyperglass.configuration import params
|
||||
from hyperglass.execution.drivers.ssh import SSHConnection
|
||||
|
||||
SCRAPLI_DRIVER_MAP = {
|
||||
"cisco_ios": AsyncIOSXEDriver,
|
||||
"cisco_nxos": AsyncNXOSDriver,
|
||||
"cisco_xr": AsyncIOSXRDriver,
|
||||
"juniper": AsyncJunosDriver,
|
||||
"arista_eos": AsyncEOSDriver,
|
||||
}
|
||||
|
||||
|
||||
def _map_driver(nos: str) -> AsyncGenericDriver:
|
||||
driver = SCRAPLI_DRIVER_MAP.get(nos)
|
||||
if driver is None:
|
||||
raise UnsupportedDevice("{nos} is not supported by scrapli.", nos=nos)
|
||||
return driver
|
||||
|
||||
|
||||
class ScrapliConnection(SSHConnection):
|
||||
"""Handle a device connection via Scrapli."""
|
||||
|
||||
async def collect(self, host: str = None, port: int = None) -> Iterable:
|
||||
"""Connect directly to a device.
|
||||
|
||||
Directly connects to the router via Netmiko library, returns the
|
||||
command output.
|
||||
"""
|
||||
driver = _map_driver(self.device.nos)
|
||||
|
||||
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)
|
||||
|
||||
driver_kwargs = {
|
||||
"host": host or self.device.address,
|
||||
"port": port or self.device.port,
|
||||
"auth_username": self.device.credential.username,
|
||||
"auth_password": self.device.credential.password.get_secret_value(),
|
||||
"timeout_transport": math.floor(params.request_timeout * 1.25),
|
||||
"transport": "asyncssh",
|
||||
"auth_strict_key": False,
|
||||
"ssh_known_hosts_file": False,
|
||||
"ssh_config_file": False,
|
||||
}
|
||||
|
||||
driver = driver(**driver_kwargs)
|
||||
driver.logger = log.bind(logger_name=f"scrapli.driver-{driver._host}")
|
||||
|
||||
try:
|
||||
responses = ()
|
||||
|
||||
async with driver as connection:
|
||||
|
||||
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:
|
||||
log.error(err)
|
||||
raise DeviceTimeout(
|
||||
params.messages.connection_error,
|
||||
device_name=self.device.display_name,
|
||||
proxy=None,
|
||||
error=params.messages.request_timeout,
|
||||
)
|
||||
except (ScrapliAuthenticationFailed, KeyVerificationFailed) as err:
|
||||
log.error(
|
||||
"Error authenticating to device {loc}: {e}",
|
||||
loc=self.device.name,
|
||||
e=str(err),
|
||||
)
|
||||
|
||||
raise AuthError(
|
||||
params.messages.connection_error,
|
||||
device_name=self.device.display_name,
|
||||
proxy=None,
|
||||
error=params.messages.authentication_error,
|
||||
)
|
||||
except ScrapliException as err:
|
||||
log.error(err)
|
||||
raise ScrapeError(
|
||||
params.messages.connection_error,
|
||||
device_name=self.device.display_name,
|
||||
proxy=None,
|
||||
error=params.messages.no_response,
|
||||
)
|
||||
|
||||
if not responses:
|
||||
raise ScrapeError(
|
||||
params.messages.connection_error,
|
||||
device_name=self.device.display_name,
|
||||
proxy=None,
|
||||
error=params.messages.no_response,
|
||||
)
|
||||
|
||||
return responses
|
Reference in New Issue
Block a user