forked from mirrors/thatmattlove-hyperglass
reworked app-wide logging
This commit is contained in:
parent
e88169fb37
commit
2325f4feb0
17 changed files with 74 additions and 122 deletions
BIN
.flask_cache/0cc005a225d064a6216a21c390e8fd8f
Normal file
BIN
.flask_cache/0cc005a225d064a6216a21c390e8fd8f
Normal file
Binary file not shown.
BIN
.flask_cache/1fc39e56a58c627ed59c0d0523e808e2
Normal file
BIN
.flask_cache/1fc39e56a58c627ed59c0d0523e808e2
Normal file
Binary file not shown.
Binary file not shown.
BIN
.flask_cache/379a23d6e49ea74418d51711a36df194
Normal file
BIN
.flask_cache/379a23d6e49ea74418d51711a36df194
Normal file
Binary file not shown.
BIN
.flask_cache/5e8887a448534e50af390288650930ea
Normal file
BIN
.flask_cache/5e8887a448534e50af390288650930ea
Normal file
Binary file not shown.
BIN
.flask_cache/632595e1de107e8f891d3cf18b102ff1
Normal file
BIN
.flask_cache/632595e1de107e8f891d3cf18b102ff1
Normal file
Binary file not shown.
Binary file not shown.
BIN
.flask_cache/c10d865004bdf7e67dcf50a6039073dd
Normal file
BIN
.flask_cache/c10d865004bdf7e67dcf50a6039073dd
Normal file
Binary file not shown.
BIN
.flask_cache/c9a8ada7d4e04353536dc74ceb1b08e2
Normal file
BIN
.flask_cache/c9a8ada7d4e04353536dc74ceb1b08e2
Normal file
Binary file not shown.
BIN
.flask_cache/d277c4e120e0e4b7fa8f80455a32af2e
Normal file
BIN
.flask_cache/d277c4e120e0e4b7fa8f80455a32af2e
Normal file
Binary file not shown.
BIN
.flask_cache/e6dad9c79446e7c35963c49fd05507d6
Normal file
BIN
.flask_cache/e6dad9c79446e7c35963c49fd05507d6
Normal file
Binary file not shown.
BIN
.flask_cache/e9ad28e2141cab0361d67aef3520c6f7
Normal file
BIN
.flask_cache/e9ad28e2141cab0361d67aef3520c6f7
Normal file
Binary file not shown.
|
|
@ -3,12 +3,11 @@ import sys
|
|||
import toml
|
||||
import logging
|
||||
from netaddr import *
|
||||
from loguru import logger
|
||||
from logzero import logger
|
||||
|
||||
# Local imports
|
||||
from hyperglass import configuration
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
# Load TOML config file
|
||||
devices = configuration.devices()
|
||||
|
||||
|
|
@ -18,13 +17,10 @@ commands = configuration.commands()
|
|||
# Filter config to router list
|
||||
routers_list = devices["router"]
|
||||
|
||||
logger.add(sys.stderr)
|
||||
|
||||
# Receives JSON from Flask, constucts the command that will be passed to the router
|
||||
# Also handles input validation & error handling
|
||||
def construct(router, cmd, ipprefix):
|
||||
input_params = (router, cmd, ipprefix)
|
||||
logger.info(*input_params)
|
||||
logger.info(f"Constructing {cmd} command for {router} to {ipprefix}...")
|
||||
try:
|
||||
# Loop through routers config file, match input router with configured routers, set variables
|
||||
for r in routers_list:
|
||||
|
|
@ -47,8 +43,10 @@ def construct(router, cmd, ipprefix):
|
|||
if cmd == "Query Type":
|
||||
msg = "You must select a query type."
|
||||
code = 415
|
||||
logger.error(msg, code, *input_params)
|
||||
return (msg, code)
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
# BGP Community Query
|
||||
elif cmd in ["bgp_community"]:
|
||||
# Extended Communities, new-format
|
||||
|
|
@ -56,26 +54,18 @@ def construct(router, cmd, ipprefix):
|
|||
for a, c in dual_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = "{i} matched new-format community.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} matched new-format community."
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (msg, code, router, type, command)
|
||||
# Extended Communities, 32 bit format
|
||||
elif re.match("^[0-9]{1,10}$", ipprefix):
|
||||
for a, c in dual_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = "{i} matched 32 bit community.".format(
|
||||
i=ipprefix
|
||||
msg = (
|
||||
f"{ipprefix} matched 32 bit community."
|
||||
)
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (msg, code, router, type, command)
|
||||
# RFC 8092 Large Community Support
|
||||
elif re.match(
|
||||
|
|
@ -85,42 +75,32 @@ def construct(router, cmd, ipprefix):
|
|||
for a, c in dual_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = "{i} matched large community.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} matched large community."
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (msg, code, router, type, command)
|
||||
else:
|
||||
msg = "{i} is an invalid BGP Community Format.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
code = 415
|
||||
logger.error(msg, code, *input_params)
|
||||
return (msg, code)
|
||||
else:
|
||||
msg = f"{ipprefix} is an invalid BGP Community Format."
|
||||
code = 415
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
# BGP AS_PATH Query
|
||||
elif cmd in ["bgp_aspath"]:
|
||||
if re.match(".*", ipprefix):
|
||||
for a, c in dual_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = "{i} matched AS_PATH regex.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} matched AS_PATH regex."
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (msg, code, router, type, command)
|
||||
else:
|
||||
msg = "{i} is an invalid AS_PATH regex.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} is an invalid AS_PATH regex."
|
||||
code = 415
|
||||
logger.error(msg, code, *input_params)
|
||||
return (msg, code)
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
# BGP Route Query
|
||||
elif cmd in ["bgp_route"]:
|
||||
try:
|
||||
|
|
@ -129,13 +109,8 @@ def construct(router, cmd, ipprefix):
|
|||
for a, c in ipv4_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = "{i} is a valid IPv4 Adddress.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
|
|
@ -148,13 +123,8 @@ def construct(router, cmd, ipprefix):
|
|||
for a, c in ipv6_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = "{i} is a valid IPv6 Adddress.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
|
|
@ -164,12 +134,12 @@ def construct(router, cmd, ipprefix):
|
|||
)
|
||||
# Exception from netaddr library will return a user-facing error
|
||||
except:
|
||||
msg = "{i} is an invalid IP Address.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
code = 415
|
||||
logger.error(msg, code, *input_params)
|
||||
return (msg, code)
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
# Ping/Traceroute
|
||||
elif cmd in ["ping", "traceroute"]:
|
||||
try:
|
||||
|
|
@ -180,13 +150,8 @@ def construct(router, cmd, ipprefix):
|
|||
target=ipprefix,
|
||||
src_addr_ipv4=src_addr_ipv4,
|
||||
)
|
||||
msg = "{i} is a valid IPv4 Adddress.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
|
|
@ -201,13 +166,8 @@ def construct(router, cmd, ipprefix):
|
|||
target=ipprefix,
|
||||
src_addr_ipv6=src_addr_ipv6,
|
||||
)
|
||||
msg = "{i} is a valid IPv6 Adddress.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
code = 200
|
||||
logger.warning(
|
||||
msg, code, router, type, command
|
||||
)
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
|
|
@ -216,22 +176,23 @@ def construct(router, cmd, ipprefix):
|
|||
command,
|
||||
)
|
||||
except:
|
||||
msg = "{i} is an invalid IP Address.".format(
|
||||
i=ipprefix
|
||||
)
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
code = 415
|
||||
logger.error(msg, code, *input_params)
|
||||
return (msg, code)
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
else:
|
||||
msg = "Command {i} not found.".format(i=cmd)
|
||||
msg = f"Command {cmd} not found."
|
||||
code = 415
|
||||
logger.error(msg, code, *input_params)
|
||||
return (msg, code)
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
except:
|
||||
router_ip = r["address"]
|
||||
error_msg = logger.error(
|
||||
"Input router IP {router} does not match the configured router IP of {ip}".format(
|
||||
router=router, ip=r["address"]
|
||||
)
|
||||
f"Input router IP {router} does not match the configured router IP of {router_ip}"
|
||||
)
|
||||
raise ValueError(error_msg)
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import sys
|
||||
import time
|
||||
from netaddr import *
|
||||
from loguru import logger
|
||||
from logzero import logger
|
||||
from netmiko import redispatch
|
||||
from netmiko import ConnectHandler
|
||||
from hyperglass import configuration
|
||||
|
|
@ -22,35 +22,36 @@ blacklist = IPSet(blacklist_config["blacklist"])
|
|||
|
||||
general_error = "Error connecting to device."
|
||||
|
||||
logger.add(sys.stderr)
|
||||
|
||||
|
||||
def execute(lg_data):
|
||||
logger.info(lg_data)
|
||||
logger.info(f"Received lookup request for: {lg_data}")
|
||||
# Check POST data from JS, if location matches a configured router's
|
||||
# location, use the router's configured IP address to connect
|
||||
router = lg_data["router"]
|
||||
cmd = lg_data["cmd"]
|
||||
ipprefix = lg_data["ipprefix"]
|
||||
|
||||
for r in routers_list:
|
||||
if r["location"] == lg_data["router"]:
|
||||
if r["location"] == router:
|
||||
lg_router_address = r["address"]
|
||||
|
||||
# Check blacklist.toml array for prefixes/IPs and return an error upon a match
|
||||
if lg_data["cmd"] in ["bgp_route", "ping", "traceroute"]:
|
||||
if cmd in ["bgp_route", "ping", "traceroute"]:
|
||||
try:
|
||||
if IPNetwork(lg_data["ipprefix"]).ip in blacklist:
|
||||
msg = "{i} is not allowed.".format(i=lg_data["ipprefix"])
|
||||
if IPNetwork(ipprefix).ip in blacklist:
|
||||
msg = f"{ipprefix} is not allowed."
|
||||
code = 405
|
||||
logger.error(msg, code, lg_data)
|
||||
logger.error(f"{msg}, {code}, {lg_data}")
|
||||
return (msg, code, lg_data)
|
||||
# If netaddr library throws an exception, return a user-facing error.
|
||||
except:
|
||||
msg = "{i} is not a valid IP Address.".format(i=lg_data["ipprefix"])
|
||||
msg = f"{ipprefix} is not a valid IP Address."
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
logger.error(f"{msg}, {code}, {lg_data}")
|
||||
return (msg, code, lg_data)
|
||||
# Send "clean" request to constructor to build the command that will be sent to the router
|
||||
print(lg_router_address)
|
||||
msg, status, router, type, command = construct.construct(
|
||||
lg_router_address, lg_data["cmd"], lg_data["ipprefix"]
|
||||
lg_router_address, cmd, ipprefix
|
||||
)
|
||||
# Loop through proxy config, match configured proxy name for each router with a configured proxy
|
||||
# Return configured proxy parameters for netmiko
|
||||
|
|
@ -71,7 +72,7 @@ def execute(lg_data):
|
|||
else:
|
||||
msg = "Router does not have a proxy configured."
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
logger.error(f"{msg}, {code}, {lg_data}")
|
||||
return (msg, code, lg_data)
|
||||
|
||||
# Matches router with configured credential
|
||||
|
|
@ -88,9 +89,9 @@ def execute(lg_data):
|
|||
matched_password = credentials_list[configured_credential]["password"]
|
||||
return matched_username, matched_password
|
||||
else:
|
||||
msg = "Credential {i} does not exist".format(i=configured_credential)
|
||||
msg = f"Credential {configured_credential} does not exist"
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
logger.error(f"{msg}, {code}, {lg_data}")
|
||||
return (general_error, code, lg_data)
|
||||
|
||||
# Connect to the router via netmiko library, return the command output
|
||||
|
|
@ -100,9 +101,9 @@ def execute(lg_data):
|
|||
nm_output_direct = nm_connect_direct.send_command(command)
|
||||
return nm_output_direct
|
||||
except:
|
||||
msg = "Unable to reach target {l}".format(l=lg_data["router"])
|
||||
msg = f"Unable to reach target {router}"
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
logger.error(f"{msg}, {code}, {lg_data}")
|
||||
return (general_error, code, lg_data)
|
||||
|
||||
# Connect to the proxy server via netmiko library, then log into the router
|
||||
|
|
@ -137,11 +138,9 @@ def execute(lg_data):
|
|||
if host_output:
|
||||
return host_output
|
||||
except:
|
||||
msg = "Proxy server {p} unable to reach target {d}".format(
|
||||
p=nm_proxy["host"], d=nm_host["host"]
|
||||
)
|
||||
msg = f'Proxy server {nm_proxy["host"]} unable to reach target {nm_host["host"]}'
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
logger.error(f"{msg}, {code}, {lg_data}")
|
||||
return (general_error, code, lg_data)
|
||||
|
||||
nm_host = {
|
||||
|
|
@ -160,14 +159,15 @@ def execute(lg_data):
|
|||
else:
|
||||
connection_proxied = True
|
||||
if status == 200:
|
||||
logger.info(f"Executing {command} on {router}...")
|
||||
try:
|
||||
if connection_proxied is True:
|
||||
output_proxied = getOutputProxy(configured_proxy)
|
||||
parsed_output = parse.parse(output_proxied, type, lg_data["cmd"])
|
||||
parsed_output = parse.parse(output_proxied, type, cmd)
|
||||
return parsed_output, status, router, type, command
|
||||
elif connection_proxied is False:
|
||||
output_direct = getOutputDirect()
|
||||
parsed_output = parse.parse(output_direct, type, lg_data["cmd"])
|
||||
parsed_output = parse.parse(output_direct, type, cmd)
|
||||
return parsed_output, status, router, type, command
|
||||
except:
|
||||
raise
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ def devices():
|
|||
def requires_ipv6_cidr():
|
||||
f = os.path.join(dir, "requires_ipv6_cidr.toml")
|
||||
t = toml.load(f)
|
||||
return t
|
||||
return t["requires_ipv6_cidr"]
|
||||
|
||||
|
||||
# Filter config to branding variables
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import sys
|
||||
import json
|
||||
import toml
|
||||
from loguru import logger
|
||||
from logzero import logger
|
||||
from flask import Flask, request, Response, jsonify, flash
|
||||
from flask_caching import Cache
|
||||
from flask_limiter import Limiter
|
||||
|
|
@ -13,8 +13,6 @@ from hyperglass import render
|
|||
from hyperglass import configuration
|
||||
from hyperglass.command import execute
|
||||
|
||||
logger.add(sys.stderr)
|
||||
|
||||
# Load TOML config file
|
||||
devices = configuration.devices()
|
||||
# Filter config file to list of routers & subsequent configurations
|
||||
|
|
@ -130,17 +128,14 @@ def lg():
|
|||
# Check if cached entry exists
|
||||
if cache.get(cache_key) is None:
|
||||
cache_value = execute.execute(lg_data)
|
||||
logger.info(cache_value[1:])
|
||||
value_output = cache_value[0]
|
||||
value_code = cache_value[1]
|
||||
value_params = cache_value[2:]
|
||||
logger.info("No cache match for: {cache_key}".format(cache_key=cache_key))
|
||||
logger.info(f"No cache match for: {cache_key}")
|
||||
# If it doesn't, create a cache entry
|
||||
try:
|
||||
cache.set(cache_key, value_output)
|
||||
logger.info(
|
||||
"Added cache entry: {value_params}".format(value_params=value_params)
|
||||
)
|
||||
logger.info(f"Added cache entry: {value_params}")
|
||||
except:
|
||||
raise RuntimeError("Unable to add output to cache.", 415, *value_params)
|
||||
# If 200, return output
|
||||
|
|
@ -151,11 +146,7 @@ def lg():
|
|||
return Response(cache.get(cache_key), value_code)
|
||||
# If it does, return the cached entry
|
||||
else:
|
||||
logger.info(
|
||||
"Cache match for: {cache_key}, returning cached entry...".format(
|
||||
cache_key=cache_key
|
||||
)
|
||||
)
|
||||
logger.info(f"Cache match for: {cache_key}, returning cached entry...")
|
||||
try:
|
||||
return cache.get(cache_key)
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ netmiko
|
|||
netaddr
|
||||
markdown2
|
||||
libsass
|
||||
loguru
|
||||
logzero
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue