mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
overhaul of construct.py
This commit is contained in:
@ -20,317 +20,210 @@ commands = configuration.commands()
|
||||
routers_list = devices["router"]
|
||||
|
||||
|
||||
def frr(router, cmd, ipprefix):
|
||||
logger.info(f"Constructing {cmd} command for FRR router {router} to {ipprefix}...")
|
||||
try:
|
||||
# Loop through routers config file, match input router with configured routers, set variables
|
||||
for r in routers_list:
|
||||
if router == r["address"]:
|
||||
type = r["type"]
|
||||
src_addr_ipv4 = r["src_addr_ipv4"]
|
||||
src_addr_ipv6 = r["src_addr_ipv6"]
|
||||
try:
|
||||
# Loop through commands config file, set variables for matched commands
|
||||
if cmd == "Query Type":
|
||||
msg = "You must select a query type."
|
||||
code = 415
|
||||
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
|
||||
if re.match("^([0-9]{0,5})\:([0-9]{1,5})$", ipprefix):
|
||||
query = json.dumps(
|
||||
{"cmd": cmd, "afi": "dual", "target": ipprefix}
|
||||
)
|
||||
msg = f"{ipprefix} matched new-format community."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
# Extended Communities, 32 bit format
|
||||
elif re.match("^[0-9]{1,10}$", ipprefix):
|
||||
query = json.dumps(
|
||||
{"cmd": cmd, "afi": "dual", "target": ipprefix}
|
||||
)
|
||||
msg = f"{ipprefix} matched 32 bit community."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
# RFC 8092 Large Community Support
|
||||
elif re.match(
|
||||
"^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$", ipprefix
|
||||
):
|
||||
query = json.dumps(
|
||||
{"cmd": cmd, "afi": "dual", "target": ipprefix}
|
||||
)
|
||||
msg = f"{ipprefix} matched large community."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
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):
|
||||
query = json.dumps(
|
||||
{"cmd": cmd, "afi": "dual", "target": ipprefix}
|
||||
)
|
||||
msg = f"{ipprefix} matched AS_PATH regex."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
else:
|
||||
msg = f"{ipprefix} is an invalid AS_PATH regex."
|
||||
code = 415
|
||||
logger.error(f"{msg}, {code}, {router}, {cmd}, {ipprefix}")
|
||||
return (msg, code, router, query)
|
||||
# BGP Route Query
|
||||
elif cmd in ["bgp_route"]:
|
||||
try:
|
||||
# Use netaddr library to verify if input is a valid IPv4 address or prefix
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
query = json.dumps(
|
||||
{"cmd": cmd, "afi": "ipv4", "target": ipprefix}
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
# Use netaddr library to verify if input is a valid IPv6 address or prefix
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
query = json.dumps(
|
||||
{"cmd": cmd, "afi": "ipv6", "target": ipprefix}
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
# Exception from netaddr library will return a user-facing error
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
code = 415
|
||||
logger.error(f"{msg}, {code}, {router}, {cmd}, {ipprefix}")
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
# Ping/Traceroute
|
||||
elif cmd in ["ping", "traceroute"]:
|
||||
try:
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
query = json.dumps(
|
||||
{
|
||||
"cmd": cmd,
|
||||
"afi": "ipv4",
|
||||
"source": src_addr_ipv4,
|
||||
"target": ipprefix,
|
||||
}
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
query = json.dumps(
|
||||
{
|
||||
"cmd": cmd,
|
||||
"afi": "ipv6",
|
||||
"source": src_addr_ipv6,
|
||||
"target": ipprefix,
|
||||
}
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
code = 200
|
||||
return (msg, code, router, query)
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
code = 415
|
||||
logger.error(f"{msg}, {code}, {router}, {cmd}, {ipprefix}")
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
else:
|
||||
msg = f"Command {cmd} not found."
|
||||
code = 415
|
||||
logger.error(f"{msg}, {code}, {router}, {cmd}, {ipprefix}")
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
except:
|
||||
router_ip = r["address"]
|
||||
error_msg = logger.error(
|
||||
f"Input router IP {router} does not match the configured router IP of {router_ip}"
|
||||
class codes:
|
||||
"""Class for easy calling & recalling of http success/error codes"""
|
||||
|
||||
def __init__(self):
|
||||
# 200 OK: renders standard display text
|
||||
self.success = 200
|
||||
# 405 Method Not Allowed: Renders Bulma "warning" class notification message with message text
|
||||
self.warning = 405
|
||||
# 415 Unsupported Media Type: Renders Bulma "danger" class notification message with message text
|
||||
self.danger = 415
|
||||
|
||||
|
||||
code = codes()
|
||||
|
||||
|
||||
def frr(cmd, ipprefix, device):
|
||||
d_address = device["address"]
|
||||
d_src_addr_ipv4 = device["src_addr_ipv4"]
|
||||
d_src_addr_ipv6 = device["src_addr_ipv6"]
|
||||
d_location = device["location"]
|
||||
d_name = device["name"]
|
||||
d_port = device["port"]
|
||||
d_type = device["type"]
|
||||
|
||||
logger.info(f"Constructing {cmd} command for FRR router {d_name} to {ipprefix}...")
|
||||
# BGP Community Query
|
||||
if cmd in ["bgp_community"]:
|
||||
# Extended Communities, new-format
|
||||
query = json.dumps({"cmd": cmd, "afi": "dual", "target": ipprefix})
|
||||
if re.match("^([0-9]{0,5})\:([0-9]{1,5})$", ipprefix):
|
||||
msg = f"{ipprefix} matched new-format community."
|
||||
return (msg, code.success, d_address, query)
|
||||
# Extended Communities, 32 bit format
|
||||
elif re.match("^[0-9]{1,10}$", ipprefix):
|
||||
msg = f"{ipprefix} matched 32 bit community."
|
||||
return (msg, code.success, d_address, query)
|
||||
# RFC 8092 Large Community Support
|
||||
elif re.match("^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$", ipprefix):
|
||||
msg = f"{ipprefix} matched large community."
|
||||
return (msg, code.success, d_address, query)
|
||||
else:
|
||||
msg = f"{ipprefix} is an invalid BGP Community Format."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {query}")
|
||||
return (msg, code.danger, d_address, query)
|
||||
# BGP AS_PATH Query
|
||||
elif cmd in ["bgp_aspath"]:
|
||||
if re.match(".*", ipprefix):
|
||||
query = json.dumps({"cmd": cmd, "afi": "dual", "target": ipprefix})
|
||||
msg = f"{ipprefix} matched AS_PATH regex."
|
||||
return (msg, code.success, d_address, query)
|
||||
else:
|
||||
msg = f"{ipprefix} is an invalid AS_PATH regex."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
|
||||
return (msg, code.danger, d_address, query)
|
||||
# BGP Route Query
|
||||
elif cmd in ["bgp_route"]:
|
||||
try:
|
||||
# Use netaddr library to verify if input is a valid IPv4 address or prefix
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
query = json.dumps({"cmd": cmd, "afi": "ipv4", "target": ipprefix})
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
return (msg, code.success, d_address, query)
|
||||
# Use netaddr library to verify if input is a valid IPv6 address or prefix
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
query = json.dumps({"cmd": cmd, "afi": "ipv6", "target": ipprefix})
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
return (msg, code.success, d_address, query)
|
||||
# Exception from netaddr library will return a user-facing error
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {query}")
|
||||
return (msg, code.danger, d_address, query)
|
||||
# Ping/Traceroute
|
||||
elif cmd in ["ping", "traceroute"]:
|
||||
try:
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
query = json.dumps(
|
||||
{
|
||||
"cmd": cmd,
|
||||
"afi": "ipv4",
|
||||
"source": d_src_addr_ipv4,
|
||||
"target": ipprefix,
|
||||
}
|
||||
)
|
||||
raise ValueError(error_msg)
|
||||
except:
|
||||
raise
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
return (msg, code.success, d_address, query)
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
query = json.dumps(
|
||||
{
|
||||
"cmd": cmd,
|
||||
"afi": "ipv6",
|
||||
"source": d_src_addr_ipv6,
|
||||
"target": ipprefix,
|
||||
}
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
return (msg, code.success, d_address, query)
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {query}")
|
||||
return (msg, code.danger, d_name, query)
|
||||
else:
|
||||
msg = f"Command {cmd} not found."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {query}")
|
||||
return (msg, code.danger, d_name, query)
|
||||
|
||||
|
||||
def netmiko(router, cmd, ipprefix):
|
||||
def ssh(cmd, ipprefix, device):
|
||||
"""Receives JSON from Flask, constucts the command that will be passed to the router. Also handles input validation & error handling."""
|
||||
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:
|
||||
try:
|
||||
if router == r["address"]:
|
||||
type = r["type"]
|
||||
src_addr_ipv4 = r["src_addr_ipv4"]
|
||||
src_addr_ipv6 = r["src_addr_ipv6"]
|
||||
# Loop through commands config file, set variables for matched commands
|
||||
for nos in commands:
|
||||
if type == nos:
|
||||
nos = commands[type]
|
||||
nos_commands = nos[0]
|
||||
# Dual stack commands (agnostic of IPv4/IPv6)
|
||||
dual_commands = nos_commands["dual"]
|
||||
# IPv4 Specific Commands
|
||||
ipv4_commands = nos_commands["ipv4"]
|
||||
# IPv6 Specific Commands
|
||||
ipv6_commands = nos_commands["ipv6"]
|
||||
if cmd == "Query Type":
|
||||
msg = "You must select a query type."
|
||||
code = 415
|
||||
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
|
||||
if re.match("^([0-9]{0,5})\:([0-9]{1,5})$", ipprefix):
|
||||
for a, c in dual_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = f"{ipprefix} matched new-format community."
|
||||
code = 200
|
||||
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 = (
|
||||
f"{ipprefix} matched 32 bit community."
|
||||
)
|
||||
code = 200
|
||||
return (msg, code, router, type, command)
|
||||
# RFC 8092 Large Community Support
|
||||
elif re.match(
|
||||
"^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$",
|
||||
ipprefix,
|
||||
):
|
||||
for a, c in dual_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = f"{ipprefix} matched large community."
|
||||
code = 200
|
||||
return (msg, code, router, type, command)
|
||||
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 = f"{ipprefix} matched AS_PATH regex."
|
||||
code = 200
|
||||
return (msg, code, router, type, command)
|
||||
else:
|
||||
msg = f"{ipprefix} is an invalid AS_PATH regex."
|
||||
code = 415
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
# BGP Route Query
|
||||
elif cmd in ["bgp_route"]:
|
||||
try:
|
||||
# Use netaddr library to verify if input is a valid IPv4 address or prefix
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
for a, c in ipv4_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
code = 200
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
router,
|
||||
type,
|
||||
command,
|
||||
)
|
||||
# Use netaddr library to verify if input is a valid IPv6 address or prefix
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
for a, c in ipv6_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(target=ipprefix)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
code = 200
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
router,
|
||||
type,
|
||||
command,
|
||||
)
|
||||
# Exception from netaddr library will return a user-facing error
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
code = 415
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
# Ping/Traceroute
|
||||
elif cmd in ["ping", "traceroute"]:
|
||||
try:
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
for a, c in ipv4_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(
|
||||
target=ipprefix,
|
||||
src_addr_ipv4=src_addr_ipv4,
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
code = 200
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
router,
|
||||
type,
|
||||
command,
|
||||
)
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
for a, c in ipv6_commands.items():
|
||||
if a == cmd:
|
||||
command = c.format(
|
||||
target=ipprefix,
|
||||
src_addr_ipv6=src_addr_ipv6,
|
||||
)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
code = 200
|
||||
return (
|
||||
msg,
|
||||
code,
|
||||
router,
|
||||
type,
|
||||
command,
|
||||
)
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
code = 415
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
else:
|
||||
msg = f"Command {cmd} not found."
|
||||
code = 415
|
||||
logger.error(
|
||||
f"{msg}, {code}, {router}, {cmd}, {ipprefix}"
|
||||
)
|
||||
return (msg, code, router, cmd, ipprefix)
|
||||
except:
|
||||
router_ip = r["address"]
|
||||
error_msg = logger.error(
|
||||
f"Input router IP {router} does not match the configured router IP of {router_ip}"
|
||||
)
|
||||
raise ValueError(error_msg)
|
||||
except:
|
||||
raise
|
||||
d_address = device["address"]
|
||||
d_src_addr_ipv4 = device["src_addr_ipv4"]
|
||||
d_src_addr_ipv6 = device["src_addr_ipv6"]
|
||||
d_location = device["location"]
|
||||
d_name = device["name"]
|
||||
d_port = device["port"]
|
||||
d_type = device["type"]
|
||||
|
||||
logger.info(f"Constructing {cmd} command for {d_name} to {ipprefix}...")
|
||||
# Loop through commands config file, set variables for matched commands
|
||||
class command:
|
||||
def __init__(self, type):
|
||||
if type in commands:
|
||||
self.dual = commands[type][0]["dual"]
|
||||
self.ipv4 = commands[type][0]["ipv4"]
|
||||
self.ipv6 = commands[type][0]["ipv6"]
|
||||
else:
|
||||
msg = f"{d_type} is an unsupported network operating system."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
|
||||
return (msg, code.danger, d_name, cmd, ipprefix)
|
||||
|
||||
c = command(d_type)
|
||||
# BGP Community Query
|
||||
if cmd == "bgp_community":
|
||||
# Extended Communities, new-format
|
||||
if re.match("^([0-9]{0,5})\:([0-9]{1,5})$", ipprefix):
|
||||
mc = c.dual[cmd]
|
||||
command = mc.format(target=ipprefix)
|
||||
msg = f"{ipprefix} matched new-format community."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
# Extended Communities, 32 bit format
|
||||
elif re.match("^[0-9]{1,10}$", ipprefix):
|
||||
mc = c.dual[cmd]
|
||||
command = mc.format(target=ipprefix)
|
||||
msg = f"{ipprefix} matched 32 bit community."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
# RFC 8092 Large Community Support
|
||||
elif re.match("^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$", ipprefix):
|
||||
mc = c.dual[cmd]
|
||||
command = mc.format(target=ipprefix)
|
||||
msg = f"{ipprefix} matched large community."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
else:
|
||||
msg = f"{ipprefix} is an invalid BGP Community Format."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
|
||||
return (msg, code.danger, d_name, cmd, ipprefix)
|
||||
# BGP AS_PATH Query
|
||||
elif cmd == "bgp_aspath":
|
||||
if re.match(".*", ipprefix):
|
||||
mc = c.dual[cmd]
|
||||
command = mc.format(target=ipprefix)
|
||||
msg = f"{ipprefix} matched AS_PATH regex."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
else:
|
||||
msg = f"{ipprefix} is an invalid AS_PATH regex."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
|
||||
return (msg, code.danger, d_name, cmd, ipprefix)
|
||||
# BGP Route Query
|
||||
elif cmd == "bgp_route":
|
||||
try:
|
||||
# Use netaddr library to verify if input is a valid IPv4 address or prefix
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
mc = c.ipv4[cmd]
|
||||
command = mc.format(target=ipprefix)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
# Use netaddr library to verify if input is a valid IPv6 address or prefix
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
mc = c.ipv6[cmd]
|
||||
command = mc.format(target=ipprefix)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
# Exception from netaddr library will return a user-facing error
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
|
||||
return (msg, code.danger, d_name, cmd, ipprefix)
|
||||
# Ping/Traceroute
|
||||
elif cmd in ["ping", "traceroute"]:
|
||||
try:
|
||||
if IPNetwork(ipprefix).ip.version == 4:
|
||||
mc = c.ipv4[cmd]
|
||||
command = mc.format(target=ipprefix, src_addr_ipv4=d_src_addr_ipv4)
|
||||
msg = f"{ipprefix} is a valid IPv4 Adddress."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
elif IPNetwork(ipprefix).ip.version == 6:
|
||||
mc = c.ipv6[cmd]
|
||||
command = mc.format(target=ipprefix, src_addr_ipv6=d_src_addr_ipv6)
|
||||
msg = f"{ipprefix} is a valid IPv6 Adddress."
|
||||
return (msg, code.success, d_address, d_type, command)
|
||||
except:
|
||||
msg = f"{ipprefix} is an invalid IP Address."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
|
||||
return (msg, code.danger, d_name, cmd, ipprefix)
|
||||
else:
|
||||
msg = f"Command {cmd} not found."
|
||||
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
|
||||
return (msg, code.danger, d_name, cmd, ipprefix)
|
||||
|
Reference in New Issue
Block a user