reworked app-wide logging

This commit is contained in:
checktheroads 2019-05-12 11:04:23 -07:00
parent e88169fb37
commit 2325f4feb0
17 changed files with 74 additions and 122 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -7,4 +7,4 @@ netmiko
netaddr
markdown2
libsass
loguru
logzero