1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00

86 lines
2.5 KiB
Python
Raw Normal View History

"""Execute validated & constructed query on device.
Accepts input from front end application, validates the input and
returns errors if input is invalid. Passes validated parameters to
construct.py, which is used to build & run the Netmiko connections or
hyperglass-frr API calls, returns the output back to the front end.
"""
# Standard Library
import signal
from typing import Any, Dict, Union, Callable
# Project
from hyperglass.log import log
from hyperglass.util import validate_nos
from hyperglass.exceptions import DeviceTimeout, ResponseEmpty
2020-07-30 01:30:01 -07:00
from hyperglass.configuration import params
from hyperglass.api.models.query import Query
2020-07-23 17:47:54 -07:00
from hyperglass.execution.drivers import (
AgentConnection,
NetmikoConnection,
ScrapliConnection,
)
DRIVER_MAP = {
"scrapli": ScrapliConnection,
"netmiko": NetmikoConnection,
"hyperglass_agent": AgentConnection,
}
def handle_timeout(**exc_args: Any) -> Callable:
"""Return a function signal can use to raise a timeout exception."""
def handler(*args: Any, **kwargs: Any) -> None:
raise DeviceTimeout(**exc_args)
return handler
async def execute(query: Query) -> Union[str, Dict]:
"""Initiate query validation and execution."""
output = params.messages.general
log.debug(f"Received query for {query}")
2020-07-30 01:30:01 -07:00
log.debug(f"Matched device config: {query.device}")
2020-07-30 01:30:01 -07:00
supported, driver_name = validate_nos(query.device.nos)
2020-07-23 17:47:54 -07:00
mapped_driver = DRIVER_MAP.get(driver_name, NetmikoConnection)
2020-07-30 01:30:01 -07:00
driver = mapped_driver(query.device, query)
timeout_args = {
"unformatted_msg": params.messages.connection_error,
2020-07-30 01:30:01 -07:00
"device_name": query.device.display_name,
"error": params.messages.request_timeout,
}
2020-07-30 01:30:01 -07:00
if query.device.proxy:
timeout_args["proxy"] = query.device.proxy.name
signal.signal(signal.SIGALRM, handle_timeout(**timeout_args))
signal.alarm(params.request_timeout - 1)
2020-07-30 01:30:01 -07:00
if query.device.proxy:
proxy = driver.setup_proxy()
with proxy() as tunnel:
2020-07-23 17:47:54 -07:00
response = await driver.collect(
tunnel.local_bind_host, tunnel.local_bind_port
)
else:
2020-07-23 17:47:54 -07:00
response = await driver.collect()
output = await driver.parsed_response(response)
if output == "" or output == "\n":
2020-07-30 01:30:01 -07:00
raise ResponseEmpty(
params.messages.no_output, device_name=query.device.display_name
)
log.debug(f"Output for query: {query.json()}:\n{repr(output)}")
signal.alarm(0)
return output