Merge pull request #1 from TimStallard/tds
better bgpmap internal route handling, other minor changes
This commit is contained in:
commit
fca8545fcf
101
lg.py
101
lg.py
@ -123,7 +123,7 @@ def whois_command(query):
|
|||||||
def bird_command(host, proto, query):
|
def bird_command(host, proto, query):
|
||||||
"""Alias to bird_proxy for bird service"""
|
"""Alias to bird_proxy for bird service"""
|
||||||
if app.config.get("UNIFIED_DAEMON", False):
|
if app.config.get("UNIFIED_DAEMON", False):
|
||||||
return bird_proxy(host, "ipv4", "bird", query)
|
return bird_proxy(host, app.config.get("PROTO_DEFAULT", "ipv4"), "bird", query)
|
||||||
else:
|
else:
|
||||||
return bird_proxy(host, proto, "bird", query)
|
return bird_proxy(host, proto, "bird", query)
|
||||||
|
|
||||||
@ -145,6 +145,8 @@ def bird_proxy(host, proto, service, query):
|
|||||||
path = service
|
path = service
|
||||||
|
|
||||||
proxyHost = app.config["PROXY"].get(host, "")
|
proxyHost = app.config["PROXY"].get(host, "")
|
||||||
|
if isinstance(proxyHost, int):
|
||||||
|
proxyHost = "%s:%s" % (host, proxyHost)
|
||||||
|
|
||||||
if not proxyHost:
|
if not proxyHost:
|
||||||
return False, 'Host "%s" invalid' % host
|
return False, 'Host "%s" invalid' % host
|
||||||
@ -185,14 +187,12 @@ def inject_commands():
|
|||||||
return dict(commands=commands, commands_dict=commands_dict)
|
return dict(commands=commands, commands_dict=commands_dict)
|
||||||
|
|
||||||
|
|
||||||
@app.context_processor
|
|
||||||
def inject_all_host():
|
|
||||||
return dict(all_hosts="+".join(app.config["PROXY"].keys()))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def hello():
|
def hello():
|
||||||
return redirect("/summary/%s/ipv4" % "+".join(app.config["PROXY"].keys()))
|
if app.config.get("UNIFIED_DAEMON", False):
|
||||||
|
return redirect("/summary/all")
|
||||||
|
else:
|
||||||
|
return redirect("/summary/all/%s" % app.config.get("PROTO_DEFAULT", "ipv4"))
|
||||||
|
|
||||||
|
|
||||||
def error_page(text):
|
def error_page(text):
|
||||||
@ -230,18 +230,20 @@ def whois():
|
|||||||
return jsonify(output=output, title=query)
|
return jsonify(output=output, title=query)
|
||||||
|
|
||||||
|
|
||||||
SUMMARY_UNWANTED_PROTOS = ["Kernel", "Static", "Device"]
|
SUMMARY_UNWANTED_PROTOS = ["Kernel", "Static", "Device", "BFD", "Direct"]
|
||||||
|
|
||||||
@app.route("/summary/<hosts>")
|
@app.route("/summary/<hosts>")
|
||||||
@app.route("/summary/<hosts>/<proto>")
|
@app.route("/summary/<hosts>/<proto>")
|
||||||
def summary(hosts, proto="ipv4"):
|
def summary(hosts, proto="ipv4"):
|
||||||
|
|
||||||
set_session("summary", hosts, proto, "")
|
set_session("summary", hosts, proto, "")
|
||||||
command = "show protocols"
|
command = "show protocols"
|
||||||
|
|
||||||
summary = {}
|
summary = {}
|
||||||
errors = []
|
errors = []
|
||||||
for host in hosts.split("+"):
|
hosts = hosts.split("+")
|
||||||
|
if hosts == ["all"]:
|
||||||
|
hosts = app.config["PROXY"].keys()
|
||||||
|
for host in hosts:
|
||||||
ret, res = bird_command(host, proto, command)
|
ret, res = bird_command(host, proto, command)
|
||||||
res = res.split("\n")
|
res = res.split("\n")
|
||||||
|
|
||||||
@ -284,8 +286,9 @@ def summary(hosts, proto="ipv4"):
|
|||||||
return render_template('summary.html', summary=summary, command=command, errors=errors)
|
return render_template('summary.html', summary=summary, command=command, errors=errors)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/detail/<hosts>")
|
||||||
@app.route("/detail/<hosts>/<proto>")
|
@app.route("/detail/<hosts>/<proto>")
|
||||||
def detail(hosts, proto):
|
def detail(hosts, proto="ipv4"):
|
||||||
name = get_query()
|
name = get_query()
|
||||||
|
|
||||||
if not name:
|
if not name:
|
||||||
@ -296,7 +299,10 @@ def detail(hosts, proto):
|
|||||||
|
|
||||||
detail = {}
|
detail = {}
|
||||||
errors = []
|
errors = []
|
||||||
for host in hosts.split("+"):
|
hosts = hosts.split("+")
|
||||||
|
if hosts == ["all"]:
|
||||||
|
hosts = app.config["PROXY"].keys()
|
||||||
|
for host in hosts:
|
||||||
ret, res = bird_command(host, proto, command)
|
ret, res = bird_command(host, proto, command)
|
||||||
res = res.split("\n")
|
res = res.split("\n")
|
||||||
|
|
||||||
@ -308,13 +314,14 @@ def detail(hosts, proto):
|
|||||||
errors.append("%s: bird command failed with error, %s" % (host, "\n".join(res)))
|
errors.append("%s: bird command failed with error, %s" % (host, "\n".join(res)))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
detail[host] = {"status": res[1], "description": add_links(res[2:])}
|
detail[host] = {"status": res[1], "description": add_links(res[2:]).decode("utf-8")}
|
||||||
|
|
||||||
return render_template('detail.html', detail=detail, command=command, errors=errors)
|
return render_template('detail.html', detail=detail, command=command, errors=errors)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/traceroute/<hosts>")
|
||||||
@app.route("/traceroute/<hosts>/<proto>")
|
@app.route("/traceroute/<hosts>/<proto>")
|
||||||
def traceroute(hosts, proto):
|
def traceroute(hosts, proto="ipv4"):
|
||||||
q = get_query()
|
q = get_query()
|
||||||
|
|
||||||
if not q:
|
if not q:
|
||||||
@ -325,9 +332,16 @@ def traceroute(hosts, proto):
|
|||||||
if app.config.get("UNIFIED_DAEMON", False):
|
if app.config.get("UNIFIED_DAEMON", False):
|
||||||
if not ip_is_valid(q):
|
if not ip_is_valid(q):
|
||||||
try:
|
try:
|
||||||
|
if app.config.get("UNIFIED_TRACEROUTE_IPV6", True):
|
||||||
q = resolve_any(q)
|
q = resolve_any(q)
|
||||||
|
else:
|
||||||
|
q = resolve(q, "A")
|
||||||
except:
|
except:
|
||||||
return error_page("%s is unresolvable" % q)
|
return error_page("%s is unresolvable" % q)
|
||||||
|
if ipv6_is_valid(q):
|
||||||
|
proto = "ipv6"
|
||||||
|
else:
|
||||||
|
proto = "ipv4"
|
||||||
else:
|
else:
|
||||||
if proto == "ipv6" and not ipv6_is_valid(q):
|
if proto == "ipv6" and not ipv6_is_valid(q):
|
||||||
try:
|
try:
|
||||||
@ -342,7 +356,10 @@ def traceroute(hosts, proto):
|
|||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
infos = {}
|
infos = {}
|
||||||
for host in hosts.split("+"):
|
hosts = hosts.split("+")
|
||||||
|
if hosts == ["all"]:
|
||||||
|
hosts = app.config["PROXY"].keys()
|
||||||
|
for host in hosts:
|
||||||
status, resultat = bird_proxy(host, proto, "traceroute", q)
|
status, resultat = bird_proxy(host, proto, "traceroute", q)
|
||||||
if status is False:
|
if status is False:
|
||||||
errors.append("%s" % resultat)
|
errors.append("%s" % resultat)
|
||||||
@ -353,43 +370,51 @@ def traceroute(hosts, proto):
|
|||||||
return render_template('traceroute.html', infos=infos, errors=errors)
|
return render_template('traceroute.html', infos=infos, errors=errors)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/adv/<hosts>")
|
||||||
@app.route("/adv/<hosts>/<proto>")
|
@app.route("/adv/<hosts>/<proto>")
|
||||||
def show_route_filter(hosts, proto):
|
def show_route_filter(hosts, proto="ipv4"):
|
||||||
return show_route("adv", hosts, proto)
|
return show_route("adv", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/adv_bgpmap/<hosts>")
|
||||||
@app.route("/adv_bgpmap/<hosts>/<proto>")
|
@app.route("/adv_bgpmap/<hosts>/<proto>")
|
||||||
def show_route_filter_bgpmap(hosts, proto):
|
def show_route_filter_bgpmap(hosts, proto="ipv4"):
|
||||||
return show_route("adv_bgpmap", hosts, proto)
|
return show_route("adv_bgpmap", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/where/<hosts>")
|
||||||
@app.route("/where/<hosts>/<proto>")
|
@app.route("/where/<hosts>/<proto>")
|
||||||
def show_route_where(hosts, proto):
|
def show_route_where(hosts, proto="ipv4"):
|
||||||
return show_route("where", hosts, proto)
|
return show_route("where", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/where_detail/<hosts>")
|
||||||
@app.route("/where_detail/<hosts>/<proto>")
|
@app.route("/where_detail/<hosts>/<proto>")
|
||||||
def show_route_where_detail(hosts, proto):
|
def show_route_where_detail(hosts, proto="ipv4"):
|
||||||
return show_route("where_detail", hosts, proto)
|
return show_route("where_detail", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/where_bgpmap/<hosts>")
|
||||||
@app.route("/where_bgpmap/<hosts>/<proto>")
|
@app.route("/where_bgpmap/<hosts>/<proto>")
|
||||||
def show_route_where_bgpmap(hosts, proto):
|
def show_route_where_bgpmap(hosts, proto="ipv4"):
|
||||||
return show_route("where_bgpmap", hosts, proto)
|
return show_route("where_bgpmap", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/prefix/<hosts>")
|
||||||
@app.route("/prefix/<hosts>/<proto>")
|
@app.route("/prefix/<hosts>/<proto>")
|
||||||
def show_route_for(hosts, proto):
|
def show_route_for(hosts, proto="ipv4"):
|
||||||
return show_route("prefix", hosts, proto)
|
return show_route("prefix", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/prefix_detail/<hosts>")
|
||||||
@app.route("/prefix_detail/<hosts>/<proto>")
|
@app.route("/prefix_detail/<hosts>/<proto>")
|
||||||
def show_route_for_detail(hosts, proto):
|
def show_route_for_detail(hosts, proto="ipv4"):
|
||||||
return show_route("prefix_detail", hosts, proto)
|
return show_route("prefix_detail", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/prefix_bgpmap/<hosts>")
|
||||||
@app.route("/prefix_bgpmap/<hosts>/<proto>")
|
@app.route("/prefix_bgpmap/<hosts>/<proto>")
|
||||||
def show_route_for_bgpmap(hosts, proto):
|
def show_route_for_bgpmap(hosts, proto="ipv4"):
|
||||||
return show_route("prefix_bgpmap", hosts, proto)
|
return show_route("prefix_bgpmap", hosts, proto)
|
||||||
|
|
||||||
|
|
||||||
@ -519,7 +544,9 @@ def show_bgpmap():
|
|||||||
hop_label = ""
|
hop_label = ""
|
||||||
|
|
||||||
|
|
||||||
add_node(_as, fillcolor=(first and "#F5A9A9" or "white"))
|
add_node(_as, fillcolor=("white"))
|
||||||
|
if first:
|
||||||
|
nodes[_as].set_fillcolor("#F5A9A9")
|
||||||
if hop_label:
|
if hop_label:
|
||||||
edge = add_edge(nodes[previous_as], nodes[_as], label=hop_label, fontsize="7")
|
edge = add_edge(nodes[previous_as], nodes[_as], label=hop_label, fontsize="7")
|
||||||
else:
|
else:
|
||||||
@ -587,7 +614,8 @@ def build_as_tree_from_raw_bird_ouput(host, proto, text):
|
|||||||
for rt_host, rt_ips in app.config["ROUTER_IP"].iteritems():
|
for rt_host, rt_ips in app.config["ROUTER_IP"].iteritems():
|
||||||
# Special case for internal routing
|
# Special case for internal routing
|
||||||
if peer_ip in rt_ips:
|
if peer_ip in rt_ips:
|
||||||
path = [rt_host]
|
paths.append([peer_protocol_name, rt_host])
|
||||||
|
path = None
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# ugly hack for good printing
|
# ugly hack for good printing
|
||||||
@ -604,7 +632,13 @@ def build_as_tree_from_raw_bird_ouput(host, proto, text):
|
|||||||
if expr3.group(1).strip():
|
if expr3.group(1).strip():
|
||||||
net_dest = expr3.group(1).strip()
|
net_dest = expr3.group(1).strip()
|
||||||
|
|
||||||
if line.startswith("BGP.as_path:"):
|
expr4 = re.search(r'^dev', line)
|
||||||
|
#handle on-link routes
|
||||||
|
if expr4:
|
||||||
|
paths.append([peer_protocol_name, net_dest])
|
||||||
|
path = None
|
||||||
|
|
||||||
|
if line.startswith("BGP.as_path:") and path:
|
||||||
path.extend(line.replace("BGP.as_path:", "").strip().split(" "))
|
path.extend(line.replace("BGP.as_path:", "").strip().split(" "))
|
||||||
|
|
||||||
if path:
|
if path:
|
||||||
@ -677,7 +711,11 @@ def show_route(request_type, hosts, proto):
|
|||||||
|
|
||||||
detail = {}
|
detail = {}
|
||||||
errors = []
|
errors = []
|
||||||
for host in hosts.split("+"):
|
hosts = hosts.split("+")
|
||||||
|
if hosts == ["all"]:
|
||||||
|
hosts = app.config["PROXY"].keys()
|
||||||
|
allhosts = hosts[:]
|
||||||
|
for host in allhosts:
|
||||||
ret, res = bird_command(host, proto, command)
|
ret, res = bird_command(host, proto, command)
|
||||||
res = res.split("\n")
|
res = res.split("\n")
|
||||||
|
|
||||||
@ -691,6 +729,15 @@ def show_route(request_type, hosts, proto):
|
|||||||
|
|
||||||
if bgpmap:
|
if bgpmap:
|
||||||
detail[host] = build_as_tree_from_raw_bird_ouput(host, proto, res)
|
detail[host] = build_as_tree_from_raw_bird_ouput(host, proto, res)
|
||||||
|
#for internal routes via hosts not selected
|
||||||
|
#add them to the list, but only show preferred route
|
||||||
|
if host not in hosts:
|
||||||
|
detail[host] = detail[host][:1]
|
||||||
|
for path in detail[host]:
|
||||||
|
if len(path) == 2:
|
||||||
|
if (path[1] not in allhosts) and (path[1] in app.config["PROXY"]):
|
||||||
|
allhosts.append(path[1])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
detail[host] = add_links(res)
|
detail[host] = add_links(res)
|
||||||
|
|
||||||
|
@ -5,7 +5,10 @@ function change_url(loc){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reload(){
|
function reload(){
|
||||||
loc = "/" + request_type + "/" + hosts + "/" + proto;
|
loc = "/" + request_type + "/" + hosts;
|
||||||
|
if(proto){
|
||||||
|
loc += "/" + proto;
|
||||||
|
}
|
||||||
if (request_type != "summary" ){
|
if (request_type != "summary" ){
|
||||||
if( request_args != undefined && request_args != ""){
|
if( request_args != undefined && request_args != ""){
|
||||||
loc = loc + "?q=" + encodeURIComponent(request_args);
|
loc = loc + "?q=" + encodeURIComponent(request_args);
|
||||||
@ -23,7 +26,9 @@ function update_view(){
|
|||||||
|
|
||||||
$(".navbar li").removeClass('active');
|
$(".navbar li").removeClass('active');
|
||||||
|
|
||||||
|
if(proto){
|
||||||
$("a#"+proto+".proto").addClass('active');
|
$("a#"+proto+".proto").addClass('active');
|
||||||
|
}
|
||||||
$(".hosts a[id='"+hosts+"']").addClass('active');
|
$(".hosts a[id='"+hosts+"']").addClass('active');
|
||||||
$(".request_type a#"+request_type).parent().addClass('active');
|
$(".request_type a#"+request_type).parent().addClass('active');
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
<a class="navbar-brand" href="/">{{config.DOMAIN|capitalize}}</a>
|
<a class="navbar-brand" href="/">{{config.DOMAIN|capitalize}}</a>
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li class="nav-item hosts mr-1"><a class="nav-link" id="{{all_hosts}}" href="#">all</a></li>
|
<li class="nav-item hosts mr-1"><a class="nav-link" id="all" href="#">all</a></li>
|
||||||
|
|
||||||
{% for host in config.PROXY %}
|
{% for host in config.PROXY %}
|
||||||
<li class="nav-item hosts mr-1"><a class="nav-link" id="{{host}}" href="#">{{host}}</a></li>
|
<li class="nav-item hosts mr-1"><a class="nav-link" id="{{host}}" href="#">{{host}}</a></li>
|
||||||
@ -76,7 +76,7 @@
|
|||||||
<div class="list-group history">
|
<div class="list-group history">
|
||||||
{% for hosts, proto, request_type, request_args in session.history %}
|
{% for hosts, proto, request_type, request_args in session.history %}
|
||||||
<a class="list-group-item list-group-item-action {% if loop.first %}active{% endif %}"
|
<a class="list-group-item list-group-item-action {% if loop.first %}active{% endif %}"
|
||||||
href="/{{ [request_type, hosts, proto]|join("/") }}{% if request_args %}?q={{request_args}}{% endif %}">
|
href="/{{ [request_type, hosts]|join("/") }}{% if not config.UNIFIED_DAEMON %}/{{proto}}{% endif %}{% if request_args %}?q={{request_args}}{% endif %}">
|
||||||
{{hosts}}{% if not config.UNIFIED_DAEMON %}/{{proto}}{% endif %}: {{ commands_dict[request_type]|replace("...", request_args) }}
|
{{hosts}}{% if not config.UNIFIED_DAEMON %}/{{proto}}{% endif %}: {{ commands_dict[request_type]|replace("...", request_args) }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -119,7 +119,11 @@
|
|||||||
request_type = "{{session.request_type}}";
|
request_type = "{{session.request_type}}";
|
||||||
request_args = "{{session.request_args}}";
|
request_args = "{{session.request_args}}";
|
||||||
hosts = "{{session.hosts}}";
|
hosts = "{{session.hosts}}";
|
||||||
|
{% if config.UNIFIED_DAEMON %}
|
||||||
|
proto = ""
|
||||||
|
{% else %}
|
||||||
proto = "{{session.proto}}";
|
proto = "{{session.proto}}";
|
||||||
|
{% endif %}
|
||||||
history_query = {{session.history|tojson|safe}};
|
history_query = {{session.history|tojson|safe}};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="{{url_for('static', filename='js/lg.js') }}"></script>
|
<script type="text/javascript" src="{{url_for('static', filename='js/lg.js') }}"></script>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
{% for host in detail %}
|
{% for host in detail %}
|
||||||
<h3>
|
<h3>
|
||||||
{{host}}: {{command}}
|
{{host}}: {{command}}
|
||||||
<small><a class="pull-right" href="/{{session.request_type|replace("_detail","")}}_bgpmap/{{session.hosts}}/{{session.proto}}?q={{session.request_args}}">View the BGP map</a></small>
|
<small><a class="pull-right" href="/{{session.request_type|replace("_detail","")}}_bgpmap/{{session.hosts}}{% if not config.UNIFIED_DAEMON %}/{{session.proto}}{% endif %}?q={{session.request_args}}">View the BGP map</a></small>
|
||||||
</h3>
|
</h3>
|
||||||
{% if session.request_args != expression|replace("/32","")|replace("/128","") %}
|
{% if session.request_args != expression|replace("/32","")|replace("/128","") %}
|
||||||
<i>DNS: <a href="/whois/{{session.request_args}}" class="whois">{{session.request_args}}</a> => <a href="/whois/{{ expression|replace("/32","")|replace("/128","") }}" class="whois">{{expression|replace("/32","")|replace("/128","")}}</a></i><br />
|
<i>DNS: <a href="/whois/{{session.request_args}}" class="whois">{{session.request_args}}</a> => <a href="/whois/{{ expression|replace("/32","")|replace("/128","") }}" class="whois">{{expression|replace("/32","")|replace("/128","")}}</a></i><br />
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for row in summary[host] %}
|
{% for row in summary[host] %}
|
||||||
<tr class="{{ loop.cycle('odd', 'even') }}">
|
<tr class="{{ loop.cycle('odd', 'even') }}">
|
||||||
<td><a href="/detail/{{host}}/{{session.proto}}?q={{row.name}}">{{row.name}}</a></td>
|
<td><a href="/detail/{{host}}{% if not config.UNIFIED_DAEMON %}/{{session.proto}}{% endif %}?q={{row.name}}">{{row.name}}</a></td>
|
||||||
<td>{{row.proto}}</td>
|
<td>{{row.proto}}</td>
|
||||||
<td><span class="badge badge-{% if row.state == "up" %}success{% elif row.state == "down" %}default{% elif row.state == "start" and row.info == "Passive" %}info{% else %}danger{% endif %}">{{row.state}}</span></td>
|
<td><span class="badge badge-{% if row.state == "up" %}success{% elif row.state == "down" %}default{% elif row.state == "start" and row.info == "Passive" %}info{% else %}danger{% endif %}">{{row.state}}</span></td>
|
||||||
<td>{{row.since}}</td>
|
<td>{{row.since}}</td>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% for host in infos %}
|
{% for host in infos %}
|
||||||
<h3 id="traceroute_cmd_{{host}}">{{host}}/{{session.proto}}: traceroute {{session.request_args}}</h3><br />
|
<h3 id="traceroute_cmd_{{host}}">{{host}}{% if not config.UNIFIED_DAEMON %}/{{session.proto}}{% endif %}: traceroute {{session.request_args}}</h3><br />
|
||||||
{% if infos[host]|trim %}
|
{% if infos[host]|trim %}
|
||||||
<pre>{{infos[host]|trim|safe}}</pre>
|
<pre>{{infos[host]|trim|safe}}</pre>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user