From 4c2b4f16286287e9e369a5cae49b9dc4a5e03ddc Mon Sep 17 00:00:00 2001 From: Adrian Schmutzler Date: Sat, 25 Aug 2018 19:29:50 +0200 Subject: [PATCH] gateways: Add new page with gateway data (IPs, DHCP ranges) Shows all interfaces without checking vpnif. Signed-off-by: Adrian Schmutzler --- ffmap/stattools.py | 77 +++++++++- ffmap/web/application.py | 23 ++- ffmap/web/filters.py | 16 ++ ffmap/web/templates/bootstrap.html | 1 + ffmap/web/templates/gws.html | 226 +++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 ffmap/web/templates/gws.html diff --git a/ffmap/stattools.py b/ffmap/stattools.py index 997cb5a..41083ce 100644 --- a/ffmap/stattools.py +++ b/ffmap/stattools.py @@ -248,7 +248,82 @@ def hoods_gws(mysql): result[rs["hood"]] = rs["count"] return result -def gws(mysql,selecthood=None): +def gateways(mysql): + macs = mysql.fetchall(""" + SELECT router_gw.mac, gw.name, gw.id AS gw, gw_netif.netif + FROM router + INNER JOIN router_gw ON router.id = router_gw.router + LEFT JOIN (gw_netif INNER JOIN gw ON gw_netif.gw = gw.id) + ON router_gw.mac = gw_netif.mac + WHERE router.status <> 'orphaned' AND NOT ISNULL(gw.name) + GROUP BY router_gw.mac + ORDER BY gw.name ASC, gw_netif.netif ASC, router_gw.mac ASC + """) + selected = mysql.fetchall(""" + SELECT gw_netif.gw, router.status, COUNT(router_gw.router) AS count + FROM router + INNER JOIN router_gw ON router.id = router_gw.router + INNER JOIN gw_netif ON gw_netif.mac = router_gw.mac + WHERE router_gw.selected = TRUE AND router.status <> 'orphaned' + GROUP BY gw_netif.gw, router.status + """) + others = mysql.fetchall(""" + SELECT gw_netif.gw, router.status, COUNT(router_gw.router) AS count + FROM router + INNER JOIN router_gw ON router.id = router_gw.router + INNER JOIN gw_netif ON gw_netif.mac = router_gw.mac + WHERE router_gw.selected = FALSE AND router.status <> 'orphaned' + GROUP BY gw_netif.gw, router.status + """) + + result = OrderedDict() + for m in macs: + if not m["gw"] in result: + result[m["gw"]] = {"name":m["name"],"macs":[],"selected":{},"others":{}} + result[m["gw"]]["macs"].append(m["mac"]) + for rs in selected: + result[rs["gw"]]["selected"][rs["status"]] = rs["count"] + for rs in others: + result[rs["gw"]]["others"][rs["status"]] = rs["count"] + return result + +def gws_ipv4(mysql): + data = mysql.fetchall(""" + SELECT name, n1.ipv4, n1.netif AS batif, n2.netif AS vpnif, n2.mac FROM gw + INNER JOIN gw_netif AS n1 ON gw.id = n1.gw + LEFT JOIN gw_netif AS n2 ON n2.mac = n1.vpnmac AND n1.gw = n2.gw + WHERE n1.ipv4 IS NOT NULL + GROUP BY name, n1.ipv4, n1.netif, n2.netif, n2.mac + ORDER BY n1.ipv4 + """) + + return data + +def gws_ipv6(mysql): + data = mysql.fetchall(""" + SELECT name, n1.ipv6, n1.netif AS batif, n2.netif AS vpnif, n2.mac FROM gw + INNER JOIN gw_netif AS n1 ON gw.id = n1.gw + LEFT JOIN gw_netif AS n2 ON n2.mac = n1.vpnmac AND n1.gw = n2.gw + WHERE n1.ipv6 IS NOT NULL + GROUP BY name, n1.ipv6, n1.netif, n2.netif, n2.mac + ORDER BY n1.ipv6 + """) + + return data + +def gws_dhcp(mysql): + data = mysql.fetchall(""" + SELECT name, n1.dhcpstart, n1.dhcpend, n1.netif AS batif, n2.netif AS vpnif, n2.mac FROM gw + INNER JOIN gw_netif AS n1 ON gw.id = n1.gw + LEFT JOIN gw_netif AS n2 ON n2.mac = n1.vpnmac AND n1.gw = n2.gw + WHERE n1.dhcpstart IS NOT NULL + GROUP BY name, n1.dhcpstart, n1.dhcpend, n1.netif, n2.netif, n2.mac + ORDER BY n1.dhcpstart + """) + + return data + +def gws_ifs(mysql,selecthood=None): if selecthood: where = " AND hood=%s" tup = (selecthood,) diff --git a/ffmap/web/application.py b/ffmap/web/application.py index 1316370..0897923 100755 --- a/ffmap/web/application.py +++ b/ffmap/web/application.py @@ -501,7 +501,7 @@ def global_gwstatistics(selectgw): def helper_statistics(mysql,stats,selecthood,selectgw): try: hoods = stattools.hoods(mysql,selectgw) - gws = stattools.gws(mysql,selecthood) + gws = stattools.gws_ifs(mysql,selecthood) if selecthood: selecthoodname = mysql.findone("SELECT name FROM hoods WHERE id = %s",(selecthood,),'name') @@ -588,6 +588,27 @@ def helper_statistics(mysql,stats,selecthood,selectgw): import traceback writefulllog("Warning: Failed to display stats page: %s\n__%s" % (e, traceback.format_exc().replace("\n", "\n__"))) +@app.route('/gateways') +def gateways(): + try: + mysql = FreifunkMySQL() + gws = stattools.gateways(mysql) + ipv4 = stattools.gws_ipv4(mysql) + ipv6 = stattools.gws_ipv6(mysql) + dhcp = stattools.gws_dhcp(mysql) + mysql.close() + + return render_template("gws.html", + gws = gws, + ipv4 = ipv4, + ipv6 = ipv6, + dhcp = dhcp + ) + except Exception as e: + writelog(CONFIG["debug_dir"] + "/fail_gateways.txt", str(e)) + import traceback + writefulllog("Warning: Failed to display gateways page: %s\n__%s" % (e, traceback.format_exc().replace("\n", "\n__"))) + @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': diff --git a/ffmap/web/filters.py b/ffmap/web/filters.py index 6701aff..8d721af 100644 --- a/ffmap/web/filters.py +++ b/ffmap/web/filters.py @@ -10,6 +10,7 @@ import datetime import re import hashlib from ffmap.misc import int2mac, int2shortmac, inttoipv4, bintoipv6 +from ipaddress import ip_address sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/' + '../..')) from ffmap.misc import * @@ -20,6 +21,13 @@ filters = Blueprint("filters", __name__) def sumdict(d): return sum(d.values()) +@filters.app_template_filter('longip') +def longip(d): + if len(d) > 32: + return d.replace('::','::... ...::') + else: + return d + @filters.app_template_filter('int2mac') def int2macfilter(d): return int2mac(d) @@ -36,6 +44,14 @@ def int2ipv4filter(d): def bin2ipv6filter(d): return bintoipv6(d) +@filters.app_template_filter('ip2int') +def ip2intfilter(d): + return int(ip_address(d)) + +@filters.app_template_filter('ipnet2int') +def ipnet2intfilter(d): + return int(ip_address(d.split("/")[0])) + @filters.app_template_filter('utc2local') def utc2local(dt): return dt.astimezone(tz.tzlocal()) diff --git a/ffmap/web/templates/bootstrap.html b/ffmap/web/templates/bootstrap.html index 80fdf9d..37bfcee 100644 --- a/ffmap/web/templates/bootstrap.html +++ b/ffmap/web/templates/bootstrap.html @@ -39,6 +39,7 @@ (["router_list", "router_info"], "Routers"), (["user_list", "user_info"], "Users"), (["global_statistics"], "Statistics"), + (["gateways"], "GWs"), (["apidoc"], "API"), ] %}
  • {{ text }}
  • diff --git a/ffmap/web/templates/gws.html b/ffmap/web/templates/gws.html new file mode 100644 index 0000000..d637ef1 --- /dev/null +++ b/ffmap/web/templates/gws.html @@ -0,0 +1,226 @@ +{% extends "bootstrap.html" %} +{% block title %}{{super()}} :: Gateways{% endblock %} +{% block head %}{{super()}} + + + + + + + + + + + + + + + +{% endblock %} + +{% block content %} +
    +
    +
    +
    Gateways (selected / others)
    +
    + + + + + + + + + + + + {%- for gw, value in gws.items() %} + + + + + + + + {%- endfor %} + +
    GatewayOnOffUnk.Sum

    {{ value["name"] }}

    {{ value["selected"]["online"] or 0 }} / {{ value["others"]["online"] or 0 }}{{ value["selected"]["offline"] or 0 }} / {{ value["others"]["offline"] or 0 }}{{ value["selected"]["unknown"] or 0 }} / {{ value["others"]["unknown"] or 0 }}{{ value["selected"]|sumdict if value["selected"] else 0 }} / {{ value["others"]|sumdict if value["others"] else 0 }}
    +
    +
    +
    +
    DHCP ranges
    +
    + + + + + + + + + + + {%- for ip in dhcp %} + + + + + + + {%- endfor %} + +
    GatewayVPNbatXRange
    {{ ip["name"] }}{{ ip["vpnif"] }}{{ ip["batif"] }}{{ ip["dhcpstart"] }} - {{ ip["dhcpend"] }}
    +
    +
    +
    +
    +
    +
    IPv4 List
    +
    + + + + + + + + + + + + {%- for ip in ipv4 %} + + + + + + {%- if ip["mac"] %} + + {%- else %} + + {%- endif %} + + {%- endfor %} + +
    GatewayVPNbatXIPv4Stat
    {{ ip["name"] }}{{ ip["vpnif"] }}{{ ip["batif"] }}{{ ip["ipv4"] }}Stats 
    +
    +
    +
    +
    IPv6 List
    +
    + + + + + + + + + + + + {%- for ip in ipv6 %} + + + + + + {%- if ip["mac"] %} + + {%- else %} + + {%- endif %} + + {%- endfor %} + +
    GatewayVPNbatXIPv6Stat
    {{ ip["name"] }}{{ ip["vpnif"] }}{{ ip["batif"] }}{{ ip["ipv6"]|longip }}Stats 
    +
    +
    +
    +
    + +{% endblock %}