From 01ec638435d092779d53939d9283de2a8cf1f870 Mon Sep 17 00:00:00 2001 From: Fabien VINCENT Date: Mon, 16 Jul 2018 12:51:08 +0200 Subject: [PATCH] Add a method to allow queries on API and return the same data from show route as JSON value Example : https://[[LG_MASTER]]/api/[[LG_NODES_LIST]]/ipv4?q=8.8.8.8 Return : { "[[LG_NODES_LIST]]": { "result": [ { "origin": "IGP", "med": 0, "via": "1.1.1.2", "last": "2018-07-10", "network": "8.8.8.0", "localPref": 350, "asPath": "15169", "originatorId": { "addr": "4.4.4.4", "reverse": "router.fr.eu" }, "community": [ "65000:65000" ], "clusterList": [ "9.89.6.6", "9.89.8.8" ], "netmask": "24", "fromPeer": "bird", "from": "4.4.4.4", "nextHop": { "addr": "1.1.1.2", "reverse": "google.fr.eu" }, "ipType": "IPv4" } ] } } --- lg.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/lg.py b/lg.py index b4bdd8b..7bace5e 100644 --- a/lg.py +++ b/lg.py @@ -363,6 +363,12 @@ def show_route_for_detail(hosts, proto): def show_route_for_bgpmap(hosts, proto): return show_route("prefix_bgpmap", hosts, proto) +@app.route("/api//") +def show_route_for_api(hosts, proto): + resp = Response(response=show_route_api("prefix_detail", hosts, proto), + status=200, + mimetype="application/json") + return resp def get_as_name(_as): """return a string that contain the as number following by the as name @@ -650,6 +656,56 @@ def show_route(request_type, hosts, proto): return render_template((bgpmap and 'bgpmap.html' or 'route.html'), detail=detail, command=command, expression=expression, errors=errors) +def show_route_api(request_type, hosts, proto): + expression = get_query() + if not expression: + abort(400) + + set_session(request_type, hosts, proto, expression) + + mask = "" + if len(expression.split("/")) == 2: + expression, mask = (expression.split("/")) + + if not mask and proto == "ipv4": + mask = "32" + if not mask and proto == "ipv6": + mask = "128" + if not mask_is_valid(mask): + return error_page("mask %s is invalid" % mask) + if proto == "ipv6" and not ipv6_is_valid(expression): + try: + expression = resolve(expression, "AAAA") + except: + return error_page("%s is unresolvable or invalid for %s" % (expression, proto)) + if proto == "ipv4" and not ipv4_is_valid(expression): + try: + expression = resolve(expression, "A") + except: + return error_page("%s is unresolvable or invalid for %s" % (expression, proto)) + if mask: + expression += "/" + mask + + command = "show route for " + expression + "all" + + detail = {} + errors = [] + for host in hosts.split("+"): + ret, res = bird_command(host, proto, command) + res = res.split("\n") + + if ret is False: + errors.append("%s" % res) + continue + + if len(res) <= 1: + errors.append("%s: bird command failed with error, %s" % (host, "\n".join(res))) + continue + + detail[host] = add_json(res) + + return json.dumps(detail) + if __name__ == "__main__": app.run(app.config.get("BIND_IP", "0.0.0.0"), app.config.get("BIND_PORT", 5000))