diff --git a/hyperglass/command/execute.py b/hyperglass/command/execute.py index f7c4cde..30c4c79 100644 --- a/hyperglass/command/execute.py +++ b/hyperglass/command/execute.py @@ -4,6 +4,7 @@ returns errors if input is invalid. Passes validated parameters to construct.py, which is used to build & run the Netmiko connectoins or hyperglass-frr API calls, returns the output back to the front end. """ + # Third Party Imports import http3 import sshtunnel @@ -82,7 +83,7 @@ class Connect: "device_type": self.device_config.nos, "username": self.cred.username, "password": self.cred.password.get_secret_value(), - "fast_cli": True, + "global_delay_factor": 0.2, } logger.debug(f"Local binding: localhost:{tunnel.local_bind_port}") try: @@ -94,6 +95,7 @@ class Connect: nm_connect_direct = ConnectHandler(**scrape_host) response = nm_connect_direct.send_command(self.query) except ( + OSError, NetMikoAuthenticationException, NetMikoTimeoutException, NetmikoAuthError, @@ -103,11 +105,12 @@ class Connect: raise CantConnect(scrape_error) else: scrape_host = { - "host": self.device_config.address, + "host": self.device_config.address.compressed, + "port": self.device_config.port, "device_type": self.device_config.nos, "username": self.cred.username, "password": self.cred.password.get_secret_value(), - "fast_cli": True, + "global_delay_factor": 0.2, } try: logger.debug( @@ -115,6 +118,7 @@ class Connect: dev=self.device_config.location ) ) + logger.debug(f"Device Parameters: {scrape_host}") nm_connect_direct = ConnectHandler(**scrape_host) response = nm_connect_direct.send_command(self.query) except ( diff --git a/hyperglass/configuration/models.py b/hyperglass/configuration/models.py index 7b2052d..43e9db1 100644 --- a/hyperglass/configuration/models.py +++ b/hyperglass/configuration/models.py @@ -315,9 +315,9 @@ class Branding(BaseSettings): class Logo(BaseSettings): """Class model for params.branding.logo""" - path: str = "static/images/hyperglass-dark.png" + path: str = "ui/images/hyperglass-dark.png" width: int = 384 - favicons: str = "static/images/favicons/" + favicons: str = "ui/images/favicons/" class PeeringDb(BaseSettings): """Class model for params.branding.peering_db""" diff --git a/hyperglass/hyperglass.py b/hyperglass/hyperglass.py index 4c47fb3..dda7465 100644 --- a/hyperglass/hyperglass.py +++ b/hyperglass/hyperglass.py @@ -1,7 +1,6 @@ """Hyperglass Front End""" # Standard Library Imports -import os import time from ast import literal_eval from pathlib import Path @@ -42,11 +41,16 @@ redis_config = { "decode_responses": True, } +# Static File Definitions +static_dir = Path(__file__).parent / "static" / "ui" + # Main Sanic app definition -static_dir = Path(__file__).parent / "static" logger.debug(f"Static Files: {static_dir}") + app = Sanic(__name__) -app.static("/static", str(static_dir)) +app.static("/ui", str(static_dir)) + +logger.debug(app.config) # Redis Cache Config r_cache = aredis.StrictRedis(db=params.features.cache.redis_id, **redis_config) @@ -124,6 +128,15 @@ async def handle_404(request, exception): return response.html(html, status=404) +@app.exception(ServerError) +async def handle_408(request, exception): + """Renders full error page for invalid URI""" + client_addr = get_remote_address(request) + count_notfound.labels(exception, path, client_addr).inc() + logger.error(f"Error: {exception}, Source: {client_addr}") + return response.html(exception, status=408) + + @app.exception(RateLimitExceeded) async def handle_429(request, exception): """Renders full error page for too many site queries""" @@ -148,6 +161,7 @@ async def clear_cache(): """Function to clear the Redis cache""" try: await r_cache.flushdb() + return "Successfully cleared cache" except Exception as error_exception: logger.error(f"Error clearing cache: {error_exception}") raise HyperglassError(f"Error clearing cache: {error_exception}") @@ -163,7 +177,7 @@ async def site(request): @app.route("/test", methods=["GET"]) async def test_route(request): """Test route for various tests""" - html = render.html("500") + html = render.html("results") return response.html(html, status=500) @@ -232,6 +246,8 @@ async def hyperglass_main(request): starttime = time.time() cache_value = await Execute(lg_data).response() endtime = time.time() + if not cache_value: + raise handle_408("Request timed out.") elapsedtime = round(endtime - starttime, 4) logger.debug( f"Execution for query {cache_key} took {elapsedtime} seconds to run." @@ -261,3 +277,7 @@ async def hyperglass_main(request): lg_data["target"], ).inc() return response.html(response_output, status=response_status) + + +if __name__ == "__main__": + cli() diff --git a/hyperglass/render/templates/404.html.j2 b/hyperglass/render/templates/404.html.j2 index 6890c4f..7b21267 100644 --- a/hyperglass/render/templates/404.html.j2 +++ b/hyperglass/render/templates/404.html.j2 @@ -1,11 +1,5 @@ {% extends "templates/base.html.j2" %} -
- {% block head %} - {% include "templates/inlinestyle.html.j2" %} - {% endblock %} - - {% block content %}